1 /* media-sox.c - analyse audio files or streams via sox
3 Copyright (C) 2006 Sebastian Freundt
5 This file is part of SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: Not in FSF. */
33 lisp.h defined UNUSED which also gets defined in some versions of SoX
34 in an incompatible fashion. We don't need that macro here...
37 #include "media-sox.h"
39 #define MYSELF MDRIVER_SOX
43 #define __SOX_DEBUG__(args...) fprintf(stderr, "SOX " args)
44 #ifndef SOX_DEBUG_FLAG
45 #define SOX_DEBUG(args...)
47 #define SOX_DEBUG(args...) __SOX_DEBUG__(args)
49 #define SOX_DEBUG_S(args...) SOX_DEBUG("[stream]: " args)
50 #define SOX_CRITICAL(args...) __SOX_DEBUG__("CRITICAL: " args)
53 DECLARE_MEDIA_DRIVER_OPEN_METH(media_sox);
54 DECLARE_MEDIA_DRIVER_CLOSE_METH(media_sox);
55 DECLARE_MEDIA_DRIVER_READ_METH(media_sox);
56 DECLARE_MEDIA_DRIVER_REWIND_METH(media_sox);
58 DEFINE_MEDIA_DRIVER_CUSTOM(media_sox,
59 media_sox_open, media_sox_close,
62 media_sox_rewind, NULL);
65 /* called from util.c::st_fail() */
71 static ms_driver_data_t
72 media_sox_open(Lisp_Media_Stream *ms)
75 mtype_audio_properties *mtap;
77 /* libsndfile stuff */
79 sxe_sox_signalinfo_t *stinfo = NULL;
82 switch (media_stream_kind(ms)) {
84 mkind_file_properties *mkfp = NULL;
89 mkfp = media_stream_kind_properties(ms).fprops;
90 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
91 ALLOCA, (file, file_len), Qnil);
92 #if defined HAVE_SOX_OPEN_READ_3ARGS
93 ft = sxe_sox_open_read(file, NULL, NULL);
94 #elif defined HAVE_SOX_OPEN_READ_4ARGS
95 ft = sxe_sox_open_read(file, NULL, NULL, NULL);
97 # error You shouldnt be here. Wake up before you try to compile me.
102 /* not yet handable */
110 media_stream_set_meths(ms, NULL);
111 media_stream_driver(ms) = MDRIVER_UNKNOWN;
115 /* retrieve the signal information */
116 #if defined HAVE_STRUCT_SOX_FORMAT
117 stinfo = &ft->signal;
118 #elif defined MEMBER_STRUCT_ST_SOUNDSTREAM_SIGNAL
119 stinfo = &ft->signal;
120 #elif defined MEMBER_STRUCT_ST_SOUNDSTREAM_INFO
123 # error "What's the matter with you?! How did you reach this?"
126 /* create a substream */
127 mss = make_media_substream_append(ms);
128 media_substream_type(mss) = MTYPE_AUDIO;
129 mtap = xnew_and_zero(mtype_audio_properties);
131 mtap->channels = stinfo->channels;
132 mtap->samplerate = stinfo->rate;
134 /* try to find a read function */
135 #if defined HAVE_SOX_SIGNALINFO_T_PRECISION
136 mtap->samplewidth = stinfo->precision;
137 mtap->framesize = mtap->channels * (stinfo->precision / 8);
139 switch (stinfo->size) {
141 mtap->samplewidth = 8;
142 mtap->framesize = mtap->channels;
145 mtap->samplewidth = 16;
146 mtap->framesize = mtap->channels * 2;
149 mtap->samplewidth = 24;
150 mtap->framesize = mtap->channels * 3;
153 mtap->samplewidth = 32;
154 mtap->framesize = mtap->channels * 4;
157 mtap->samplewidth = 64;
158 mtap->framesize = mtap->channels * 8;
161 mtap->samplewidth = 32;
162 mtap->framesize = mtap->channels * 4;
166 /* since SoX internally uses S32, we bang from S32 */
167 mtap->msf = sxe_msf_S32;
169 mtap->samplewidth = 8 * sizeof(float);
170 mtap->framesize = mtap->channels * sizeof(float);
174 mtap->endianness = 0;
177 media_substream_type_properties(mss).aprops = mtap;
178 media_stream_set_meths(ms, media_sox);
180 /* keep the sox handle */
181 media_stream_data(ms) = ft;
182 media_substream_data(mss) = ft;
184 /* set me as driver indicator */
185 media_stream_driver(ms) = MYSELF;
191 media_sox_close(ms_driver_data_t arg)
196 SOX_DEBUG("closing SoX handle: 0x%x\n",
204 media_sox_read(media_substream *mss, void *outbuf, size_t length)
206 /* read at most `length' frames into `outbuf' */
208 Lisp_Media_Stream *ms = mss->up;
209 mtype_audio_properties *mtap;
212 sxe_sox_ssize_t samples;
213 sxe_sox_sample_t *bptr;
215 media_sample_format_t *fmt;
217 /* check the integrity of the media stream */
218 if (media_stream_driver(ms) != MYSELF)
220 if (media_substream_type(mss) != MTYPE_AUDIO)
223 /* fetch the context and our audio props */
224 if (!(ft = media_stream_data(ms)))
226 if (!(mtap = media_substream_type_properties(mss).aprops))
229 framesize = mtap->framesize;
232 bptr = (sxe_sox_sample_t*)outbuf;
233 samples = sxe_sox_read(ft, bptr, mtap->channels*length);
235 SOX_DEBUG_S("read %d samples\n", samples);
240 /* always convert to internal format */
241 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, samples);
243 /* return number of frames */
244 return samples/mtap->channels;
248 media_sox_rewind(media_substream *mss)
250 /* rewind the stream to the first frame */
251 Lisp_Media_Stream *ms = mss->up;
255 /* check the integrity of the media stream */
256 if (media_stream_driver(ms) != MYSELF)
258 if (media_substream_type(mss) != MTYPE_AUDIO)
261 /* fetch the SNDFILE context and our audio props */
262 if (!(ft = media_stream_data(ms)))
265 SOX_DEBUG_S("rewind stream 0x%x\n", (unsigned int)ft);
266 sxe_sox_seek(ft, 0, SEEK_SET);