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. */
32 #include "media-sox.h"
34 #define MYSELF MDRIVER_SOX
38 #define __SOX_DEBUG__(args...) fprintf(stderr, "SOX " args)
39 #ifndef SOX_DEBUG_FLAG
40 #define SOX_DEBUG(args...)
42 #define SOX_DEBUG(args...) __SOX_DEBUG__(args)
44 #define SOX_DEBUG_S(args...) SOX_DEBUG("[stream]: " args)
45 #define SOX_CRITICAL(args...) __SOX_DEBUG__("CRITICAL: " args)
48 DECLARE_MEDIA_DRIVER_OPEN_METH(media_sox);
49 DECLARE_MEDIA_DRIVER_CLOSE_METH(media_sox);
50 DECLARE_MEDIA_DRIVER_READ_METH(media_sox);
51 DECLARE_MEDIA_DRIVER_REWIND_METH(media_sox);
53 DEFINE_MEDIA_DRIVER_CUSTOM(media_sox,
54 media_sox_open, media_sox_close,
57 media_sox_rewind, NULL);
60 /* called from util.c::st_fail() */
66 static ms_driver_data_t
67 media_sox_open(Lisp_Media_Stream *ms)
70 mtype_audio_properties *mtap;
72 /* libsndfile stuff */
74 sxe_sox_signalinfo_t *stinfo = NULL;
77 switch (media_stream_kind(ms)) {
79 mkind_file_properties *mkfp = NULL;
84 mkfp = media_stream_kind_properties(ms).fprops;
85 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
86 ALLOCA, (file, file_len), Qnil);
87 #if defined HAVE_SOX_OPEN_READ_3ARGS
88 ft = sxe_sox_open_read(file, NULL, NULL);
89 #elif defined HAVE_SOX_OPEN_READ_4ARGS
90 ft = sxe_sox_open_read(file, NULL, NULL, NULL);
92 # error You shouldnt be here. Wake up before you try to compile me.
97 /* not yet handable */
105 media_stream_set_meths(ms, NULL);
106 media_stream_driver(ms) = MDRIVER_UNKNOWN;
110 /* retrieve the signal information */
111 #if defined HAVE_STRUCT_SOX_FORMAT
112 stinfo = &ft->signal;
113 #elif defined MEMBER_STRUCT_ST_SOUNDSTREAM_SIGNAL
114 stinfo = &ft->signal;
115 #elif defined MEMBER_STRUCT_ST_SOUNDSTREAM_INFO
118 # error "What's the matter with you?! How did you reach this?"
121 /* create a substream */
122 mss = make_media_substream_append(ms);
123 media_substream_type(mss) = MTYPE_AUDIO;
124 mtap = xnew_and_zero(mtype_audio_properties);
126 mtap->channels = stinfo->channels;
127 mtap->samplerate = stinfo->rate;
129 /* try to find a read function */
130 #if defined HAVE_SOX_SIGNALINFO_T_PRECISION
131 mtap->samplewidth = stinfo->precision;
132 mtap->framesize = mtap->channels * (stinfo->precision / 8);
134 switch (stinfo->size) {
136 mtap->samplewidth = 8;
137 mtap->framesize = mtap->channels;
140 mtap->samplewidth = 16;
141 mtap->framesize = mtap->channels * 2;
144 mtap->samplewidth = 24;
145 mtap->framesize = mtap->channels * 3;
148 mtap->samplewidth = 32;
149 mtap->framesize = mtap->channels * 4;
152 mtap->samplewidth = 64;
153 mtap->framesize = mtap->channels * 8;
156 mtap->samplewidth = 32;
157 mtap->framesize = mtap->channels * 4;
161 /* since SoX internally uses S32, we bang from S32 */
162 mtap->msf = sxe_msf_S32;
164 mtap->samplewidth = 8 * sizeof(float);
165 mtap->framesize = mtap->channels * sizeof(float);
169 mtap->endianness = 0;
172 media_substream_type_properties(mss).aprops = mtap;
173 media_stream_set_meths(ms, media_sox);
175 /* keep the sox handle */
176 media_stream_data(ms) = ft;
177 media_substream_data(mss) = ft;
179 /* set me as driver indicator */
180 media_stream_driver(ms) = MYSELF;
186 media_sox_close(ms_driver_data_t arg)
191 SOX_DEBUG("closing SoX handle: 0x%x\n",
199 media_sox_read(media_substream *mss, void *outbuf, size_t length)
201 /* read at most `length' frames into `outbuf' */
203 Lisp_Media_Stream *ms = mss->up;
204 mtype_audio_properties *mtap;
207 sxe_sox_ssize_t samples;
208 sxe_sox_sample_t *bptr;
210 media_sample_format_t *fmt;
212 /* check the integrity of the media stream */
213 if (media_stream_driver(ms) != MYSELF)
215 if (media_substream_type(mss) != MTYPE_AUDIO)
218 /* fetch the context and our audio props */
219 if (!(ft = media_stream_data(ms)))
221 if (!(mtap = media_substream_type_properties(mss).aprops))
224 framesize = mtap->framesize;
227 bptr = (sxe_sox_sample_t*)outbuf;
228 samples = sxe_sox_read(ft, bptr, mtap->channels*length);
230 SOX_DEBUG_S("read %d samples\n", samples);
235 /* always convert to internal format */
236 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, samples);
238 /* return number of frames */
239 return samples/mtap->channels;
243 media_sox_rewind(media_substream *mss)
245 /* rewind the stream to the first frame */
246 Lisp_Media_Stream *ms = mss->up;
250 /* check the integrity of the media stream */
251 if (media_stream_driver(ms) != MYSELF)
253 if (media_substream_type(mss) != MTYPE_AUDIO)
256 /* fetch the SNDFILE context and our audio props */
257 if (!(ft = media_stream_data(ms)))
260 SOX_DEBUG_S("rewind stream 0x%x\n", (unsigned int)ft);
261 sxe_sox_seek(ft, 0, SEEK_SET);