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;
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
119 stinfo = &ft->signal;
120 #elif defined MEMBER_STRUCT_ST_SOUNDSTREAM_SIGNAL
121 stinfo = &ft->signal;
122 #elif defined MEMBER_STRUCT_ST_SOUNDSTREAM_INFO
125 # error "What's the matter with you?! How did you reach this?"
128 /* create a substream */
129 mss = make_media_substream_append(ms);
130 media_substream_type(mss) = MTYPE_AUDIO;
131 mtap = xnew_and_zero(mtype_audio_properties);
133 mtap->channels = stinfo->channels;
134 mtap->samplerate = stinfo->rate;
136 /* try to find a read function */
137 #if defined HAVE_SOX_SIGNALINFO_T_PRECISION
138 mtap->samplewidth = stinfo->precision;
139 mtap->framesize = mtap->channels * (stinfo->precision / 8);
141 switch (stinfo->size) {
143 mtap->samplewidth = 8;
144 mtap->framesize = mtap->channels;
147 mtap->samplewidth = 16;
148 mtap->framesize = mtap->channels * 2;
151 mtap->samplewidth = 24;
152 mtap->framesize = mtap->channels * 3;
155 mtap->samplewidth = 32;
156 mtap->framesize = mtap->channels * 4;
159 mtap->samplewidth = 64;
160 mtap->framesize = mtap->channels * 8;
163 mtap->samplewidth = 32;
164 mtap->framesize = mtap->channels * 4;
168 /* since SoX internally uses S32, we bang from S32 */
169 mtap->msf = sxe_msf_S32;
171 mtap->samplewidth = 8 * sizeof(float);
172 mtap->framesize = mtap->channels * sizeof(float);
176 mtap->endianness = 0;
179 media_substream_type_properties(mss).aprops = mtap;
180 media_stream_set_meths(ms, media_sox);
182 /* keep the sox handle */
183 media_stream_data(ms) = ft;
184 media_substream_data(mss) = ft;
186 /* set me as driver indicator */
187 media_stream_driver(ms) = MYSELF;
193 media_sox_close(ms_driver_data_t arg)
198 SOX_DEBUG("closing SoX handle: 0x%x\n",
206 media_sox_read(media_substream *mss, void *outbuf, size_t length)
208 /* read at most `length' frames into `outbuf' */
210 Lisp_Media_Stream *ms = mss->up;
211 mtype_audio_properties *mtap;
214 sxe_sox_ssize_t samples;
215 sxe_sox_sample_t *bptr;
217 media_sample_format_t *fmt;
219 /* check the integrity of the media stream */
220 if (media_stream_driver(ms) != MYSELF)
222 if (media_substream_type(mss) != MTYPE_AUDIO)
225 /* fetch the context and our audio props */
226 if (!(ft = media_stream_data(ms)))
228 if (!(mtap = media_substream_type_properties(mss).aprops))
231 framesize = mtap->framesize;
234 bptr = (sxe_sox_sample_t*)outbuf;
235 samples = sxe_sox_read(ft, bptr, mtap->channels*length);
237 SOX_DEBUG_S("read %d samples\n", samples);
242 /* always convert to internal format */
243 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, samples);
245 /* return number of frames */
246 return samples/mtap->channels;
250 media_sox_rewind(media_substream *mss)
252 /* rewind the stream to the first frame */
253 Lisp_Media_Stream *ms = mss->up;
257 /* check the integrity of the media stream */
258 if (media_stream_driver(ms) != MYSELF)
260 if (media_substream_type(mss) != MTYPE_AUDIO)
263 /* fetch the SNDFILE context and our audio props */
264 if (!(ft = media_stream_data(ms)))
267 SOX_DEBUG_S("rewind stream 0x%x\n", (unsigned int)ft);
268 sxe_sox_seek(ft, 0, SEEK_SET);