annotate src/libmad-0.15.1b/minimad.c @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents 545efbb81310
children
rev   line source
cannam@85 1 /*
cannam@85 2 * libmad - MPEG audio decoder library
cannam@85 3 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
cannam@85 4 *
cannam@85 5 * This program is free software; you can redistribute it and/or modify
cannam@85 6 * it under the terms of the GNU General Public License as published by
cannam@85 7 * the Free Software Foundation; either version 2 of the License, or
cannam@85 8 * (at your option) any later version.
cannam@85 9 *
cannam@85 10 * This program is distributed in the hope that it will be useful,
cannam@85 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
cannam@85 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
cannam@85 13 * GNU General Public License for more details.
cannam@85 14 *
cannam@85 15 * You should have received a copy of the GNU General Public License
cannam@85 16 * along with this program; if not, write to the Free Software
cannam@85 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
cannam@85 18 *
cannam@85 19 * $Id: minimad.c,v 1.4 2004/01/23 09:41:32 rob Exp $
cannam@85 20 */
cannam@85 21
cannam@85 22 # include <stdio.h>
cannam@85 23 # include <unistd.h>
cannam@85 24 # include <sys/stat.h>
cannam@85 25 # include <sys/mman.h>
cannam@85 26
cannam@85 27 # include "mad.h"
cannam@85 28
cannam@85 29 /*
cannam@85 30 * This is perhaps the simplest example use of the MAD high-level API.
cannam@85 31 * Standard input is mapped into memory via mmap(), then the high-level API
cannam@85 32 * is invoked with three callbacks: input, output, and error. The output
cannam@85 33 * callback converts MAD's high-resolution PCM samples to 16 bits, then
cannam@85 34 * writes them to standard output in little-endian, stereo-interleaved
cannam@85 35 * format.
cannam@85 36 */
cannam@85 37
cannam@85 38 static int decode(unsigned char const *, unsigned long);
cannam@85 39
cannam@85 40 int main(int argc, char *argv[])
cannam@85 41 {
cannam@85 42 struct stat stat;
cannam@85 43 void *fdm;
cannam@85 44
cannam@85 45 if (argc != 1)
cannam@85 46 return 1;
cannam@85 47
cannam@85 48 if (fstat(STDIN_FILENO, &stat) == -1 ||
cannam@85 49 stat.st_size == 0)
cannam@85 50 return 2;
cannam@85 51
cannam@85 52 fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0);
cannam@85 53 if (fdm == MAP_FAILED)
cannam@85 54 return 3;
cannam@85 55
cannam@85 56 decode(fdm, stat.st_size);
cannam@85 57
cannam@85 58 if (munmap(fdm, stat.st_size) == -1)
cannam@85 59 return 4;
cannam@85 60
cannam@85 61 return 0;
cannam@85 62 }
cannam@85 63
cannam@85 64 /*
cannam@85 65 * This is a private message structure. A generic pointer to this structure
cannam@85 66 * is passed to each of the callback functions. Put here any data you need
cannam@85 67 * to access from within the callbacks.
cannam@85 68 */
cannam@85 69
cannam@85 70 struct buffer {
cannam@85 71 unsigned char const *start;
cannam@85 72 unsigned long length;
cannam@85 73 };
cannam@85 74
cannam@85 75 /*
cannam@85 76 * This is the input callback. The purpose of this callback is to (re)fill
cannam@85 77 * the stream buffer which is to be decoded. In this example, an entire file
cannam@85 78 * has been mapped into memory, so we just call mad_stream_buffer() with the
cannam@85 79 * address and length of the mapping. When this callback is called a second
cannam@85 80 * time, we are finished decoding.
cannam@85 81 */
cannam@85 82
cannam@85 83 static
cannam@85 84 enum mad_flow input(void *data,
cannam@85 85 struct mad_stream *stream)
cannam@85 86 {
cannam@85 87 struct buffer *buffer = data;
cannam@85 88
cannam@85 89 if (!buffer->length)
cannam@85 90 return MAD_FLOW_STOP;
cannam@85 91
cannam@85 92 mad_stream_buffer(stream, buffer->start, buffer->length);
cannam@85 93
cannam@85 94 buffer->length = 0;
cannam@85 95
cannam@85 96 return MAD_FLOW_CONTINUE;
cannam@85 97 }
cannam@85 98
cannam@85 99 /*
cannam@85 100 * The following utility routine performs simple rounding, clipping, and
cannam@85 101 * scaling of MAD's high-resolution samples down to 16 bits. It does not
cannam@85 102 * perform any dithering or noise shaping, which would be recommended to
cannam@85 103 * obtain any exceptional audio quality. It is therefore not recommended to
cannam@85 104 * use this routine if high-quality output is desired.
cannam@85 105 */
cannam@85 106
cannam@85 107 static inline
cannam@85 108 signed int scale(mad_fixed_t sample)
cannam@85 109 {
cannam@85 110 /* round */
cannam@85 111 sample += (1L << (MAD_F_FRACBITS - 16));
cannam@85 112
cannam@85 113 /* clip */
cannam@85 114 if (sample >= MAD_F_ONE)
cannam@85 115 sample = MAD_F_ONE - 1;
cannam@85 116 else if (sample < -MAD_F_ONE)
cannam@85 117 sample = -MAD_F_ONE;
cannam@85 118
cannam@85 119 /* quantize */
cannam@85 120 return sample >> (MAD_F_FRACBITS + 1 - 16);
cannam@85 121 }
cannam@85 122
cannam@85 123 /*
cannam@85 124 * This is the output callback function. It is called after each frame of
cannam@85 125 * MPEG audio data has been completely decoded. The purpose of this callback
cannam@85 126 * is to output (or play) the decoded PCM audio.
cannam@85 127 */
cannam@85 128
cannam@85 129 static
cannam@85 130 enum mad_flow output(void *data,
cannam@85 131 struct mad_header const *header,
cannam@85 132 struct mad_pcm *pcm)
cannam@85 133 {
cannam@85 134 unsigned int nchannels, nsamples;
cannam@85 135 mad_fixed_t const *left_ch, *right_ch;
cannam@85 136
cannam@85 137 /* pcm->samplerate contains the sampling frequency */
cannam@85 138
cannam@85 139 nchannels = pcm->channels;
cannam@85 140 nsamples = pcm->length;
cannam@85 141 left_ch = pcm->samples[0];
cannam@85 142 right_ch = pcm->samples[1];
cannam@85 143
cannam@85 144 while (nsamples--) {
cannam@85 145 signed int sample;
cannam@85 146
cannam@85 147 /* output sample(s) in 16-bit signed little-endian PCM */
cannam@85 148
cannam@85 149 sample = scale(*left_ch++);
cannam@85 150 putchar((sample >> 0) & 0xff);
cannam@85 151 putchar((sample >> 8) & 0xff);
cannam@85 152
cannam@85 153 if (nchannels == 2) {
cannam@85 154 sample = scale(*right_ch++);
cannam@85 155 putchar((sample >> 0) & 0xff);
cannam@85 156 putchar((sample >> 8) & 0xff);
cannam@85 157 }
cannam@85 158 }
cannam@85 159
cannam@85 160 return MAD_FLOW_CONTINUE;
cannam@85 161 }
cannam@85 162
cannam@85 163 /*
cannam@85 164 * This is the error callback function. It is called whenever a decoding
cannam@85 165 * error occurs. The error is indicated by stream->error; the list of
cannam@85 166 * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
cannam@85 167 * header file.
cannam@85 168 */
cannam@85 169
cannam@85 170 static
cannam@85 171 enum mad_flow error(void *data,
cannam@85 172 struct mad_stream *stream,
cannam@85 173 struct mad_frame *frame)
cannam@85 174 {
cannam@85 175 struct buffer *buffer = data;
cannam@85 176
cannam@85 177 fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n",
cannam@85 178 stream->error, mad_stream_errorstr(stream),
cannam@85 179 stream->this_frame - buffer->start);
cannam@85 180
cannam@85 181 /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
cannam@85 182
cannam@85 183 return MAD_FLOW_CONTINUE;
cannam@85 184 }
cannam@85 185
cannam@85 186 /*
cannam@85 187 * This is the function called by main() above to perform all the decoding.
cannam@85 188 * It instantiates a decoder object and configures it with the input,
cannam@85 189 * output, and error callback functions above. A single call to
cannam@85 190 * mad_decoder_run() continues until a callback function returns
cannam@85 191 * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and
cannam@85 192 * signal an error).
cannam@85 193 */
cannam@85 194
cannam@85 195 static
cannam@85 196 int decode(unsigned char const *start, unsigned long length)
cannam@85 197 {
cannam@85 198 struct buffer buffer;
cannam@85 199 struct mad_decoder decoder;
cannam@85 200 int result;
cannam@85 201
cannam@85 202 /* initialize our private message structure */
cannam@85 203
cannam@85 204 buffer.start = start;
cannam@85 205 buffer.length = length;
cannam@85 206
cannam@85 207 /* configure input, output, and error functions */
cannam@85 208
cannam@85 209 mad_decoder_init(&decoder, &buffer,
cannam@85 210 input, 0 /* header */, 0 /* filter */, output,
cannam@85 211 error, 0 /* message */);
cannam@85 212
cannam@85 213 /* start decoding */
cannam@85 214
cannam@85 215 result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
cannam@85 216
cannam@85 217 /* release the decoder */
cannam@85 218
cannam@85 219 mad_decoder_finish(&decoder);
cannam@85 220
cannam@85 221 return result;
cannam@85 222 }