cannam@85: /* cannam@85: * libmad - MPEG audio decoder library cannam@85: * Copyright (C) 2000-2004 Underbit Technologies, Inc. cannam@85: * cannam@85: * This program is free software; you can redistribute it and/or modify cannam@85: * it under the terms of the GNU General Public License as published by cannam@85: * the Free Software Foundation; either version 2 of the License, or cannam@85: * (at your option) any later version. cannam@85: * cannam@85: * This program is distributed in the hope that it will be useful, cannam@85: * but WITHOUT ANY WARRANTY; without even the implied warranty of cannam@85: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the cannam@85: * GNU General Public License for more details. cannam@85: * cannam@85: * You should have received a copy of the GNU General Public License cannam@85: * along with this program; if not, write to the Free Software cannam@85: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA cannam@85: * cannam@85: * $Id: minimad.c,v 1.4 2004/01/23 09:41:32 rob Exp $ cannam@85: */ cannam@85: cannam@85: # include cannam@85: # include cannam@85: # include cannam@85: # include cannam@85: cannam@85: # include "mad.h" cannam@85: cannam@85: /* cannam@85: * This is perhaps the simplest example use of the MAD high-level API. cannam@85: * Standard input is mapped into memory via mmap(), then the high-level API cannam@85: * is invoked with three callbacks: input, output, and error. The output cannam@85: * callback converts MAD's high-resolution PCM samples to 16 bits, then cannam@85: * writes them to standard output in little-endian, stereo-interleaved cannam@85: * format. cannam@85: */ cannam@85: cannam@85: static int decode(unsigned char const *, unsigned long); cannam@85: cannam@85: int main(int argc, char *argv[]) cannam@85: { cannam@85: struct stat stat; cannam@85: void *fdm; cannam@85: cannam@85: if (argc != 1) cannam@85: return 1; cannam@85: cannam@85: if (fstat(STDIN_FILENO, &stat) == -1 || cannam@85: stat.st_size == 0) cannam@85: return 2; cannam@85: cannam@85: fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0); cannam@85: if (fdm == MAP_FAILED) cannam@85: return 3; cannam@85: cannam@85: decode(fdm, stat.st_size); cannam@85: cannam@85: if (munmap(fdm, stat.st_size) == -1) cannam@85: return 4; cannam@85: cannam@85: return 0; cannam@85: } cannam@85: cannam@85: /* cannam@85: * This is a private message structure. A generic pointer to this structure cannam@85: * is passed to each of the callback functions. Put here any data you need cannam@85: * to access from within the callbacks. cannam@85: */ cannam@85: cannam@85: struct buffer { cannam@85: unsigned char const *start; cannam@85: unsigned long length; cannam@85: }; cannam@85: cannam@85: /* cannam@85: * This is the input callback. The purpose of this callback is to (re)fill cannam@85: * the stream buffer which is to be decoded. In this example, an entire file cannam@85: * has been mapped into memory, so we just call mad_stream_buffer() with the cannam@85: * address and length of the mapping. When this callback is called a second cannam@85: * time, we are finished decoding. cannam@85: */ cannam@85: cannam@85: static cannam@85: enum mad_flow input(void *data, cannam@85: struct mad_stream *stream) cannam@85: { cannam@85: struct buffer *buffer = data; cannam@85: cannam@85: if (!buffer->length) cannam@85: return MAD_FLOW_STOP; cannam@85: cannam@85: mad_stream_buffer(stream, buffer->start, buffer->length); cannam@85: cannam@85: buffer->length = 0; cannam@85: cannam@85: return MAD_FLOW_CONTINUE; cannam@85: } cannam@85: cannam@85: /* cannam@85: * The following utility routine performs simple rounding, clipping, and cannam@85: * scaling of MAD's high-resolution samples down to 16 bits. It does not cannam@85: * perform any dithering or noise shaping, which would be recommended to cannam@85: * obtain any exceptional audio quality. It is therefore not recommended to cannam@85: * use this routine if high-quality output is desired. cannam@85: */ cannam@85: cannam@85: static inline cannam@85: signed int scale(mad_fixed_t sample) cannam@85: { cannam@85: /* round */ cannam@85: sample += (1L << (MAD_F_FRACBITS - 16)); cannam@85: cannam@85: /* clip */ cannam@85: if (sample >= MAD_F_ONE) cannam@85: sample = MAD_F_ONE - 1; cannam@85: else if (sample < -MAD_F_ONE) cannam@85: sample = -MAD_F_ONE; cannam@85: cannam@85: /* quantize */ cannam@85: return sample >> (MAD_F_FRACBITS + 1 - 16); cannam@85: } cannam@85: cannam@85: /* cannam@85: * This is the output callback function. It is called after each frame of cannam@85: * MPEG audio data has been completely decoded. The purpose of this callback cannam@85: * is to output (or play) the decoded PCM audio. cannam@85: */ cannam@85: cannam@85: static cannam@85: enum mad_flow output(void *data, cannam@85: struct mad_header const *header, cannam@85: struct mad_pcm *pcm) cannam@85: { cannam@85: unsigned int nchannels, nsamples; cannam@85: mad_fixed_t const *left_ch, *right_ch; cannam@85: cannam@85: /* pcm->samplerate contains the sampling frequency */ cannam@85: cannam@85: nchannels = pcm->channels; cannam@85: nsamples = pcm->length; cannam@85: left_ch = pcm->samples[0]; cannam@85: right_ch = pcm->samples[1]; cannam@85: cannam@85: while (nsamples--) { cannam@85: signed int sample; cannam@85: cannam@85: /* output sample(s) in 16-bit signed little-endian PCM */ cannam@85: cannam@85: sample = scale(*left_ch++); cannam@85: putchar((sample >> 0) & 0xff); cannam@85: putchar((sample >> 8) & 0xff); cannam@85: cannam@85: if (nchannels == 2) { cannam@85: sample = scale(*right_ch++); cannam@85: putchar((sample >> 0) & 0xff); cannam@85: putchar((sample >> 8) & 0xff); cannam@85: } cannam@85: } cannam@85: cannam@85: return MAD_FLOW_CONTINUE; cannam@85: } cannam@85: cannam@85: /* cannam@85: * This is the error callback function. It is called whenever a decoding cannam@85: * error occurs. The error is indicated by stream->error; the list of cannam@85: * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h) cannam@85: * header file. cannam@85: */ cannam@85: cannam@85: static cannam@85: enum mad_flow error(void *data, cannam@85: struct mad_stream *stream, cannam@85: struct mad_frame *frame) cannam@85: { cannam@85: struct buffer *buffer = data; cannam@85: cannam@85: fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n", cannam@85: stream->error, mad_stream_errorstr(stream), cannam@85: stream->this_frame - buffer->start); cannam@85: cannam@85: /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ cannam@85: cannam@85: return MAD_FLOW_CONTINUE; cannam@85: } cannam@85: cannam@85: /* cannam@85: * This is the function called by main() above to perform all the decoding. cannam@85: * It instantiates a decoder object and configures it with the input, cannam@85: * output, and error callback functions above. A single call to cannam@85: * mad_decoder_run() continues until a callback function returns cannam@85: * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and cannam@85: * signal an error). cannam@85: */ cannam@85: cannam@85: static cannam@85: int decode(unsigned char const *start, unsigned long length) cannam@85: { cannam@85: struct buffer buffer; cannam@85: struct mad_decoder decoder; cannam@85: int result; cannam@85: cannam@85: /* initialize our private message structure */ cannam@85: cannam@85: buffer.start = start; cannam@85: buffer.length = length; cannam@85: cannam@85: /* configure input, output, and error functions */ cannam@85: cannam@85: mad_decoder_init(&decoder, &buffer, cannam@85: input, 0 /* header */, 0 /* filter */, output, cannam@85: error, 0 /* message */); cannam@85: cannam@85: /* start decoding */ cannam@85: cannam@85: result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); cannam@85: cannam@85: /* release the decoder */ cannam@85: cannam@85: mad_decoder_finish(&decoder); cannam@85: cannam@85: return result; cannam@85: }