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;
85 const char *file = NULL;
86 int file_len __attribute__((unused)) = 0;
89 mkfp = media_stream_kind_properties(ms).fprops;
90 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
91 ALLOCA, (file, file_len), Qnil);
93 #if defined HAVE_SOX_OPEN_READ_3ARGS
94 ft = sxe_sox_open_read(file, NULL, NULL);
95 #elif defined HAVE_SOX_OPEN_READ_4ARGS
96 ft = sxe_sox_open_read(file, NULL, NULL, NULL);
98 # error You shouldnt be here. Wake up before you try to compile me.
104 /* not yet handable */
112 media_stream_set_meths(ms, NULL);
113 media_stream_driver(ms) = MDRIVER_UNKNOWN;
117 /* retrieve the signal information */
118 #if defined HAVE_STRUCT_SOX_FORMAT_T
119 stinfo = &ft->signal;
121 # error "What's the matter with you?! How did you reach this?"
124 /* create a substream */
125 mss = make_media_substream_append(ms);
126 media_substream_type(mss) = MTYPE_AUDIO;
127 mtap = xnew_and_zero(mtype_audio_properties);
129 mtap->channels = stinfo->channels;
130 mtap->samplerate = stinfo->rate;
132 /* try to find a read function */
133 #if defined HAVE_SOX_SIGNALINFO_T_PRECISION
134 mtap->samplewidth = stinfo->precision;
135 mtap->framesize = mtap->channels * (stinfo->precision / 8);
137 switch (stinfo->size) {
139 mtap->samplewidth = 8;
140 mtap->framesize = mtap->channels;
143 mtap->samplewidth = 16;
144 mtap->framesize = mtap->channels * 2;
147 mtap->samplewidth = 24;
148 mtap->framesize = mtap->channels * 3;
151 mtap->samplewidth = 32;
152 mtap->framesize = mtap->channels * 4;
155 mtap->samplewidth = 64;
156 mtap->framesize = mtap->channels * 8;
159 mtap->samplewidth = 32;
160 mtap->framesize = mtap->channels * 4;
164 /* since SoX internally uses S32, we bang from S32 */
165 mtap->msf = sxe_msf_S32;
167 mtap->samplewidth = 8 * sizeof(float);
168 mtap->framesize = mtap->channels * sizeof(float);
172 mtap->endianness = 0;
175 media_substream_type_properties(mss).aprops = mtap;
176 media_stream_set_meths(ms, media_sox);
178 /* keep the sox handle */
179 media_stream_data(ms) = ft;
180 media_substream_data(mss) = ft;
182 /* set me as driver indicator */
183 media_stream_driver(ms) = MYSELF;
189 media_sox_close(ms_driver_data_t arg)
194 SOX_DEBUG("closing SoX handle: 0x%lx\n",
195 (unsigned long int)ft);
202 media_sox_read(media_substream *mss, void *outbuf, size_t length)
204 /* read at most `length' frames into `outbuf' */
206 Lisp_Media_Stream *ms = mss->up;
207 mtype_audio_properties *mtap;
210 sxe_sox_ssize_t samples;
211 sxe_sox_sample_t *bptr;
212 uint16_t framesize __attribute__((unused));
213 media_sample_format_t *fmt;
215 /* check the integrity of the media stream */
216 if (media_stream_driver(ms) != MYSELF)
218 if (media_substream_type(mss) != MTYPE_AUDIO)
221 /* fetch the context and our audio props */
222 if (!(ft = media_stream_data(ms)))
224 if (!(mtap = media_substream_type_properties(mss).aprops))
227 framesize = mtap->framesize;
230 bptr = (sxe_sox_sample_t*)outbuf;
231 samples = sxe_sox_read(ft, bptr, mtap->channels*length);
233 SOX_DEBUG_S("SoX handle: 0x%lx read %zd samples\n",
234 (unsigned long int)ft, samples);
239 /* always convert to internal format */
240 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, samples);
242 /* return number of frames */
243 return samples/mtap->channels;
247 media_sox_rewind(media_substream *mss)
249 /* rewind the stream to the first frame */
250 Lisp_Media_Stream *ms = mss->up;
254 /* check the integrity of the media stream */
255 if (media_stream_driver(ms) != MYSELF)
257 if (media_substream_type(mss) != MTYPE_AUDIO)
260 /* fetch the SNDFILE context and our audio props */
261 if (!(ft = media_stream_data(ms)))
264 SOX_DEBUG_S("rewind stream 0x%lx\n", (unsigned long int)ft);
266 /* Unfortunately it seems sex_sox_seek is broken, so we are
267 closing and reopening the stream,
269 #ifdef SXE_SOX_CAN_SEEK
270 if( sxe_sox_seek(ft, 0, SOX_SEEK_SET) == 0 ) {
273 SOX_DEBUG_S("rewind stream 0x%lx failed, trying reopen\n",
274 (unsigned long int)ft);
279 mkind_file_properties *mkfp = NULL;
280 const char *file = NULL;
281 int file_len __attribute__((unused)) = 0;
284 mkfp = media_stream_kind_properties(ms).fprops;
285 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
286 ALLOCA, (file, file_len), Qnil);
288 #if defined HAVE_SOX_OPEN_READ_3ARGS
289 ft = sxe_sox_open_read(file, NULL, NULL);
290 #elif defined HAVE_SOX_OPEN_READ_4ARGS
291 ft = sxe_sox_open_read(file, NULL, NULL, NULL);
293 # error You shouldnt be here. Wake up before you try to compile me.
298 media_stream_set_meths(ms, NULL);
299 media_stream_driver(ms) = MDRIVER_UNKNOWN;
300 SOX_DEBUG_S("could not reopen stream");
303 media_stream_data(ms) = ft;
304 media_substream_data(mss) = ft;