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;
120 mkfp = media_stream_kind_properties(ms).fprops;
121 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
122 ALLOCA, (file, file_len), Qnil);
123 /* read in the file */
124 f = fopen(file, "rb");
126 media_stream_set_meths(ms, NULL);
127 media_stream_driver(ms) = MDRIVER_UNKNOWN;
132 fseek(f, 0, SEEK_END);
134 fseek(f, 0, SEEK_SET);
136 /* now copy into media_data structure */
137 sd->data = xmalloc_atomic(file_len+1);
139 sd->length = file_len;
141 /* THIS IS VEEEEEERY BAD! */
142 if (fread(sd->data, sizeof(char), file_len, f) < file_len)
143 MAD_DEBUG("could not read complete file\n");
146 /* store the filesize */
147 mkfp->filesize = file_len;
151 mkind_string_properties *mksp = NULL;
153 /* prepare our user_data */
154 mksp = media_stream_kind_properties(ms).sprops;
155 sd->length = mksp->size;
157 sd->data = mksp->stream_data;
165 case NUMBER_OF_MEDIA_KINDS:
170 /* now initialise our decoder struct */
171 madd->synth = xnew_and_zero(struct mad_synth);
172 madd->stream = xnew_and_zero(struct mad_stream);
173 madd->frame = xnew_and_zero(struct mad_frame);
175 mad_synth_init(madd->synth);
176 mad_stream_init(madd->stream);
177 mad_frame_init(madd->frame);
179 mad_stream_buffer(madd->stream, (unsigned char*)sd->data, sd->length);
180 madd->have_frame = (mad_frame_decode(madd->frame, madd->stream) == 0);
181 if (!madd->have_frame) {
182 media_stream_set_meths(ms, NULL);
183 media_stream_driver(ms) = MDRIVER_UNKNOWN;
184 media_mad_close(madd);
190 /* create a substream */
191 mss = make_media_substream_append(ms);
193 media_substream_type(mss) = MTYPE_AUDIO;
194 mtap = xnew_and_zero(mtype_audio_properties);
196 mtap->channels = (madd->frame->header.mode ==
197 MAD_MODE_SINGLE_CHANNEL) ? 1 : 2;
198 mtap->samplerate = madd->frame->header.samplerate;
199 mtap->bitrate = madd->frame->header.bitrate;
200 mtap->samplewidth = 16;
201 mtap->framesize = mtap->channels * 2;
202 mtap->msf = sxe_msf_MAD;
203 mtap->endianness = 0;
206 media_substream_type_properties(mss).aprops = mtap;
207 media_stream_set_meths(ms, media_mad);
209 /* keep the SNDFILE context */
210 media_stream_data(ms) = madd;
211 media_substream_data(mss) = madd;
212 /* set me as driver indicator */
213 media_stream_driver(ms) = MYSELF;
219 /* utility to scale and round samples to 16 bits */
221 DEFINE_MEDIA_SAMPLE_FORMAT_SIMPLE(sxe_msf_MAD);
224 sxe_msf_MAD_up(void *d, void *s, size_t len)
226 /* convert MAD samples to internal format (S24in32) */
229 mad_fixed_t *src = s;
231 /* len is the number of samples (== #frame * #channels) */
232 MEDIA_DEBUG_FMT("upsampling MAD->internal: %u samples\n", len);
234 for (i = len-1; i >= 0; i--) {
235 src[i] += (1L << (MAD_F_FRACBITS - 24));
236 if (src[i] >= MAD_F_ONE)
237 src[i] = MAD_F_ONE - 1;
238 else if (src[i] < -MAD_F_ONE)
241 dst[i] = (int32_t)(src[i] >> (MAD_F_FRACBITS + 1 - 24));
248 sxe_msf_MAD_down(void *d, void *s, size_t len)
250 /* len is the number of samples (== #frame * #channels) */
251 MEDIA_DEBUG_FMT("downsampling internal->MAD: %u samples\n", len);
253 MAD_CRITICAL(".oO{ Which Id10T called this?! }\n");
260 media_mad_read(media_substream *mss, void *outbuf, size_t length)
262 /* read at most `length' frames into `outbuf' */
264 Lisp_Media_Stream *ms = mss->up;
265 mtype_audio_properties *mtap;
266 /* libsndfile stuff */
267 mad_decoder_t *madd = NULL;
268 struct mad_stream *mads = NULL;
269 struct mad_frame *madf = NULL;
270 struct mad_synth *mady = NULL;
274 mad_fixed_t *tmpbuf = (mad_fixed_t*)outbuf;
276 /* check the integrity of the media stream */
277 if (media_stream_driver(ms) != MYSELF)
279 if (media_substream_type(mss) != MTYPE_AUDIO)
283 /* fetch the decoder context and our audio props */
284 if (!(madd = media_stream_data(ms)))
286 if (!(mtap = media_substream_type_properties(mss).aprops))
289 /* fetch framesize */
290 framesize = mtap->framesize;
297 MAD_DEBUG("req:%d\n", length);
298 while (size <= length) {
299 unsigned int nchannels, nframes;
300 mad_fixed_t const *left_ch, *right_ch;
301 struct mad_pcm *pcm = &mady->pcm;
303 if (!madd->have_frame) {
304 MAD_DEBUG_DEC("no frames atm, fetching new ones\n");
305 madd->have_frame = (mad_frame_decode(madf, mads) == 0);
307 if (!madd->have_frame) {
308 MAD_DEBUG_DEC("no frames there :(\n");
312 mad_synth_frame(mady, madf);
314 nchannels = pcm->channels;
315 nframes = pcm->length;
316 left_ch = pcm->samples[0];
317 right_ch = pcm->samples[1];
321 MAD_DEBUG_S("frames: %d, samples: %d, size:%d\n",
322 nframes, nframes*nchannels, size);
324 if (nchannels == 2) {
326 *tmpbuf++ = *left_ch++;
327 *tmpbuf++ = *right_ch++;
329 } else if (nchannels == 1) {
331 *tmpbuf++ = *left_ch++;
334 madd->have_frame = 0;
337 /* upsample the thing */
338 MEDIA_SAMPLE_FORMAT_UPSAMPLE(sxe_msf_MAD)(
339 outbuf, outbuf, size*mtap->channels);
345 media_mad_rewind(media_substream *mss)
347 /* rewind the stream to the first frame */
350 Lisp_Media_Stream *ms = mss->up;
351 unsigned char *sdd = NULL;
354 /* check the integrity of the media stream */
355 if (media_stream_driver(ms) != MYSELF)
358 /* fetch the format context */
359 if (!(madd = media_stream_data(ms)))
362 sdd = (unsigned char*)madd->sd->data;
363 sdl = madd->sd->length;
365 /* ... and reset the stream */
367 mad_synth_init(madd->synth);
368 mad_stream_init(madd->stream);
369 mad_frame_init(madd->frame);
371 mad_stream_buffer(madd->stream, sdd, sdl);