1 /* media-mad.c - analyse audio files or streams
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. */
37 #include "media-mad.h"
39 #define MYSELF MDRIVER_MAD
43 #define __MAD_DEBUG__(args...) fprintf(stderr, "MAD " args)
44 #ifndef MAD_DEBUG_FLAG
45 #define MAD_DEBUG(args...)
47 #define MAD_DEBUG(args...) __MAD_DEBUG__(args)
49 #define MAD_DEBUG_S(args...) MAD_DEBUG("[stream]: " args)
50 #define MAD_DEBUG_DEC(args...) MAD_DEBUG("[decoder]: " args)
51 #define MAD_CRITICAL(args...) __MAD_DEBUG__("CRITICAL: " args)
54 DECLARE_MEDIA_DRIVER_OPEN_METH(media_mad);
55 DECLARE_MEDIA_DRIVER_CLOSE_METH(media_mad);
56 DECLARE_MEDIA_DRIVER_READ_METH(media_mad);
57 DECLARE_MEDIA_DRIVER_REWIND_METH(media_mad);
59 DEFINE_MEDIA_DRIVER_CUSTOM(media_mad,
60 media_mad_open, media_mad_close,
63 media_mad_rewind, NULL);
65 DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_MAD);
69 media_mad_close(ms_driver_data_t data)
71 mad_decoder_t *madd = data;
73 MAD_DEBUG_DEC("closing decoder handle: 0x%x\n",
98 static ms_driver_data_t
99 media_mad_open(Lisp_Media_Stream *ms)
101 media_substream *mss;
102 mtype_audio_properties *mtap;
104 mad_decoder_t *madd = NULL;
105 media_data *sd = NULL;
108 sd = xnew_and_zero(media_data);
109 madd = xnew_and_zero(mad_decoder_t);
111 switch (media_stream_kind(ms)) {
113 mkind_file_properties *mkfp = NULL;
114 const char *file = NULL;
120 mkfp = media_stream_kind_properties(ms).fprops;
121 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
122 ALLOCA, (file, file_len), Qnil);
123 if ( file != NULL ) {
124 /* read in the file */
125 f = fopen(file, "rb");
128 media_stream_set_meths(ms, NULL);
129 media_stream_driver(ms) = MDRIVER_UNKNOWN;
134 fseek(f, 0, SEEK_END);
138 media_stream_set_meths(ms, NULL);
139 media_stream_driver(ms) = MDRIVER_UNKNOWN;
144 fseek(f, 0, SEEK_SET);
146 /* now copy into media_data structure */
147 sd->data = xmalloc_atomic(file_len+1);
149 sd->length = (size_t)file_len;
151 /* THIS IS VEEEEEERY BAD! */
152 if (fread(sd->data, sizeof(char), file_len, f) < file_len)
153 MAD_DEBUG("could not read complete file\n");
156 /* store the filesize */
157 mkfp->filesize = file_len;
161 mkind_string_properties *mksp = NULL;
163 /* prepare our user_data */
164 mksp = media_stream_kind_properties(ms).sprops;
165 sd->length = mksp->size;
167 sd->data = mksp->stream_data;
175 case NUMBER_OF_MEDIA_KINDS:
180 /* now initialise our decoder struct */
181 madd->synth = xnew_and_zero(struct mad_synth);
182 madd->stream = xnew_and_zero(struct mad_stream);
183 madd->frame = xnew_and_zero(struct mad_frame);
185 mad_synth_init(madd->synth);
186 mad_stream_init(madd->stream);
187 mad_frame_init(madd->frame);
189 mad_stream_buffer(madd->stream, (unsigned char*)sd->data, sd->length);
190 madd->have_frame = (mad_frame_decode(madd->frame, madd->stream) == 0);
191 if (!madd->have_frame) {
192 media_stream_set_meths(ms, NULL);
193 media_stream_driver(ms) = MDRIVER_UNKNOWN;
194 media_mad_close(madd);
201 /* create a substream */
202 mss = make_media_substream_append(ms);
204 media_substream_type(mss) = MTYPE_AUDIO;
205 mtap = xnew_and_zero(mtype_audio_properties);
207 mtap->channels = (madd->frame->header.mode ==
208 MAD_MODE_SINGLE_CHANNEL) ? 1 : 2;
209 mtap->samplerate = madd->frame->header.samplerate;
210 mtap->bitrate = madd->frame->header.bitrate;
211 mtap->samplewidth = 16;
212 mtap->framesize = mtap->channels * 2;
213 mtap->msf = sxe_msf_MAD;
214 mtap->endianness = 0;
217 media_substream_type_properties(mss).aprops = mtap;
218 media_stream_set_meths(ms, media_mad);
220 /* keep the SNDFILE context */
221 media_stream_data(ms) = madd;
222 media_substream_data(mss) = madd;
223 /* set me as driver indicator */
224 media_stream_driver(ms) = MYSELF;
230 /* utility to scale and round samples to 16 bits */
232 DEFINE_MEDIA_SAMPLE_FORMAT_SIMPLE(sxe_msf_MAD);
235 sxe_msf_MAD_up(void *d, void *s, size_t len)
237 /* convert MAD samples to internal format (S24in32) */
240 mad_fixed_t *src = s;
242 /* len is the number of samples (== #frame * #channels) */
243 MEDIA_DEBUG_FMT("upsampling MAD->internal: %u samples\n", len);
245 for (i = len-1; i >= 0; i--) {
246 src[i] += (1L << (MAD_F_FRACBITS - 24));
247 if (src[i] >= MAD_F_ONE)
248 src[i] = MAD_F_ONE - 1;
249 else if (src[i] < -MAD_F_ONE)
252 dst[i] = (int32_t)(src[i] >> (MAD_F_FRACBITS + 1 - 24));
259 sxe_msf_MAD_down(void *d, void *s, size_t len)
261 /* len is the number of samples (== #frame * #channels) */
262 MEDIA_DEBUG_FMT("downsampling internal->MAD: %u samples\n", len);
264 MAD_CRITICAL(".oO{ Which Id10T called this?! }\n");
271 media_mad_read(media_substream *mss, void *outbuf, size_t length)
273 /* read at most `length' frames into `outbuf' */
275 Lisp_Media_Stream *ms = mss->up;
276 mtype_audio_properties *mtap;
277 /* libsndfile stuff */
278 mad_decoder_t *madd = NULL;
279 struct mad_stream *mads = NULL;
280 struct mad_frame *madf = NULL;
281 struct mad_synth *mady = NULL;
285 mad_fixed_t *tmpbuf = (mad_fixed_t*)outbuf;
287 /* check the integrity of the media stream */
288 if (media_stream_driver(ms) != MYSELF)
290 if (media_substream_type(mss) != MTYPE_AUDIO)
294 /* fetch the decoder context and our audio props */
295 if (!(madd = media_stream_data(ms)))
297 if (!(mtap = media_substream_type_properties(mss).aprops))
300 /* fetch framesize */
301 framesize = mtap->framesize;
302 SXE_SET_UNUSED(framesize);
309 MAD_DEBUG("req:%d\n", length);
310 while (size <= length) {
311 unsigned int nchannels, nframes;
312 mad_fixed_t const *left_ch, *right_ch;
313 struct mad_pcm *pcm = &mady->pcm;
315 if (!madd->have_frame) {
316 MAD_DEBUG_DEC("no frames atm, fetching new ones\n");
317 madd->have_frame = (mad_frame_decode(madf, mads) == 0);
319 if (!madd->have_frame) {
320 MAD_DEBUG_DEC("no frames there :(\n");
324 mad_synth_frame(mady, madf);
326 nchannels = pcm->channels;
327 nframes = pcm->length;
328 left_ch = pcm->samples[0];
329 right_ch = pcm->samples[1];
333 MAD_DEBUG_S("frames: %d, samples: %d, size:%d\n",
334 nframes, nframes*nchannels, size);
336 if (nchannels == 2) {
338 *tmpbuf++ = *left_ch++;
339 *tmpbuf++ = *right_ch++;
341 } else if (nchannels == 1) {
343 *tmpbuf++ = *left_ch++;
346 madd->have_frame = 0;
349 /* upsample the thing */
350 MEDIA_SAMPLE_FORMAT_UPSAMPLE(sxe_msf_MAD)(
351 outbuf, outbuf, size*mtap->channels);
357 media_mad_rewind(media_substream *mss)
359 /* rewind the stream to the first frame */
362 Lisp_Media_Stream *ms = mss->up;
363 unsigned char *sdd = NULL;
366 /* check the integrity of the media stream */
367 if (media_stream_driver(ms) != MYSELF)
370 /* fetch the format context */
371 if (!(madd = media_stream_data(ms)))
374 sdd = (unsigned char*)madd->sd->data;
375 sdl = madd->sd->length;
377 /* ... and reset the stream */
379 mad_synth_init(madd->synth);
380 mad_stream_init(madd->stream);
381 mad_frame_init(madd->frame);
383 mad_stream_buffer(madd->stream, sdd, sdl);