2 * mad - MPEG audio decoder
3 * Copyright (C) 2000-2001 Robert Leslie
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * minimad.c (Simple MAD decoder) v1.13 (C) 2000-2001 Robert Leslie
23 * madlld.c (MAD low-level demonstration/decoder) v1.0p1 (C) 2001, 2002 Bertrand Petit
33 #include <proto/oss.h>
34 #include <proto/exec.h>
35 #include <proto/dos.h>
37 #define DSP_DRIVER_NAME "/dev/dsp"
38 #define SRCBUFSIZE 60000
39 #define DESTBUFSIZE 8900
43 static struct Library
*OSSBase
;
45 /* private message buffer */
53 static void cleanup(struct buffer
*buffer
);
54 static enum mad_flow
input(void *data
, struct mad_stream
*stream
);
55 static inline signed int scale(mad_fixed_t sample
);
56 static enum mad_flow
output(void *data
, struct mad_header
const *header
, struct mad_pcm
*pcm
);
57 static enum mad_flow
error(void *data
, struct mad_stream
*stream
, struct mad_frame
*frame
);
58 static const char *MadErrorString(const struct mad_stream
*Stream
);
59 static void PrintFrameInfo(struct mad_header
*Header
);
61 int main (int argc
, char *argv
[])
64 struct mad_decoder decoder
;
69 buffer
.srcbuffer
= NULL
;
70 buffer
.destbuffer
= NULL
;
71 buffer
.framecount
= 0;
74 printf ("Usage: madoss <filename>\n");
78 buffer
.srcbuffer
= AllocVec(SRCBUFSIZE
, MEMF_ANY
);
79 if (!buffer
.srcbuffer
)
81 printf ("allocvec src error\n");
86 buffer
.destbuffer
= AllocVec(DESTBUFSIZE
, MEMF_ANY
);
87 if (!buffer
.destbuffer
)
89 printf ("allocvec dest error\n");
94 buffer
.infh
= Open(argv
[1], MODE_OLDFILE
);
97 printf ("error %ld opening file\n", IoErr());
102 OSSBase
= OpenLibrary("oss.library", 0);
105 printf("Could not open oss.library\n");
110 ok
= OSS_Open(DSP_DRIVER_NAME
, FALSE
, TRUE
, TRUE
);
113 printf ("error opening DSP\n");
118 ok
= OSS_SetFormat_S16LE();
121 printf("error setting format\n");
126 /* configure input, output, and error functions */
127 mad_decoder_init(&decoder
, &buffer
,
128 input
, 0 /* header */, 0 /* filter */, output
,
129 error
, 0 /* message */);
131 mad_decoder_run(&decoder
, MAD_DECODER_MODE_SYNC
);
133 mad_decoder_finish(&decoder
);
135 printf("%d frames decoded.\n", buffer
.framecount
);
140 static void cleanup(struct buffer
*buffer
)
145 CloseLibrary(OSSBase
);
147 if(buffer
->infh
) Close(buffer
->infh
);
148 if(buffer
->srcbuffer
) FreeVec(buffer
->srcbuffer
);
149 if(buffer
->destbuffer
) FreeVec(buffer
->destbuffer
);
152 /* input function: called when more input is needed; refill stream buffer */
153 static enum mad_flow
input(void *data
, struct mad_stream
*stream
)
155 struct buffer
*buffer
= data
;
156 int readlength
, remainingbytes
;
159 //printf("1 buffer %x bufend %x thispos %d next %x buflen %d\n", stream->buffer, stream->bufend, stream->this_frame - stream->buffer, stream->next_frame, stream->bufend - stream->buffer);
160 if( stream
->next_frame
!= NULL
)
162 remainingbytes
= stream
->bufend
- stream
->next_frame
;
163 memcpy( (void*)stream
->buffer
, stream
->this_frame
, remainingbytes
);
165 else remainingbytes
= 0;
167 srcstart
= buffer
->srcbuffer
+ remainingbytes
;
168 readlength
= Read(buffer
->infh
, srcstart
, SRCBUFSIZE
- remainingbytes
);
169 printf("read %d remainingbytes %d srcstart %x\n", readlength
, remainingbytes
, (int)srcstart
);
172 printf("error reading file\n");
173 return MAD_FLOW_STOP
;
176 return MAD_FLOW_STOP
;
177 mad_stream_buffer(stream
, buffer
->srcbuffer
, readlength
+ remainingbytes
);
178 //printf("2 buffer %x bufend %x thispos %d next %x buflen %d\n", stream->buffer, stream->bufend, stream->this_frame - stream->buffer, stream->next_frame, stream->bufend - stream->buffer);
180 return MAD_FLOW_CONTINUE
;
183 /* utility to scale and round samples to 16 bits */
184 static inline signed int scale(mad_fixed_t sample
)
187 sample
+= (1L << (MAD_F_FRACBITS
- 16));
190 if (sample
>= MAD_F_ONE
)
191 sample
= MAD_F_ONE
- 1;
192 else if (sample
< -MAD_F_ONE
)
196 return sample
>> (MAD_F_FRACBITS
+ 1 - 16);
199 /* output function: called to process output */
200 static enum mad_flow
output(void *data
, struct mad_header
const *header
, struct mad_pcm
*pcm
)
202 struct buffer
*buffer
= data
;
203 unsigned int nchannels
, nsamples
;
204 mad_fixed_t
const *left_ch
, *right_ch
;
207 int written
, length
, ok
, rate
;
209 /* pcm->samplerate contains the sampling frequency */
210 nchannels
= pcm
->channels
;
211 nsamples
= pcm
->length
;
212 left_ch
= pcm
->samples
[0];
213 right_ch
= pcm
->samples
[1];
214 //printf ("nchannels %d nsamples %d left_ch %x right_ch %x\n",nchannels,nsamples,left_ch,right_ch);
216 if(buffer
->framecount
==0)
218 PrintFrameInfo((struct mad_header
*)header
);
219 ok
= OSS_SetNumChannels(nchannels
);
222 printf("error setting channels\n");
223 return MAD_FLOW_STOP
;
225 rate
= pcm
->samplerate
;
226 ok
= OSS_SetWriteRate(rate
, &rate
);
229 printf("error setting write rate\n");
230 return MAD_FLOW_STOP
;
233 buffer
->framecount
++;
238 if( length
> DESTBUFSIZE
)
240 printf("buffer overflow\n");
241 return MAD_FLOW_STOP
;
244 ptr
= buffer
->destbuffer
;
247 /* output sample(s) in 16-bit signed little-endian PCM */
248 sample
= scale(*left_ch
++);
252 sample
= scale(*right_ch
++);
257 ptr
= buffer
->destbuffer
;
260 written
= OSS_Write(ptr
, length
);
261 //printf("written %d\n", written);
264 printf ("error writing audio\n");
265 return MAD_FLOW_STOP
;
270 } while( length
> 0 );
272 return MAD_FLOW_CONTINUE
;
275 /* error function: called to handle a decoding error */
276 static enum mad_flow
error(void *data
, struct mad_stream
*stream
, struct mad_frame
*frame
)
278 //struct buffer *buffer = data;
280 printf("%srecoverable decoding error 0x%04x at byte 0x%08x (%s)\n", MAD_RECOVERABLE(stream
->error
) ? "" : "un",
281 stream
->error
, stream
->this_frame
- stream
->buffer
, MadErrorString(stream
));
283 if( MAD_RECOVERABLE(stream
->error
) )
284 return MAD_FLOW_CONTINUE
;
286 return MAD_FLOW_STOP
;
289 #if (MAD_VERSION_MAJOR>=1) || \
290 ((MAD_VERSION_MAJOR==0) && \
291 (((MAD_VERSION_MINOR==14) && \
292 (MAD_VERSION_PATCH>=2)) || \
293 (MAD_VERSION_MINOR>14)))
294 #define MadErrorString(x) mad_stream_errorstr(x)
296 static const char *MadErrorString(const struct mad_stream
*Stream
)
298 switch(Stream
->error
)
300 /* Generic unrecoverable errors. */
301 case MAD_ERROR_BUFLEN
:
302 return("input buffer too small (or EOF)");
303 case MAD_ERROR_BUFPTR
:
304 return("invalid (null) buffer pointer");
305 case MAD_ERROR_NOMEM
:
306 return("not enough memory");
308 /* Frame header related unrecoverable errors. */
309 case MAD_ERROR_LOSTSYNC
:
310 return("lost synchronization");
311 case MAD_ERROR_BADLAYER
:
312 return("reserved header layer value");
313 case MAD_ERROR_BADBITRATE
:
314 return("forbidden bitrate value");
315 case MAD_ERROR_BADSAMPLERATE
:
316 return("reserved sample frequency value");
317 case MAD_ERROR_BADEMPHASIS
:
318 return("reserved emphasis value");
320 /* Recoverable errors */
321 case MAD_ERROR_BADCRC
:
322 return("CRC check failed");
323 case MAD_ERROR_BADBITALLOC
:
324 return("forbidden bit allocation value");
325 case MAD_ERROR_BADSCALEFACTOR
:
326 return("bad scalefactor index");
327 case MAD_ERROR_BADFRAMELEN
:
328 return("bad frame length");
329 case MAD_ERROR_BADBIGVALUES
:
330 return("bad big_values count");
331 case MAD_ERROR_BADBLOCKTYPE
:
332 return("reserved block_type");
333 case MAD_ERROR_BADSCFSI
:
334 return("bad scalefactor selection info");
335 case MAD_ERROR_BADDATAPTR
:
336 return("bad main_data_begin pointer");
337 case MAD_ERROR_BADPART3LEN
:
338 return("bad audio data length");
339 case MAD_ERROR_BADHUFFTABLE
:
340 return("bad Huffman table select");
341 case MAD_ERROR_BADHUFFDATA
:
342 return("Huffman data overrun");
343 case MAD_ERROR_BADSTEREO
:
344 return("incompatible block_type for JS");
346 /* Unknown error. This swich may be out of sync with libmad's
347 * defined error codes.
350 return("Unknown error code");
355 static void PrintFrameInfo(struct mad_header
*Header
)
361 /* Convert the layer number to it's printed representation. */
362 switch(Header
->layer
)
374 Layer
="(unexpected layer value)";
378 /* Convert the audio mode to it's printed representation. */
381 case MAD_MODE_SINGLE_CHANNEL
:
382 Mode
="single channel";
384 case MAD_MODE_DUAL_CHANNEL
:
387 case MAD_MODE_JOINT_STEREO
:
388 Mode
="joint (MS/intensity) stereo";
390 case MAD_MODE_STEREO
:
391 Mode
="normal LR stereo";
394 Mode
="(unexpected mode value)";
398 /* Convert the emphasis to it's printed representation. */
399 switch(Header
->emphasis
)
401 case MAD_EMPHASIS_NONE
:
404 case MAD_EMPHASIS_50_15_US
:
407 case MAD_EMPHASIS_CCITT_J_17
:
408 Emphasis
="CCITT J.17";
411 Emphasis
="(unexpected emphasis value)";
415 printf("%lu kb/s audio mpeg layer %s stream %s crc, "
416 "%s with %s emphasis at %d Hz sample rate\n",
417 Header
->bitrate
,Layer
,
418 Header
->flags
&MAD_FLAG_PROTECTION
?"with":"without",
419 Mode
,Emphasis
,Header
->samplerate
);