📄 madlld.c
字号:
do
{
/* The input bucket must be filled if it becomes empty or if
* it's the first execution of the loop.
*/
if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN)
{
size_t ReadSize,
Remaining;
unsigned char *ReadStart;
/* {1} libmad may not consume all bytes of the input
* buffer. If the last frame in the buffer is not wholly
* contained by it, then that frame's start is pointed by
* the next_frame member of the Stream structure. This
* common situation occurs when mad_frame_decode() fails,
* sets the stream error code to MAD_ERROR_BUFLEN, and
* sets the next_frame pointer to a non NULL value. (See
* also the comment marked {2} bellow.)
*
* When this occurs, the remaining unused bytes must be
* put back at the beginning of the buffer and taken in
* account before refilling the buffer. This means that
* the input buffer must be large enough to hold a whole
* frame at the highest observable bit-rate (currently 448
* kb/s). XXX=XXX Is 2016 bytes the size of the largest
* frame? (448000*(1152/32000))/8
*/
if(Stream.next_frame!=NULL)
{
Remaining=Stream.bufend-Stream.next_frame;
memmove(InputBuffer,Stream.next_frame,Remaining);
ReadStart=InputBuffer+Remaining;
ReadSize=INPUT_BUFFER_SIZE-Remaining;
}
else
ReadSize=INPUT_BUFFER_SIZE,
ReadStart=InputBuffer,
Remaining=0;
/* Fill-in the buffer. If an error occurs print a message
* and leave the decoding loop. If the end of stream is
* reached we also leave the loop but the return status is
* left untouched.
*/
ReadSize=fread(ReadStart,1,ReadSize,InputFp);
if(ReadSize<=0)
{
if(ferror(InputFp))
{
fprintf(stderr,"%s: read error on bitstream (%s)\n",
ProgName,strerror(errno));
Status=1;
}
if(feof(InputFp))
fprintf(stderr,"%s: end of input stream\n",ProgName);
break;
}
/* Pipe the new buffer content to libmad's stream decoder
* facility.
*/
mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
Stream.error=0;
}
/* Decode the next mpeg frame. The streams is read from the
* buffer, its constituents are break down and stored the the
* Frame structure, ready for examination/alteration or PCM
* synthesis. Decoding options are carried in the Frame
* structure from the Stream structure.
*
* Error handling: mad_frame_decode() returns a non zero value
* when an error occurs. The error condition can be checked in
* the error member of the Stream structure. A mad error is
* recoverable or fatal, the error status is checked with the
* MAD_RECOVERABLE macro.
*
* {2} When a fatal error is encountered all decoding
* activities shall be stopped, except when a MAD_ERROR_BUFLEN
* is signaled. This condition means that the
* mad_frame_decode() function needs more input to achieve
* it's work. One shall refill the buffer and repeat the
* mad_frame_decode() call. Some bytes may be left unused at
* the end of the buffer if those bytes forms an incomplete
* frame. Before refilling, the remainign bytes must be moved
* to the begining of the buffer and used for input for the
* next mad_frame_decode() invocation. (See the comments marked
* {1} earlier for more details.)
*
* Recoverable errors are caused by malformed bit-streams, in
* this case one can call again mad_frame_decode() in order to
* skip the faulty part and re-sync to the next frame.
*/
if(mad_frame_decode(&Frame,&Stream))
if(MAD_RECOVERABLE(Stream.error))
{
fprintf(stderr,"%s: recoverable frame level error (%s)\n",
ProgName,MadErrorString(&Stream));
fflush(stderr);
continue;
}
else
if(Stream.error==MAD_ERROR_BUFLEN)
continue;
else
{
fprintf(stderr,"%s: unrecoverable frame level error (%s).\n",
ProgName,MadErrorString(&Stream));
Status=1;
break;
}
/* The characteristics of the stream's first frame is printed
* on stderr. The first frame is representative of the entire
* stream.
*/
if(FrameCount==0)
if(PrintFrameInfo(stderr,&Frame.header))
{
Status=1;
break;
}
/* Accounting. The computed frame duration is in the frame
* header structure. It is expressed as a fixed point number
* whole data type is mad_timer_t. It is different from the
* samples fixed point format and unlike it, it can't directly
* be added or substracted. The timer module provides several
* functions to operate on such numbers. Be careful there, as
* some functions of mad's timer module receive some of their
* mad_timer_t arguments by value!
*/
FrameCount++;
mad_timer_add(&Timer,Frame.header.duration);
/* Once decoded the frame is synthesized to PCM samples. No errors
* are reported by mad_synth_frame();
*/
mad_synth_frame(&Synth,&Frame);
/* Synthesized samples must be converted from mad's fixed
* point number to the consumer format. Here we use unsigned
* 16 bit big endian integers on two channels. Integer samples
* are temporarily stored in a buffer that is flushed when
* full.
*/
for(i=0;i<Synth.pcm.length;i++)
{
unsigned short Sample;
/* Left channel */
Sample=MadFixedToUshort(Synth.pcm.samples[0][i]);
*(OutputPtr++)=Sample>>8;
*(OutputPtr++)=Sample&0xff;
/* Right channel. If the decoded stream is monophonic then
* the right output channel is the same as the left one.
*/
if(MAD_NCHANNELS(&Frame.header)==2)
Sample=MadFixedToUshort(Synth.pcm.samples[1][i]);
*(OutputPtr++)=Sample>>8;
*(OutputPtr++)=Sample&0xff;
/* Flush the buffer if it is full. */
if(OutputPtr==OutputBufferEnd)
{
if(fwrite(OutputBuffer,1,OUTPUT_BUFFER_SIZE,OutputFp)!=OUTPUT_BUFFER_SIZE)
{
fprintf(stderr,"%s: PCM write error (%s).\n",
ProgName,strerror(errno));
Status=2;
break;
}
OutputPtr=OutputBuffer;
}
}
}while(1);
/* Mad is no longer used, the structures that were initialized must
* now be cleared.
*/
mad_synth_finish(&Synth);
mad_frame_finish(&Frame);
mad_stream_finish(&Stream);
/* If the output buffer is not empty and no error occured during
* the last write, then flush it.
*/
if(OutputPtr!=OutputBuffer && Status!=2)
{
size_t BufferSize=OutputPtr-OutputBuffer;
if(fwrite(OutputBuffer,1,BufferSize,OutputFp)!=BufferSize)
{
fprintf(stderr,"%s: PCM write error (%s).\n",
ProgName,strerror(errno));
Status=2;
}
}
/* Accounting report if no error occured. */
if(!Status)
{
char Buffer[80];
/* The duration timer is converted to a human readable string
* with the versatile but still constrained mad_timer_string()
* function, in a fashion not unlike strftime(). The main
* difference is that the timer is break-down into several
* values according some of it's arguments. The units and
* fracunits arguments specify the intended conversion to be
* executed.
*
* The conversion unit (MAD_UNIT_MINUTES in our example) also
* specify the order and kind of conversion specifications
* that can be used in the format string.
*
* It is best to examine mad's timer.c source-code for details
* of the available units, fraction of units, their meanings,
* the format arguments, etc.
*/
mad_timer_string(Timer,Buffer,"%lu:%02lu.%03u",
MAD_UNITS_MINUTES,MAD_UNITS_MILLISECONDS,0);
fprintf(stderr,"%s: %lu frames decoded (%s).\n",
ProgName,FrameCount,Buffer);
}
/* That's the end of the world (in the H. G. Wells way). */
return(Status);
}
/****************************************************************************
* Program entry point. *
****************************************************************************/
int main2(int argc, char *argv[])
{
char *cptr;
int Status;
/* Keep this for error messages. */
cptr=strrchr(argv[0],'/');
if(cptr==NULL)
ProgName=argv[0];
else
ProgName=cptr+1;
/* Decode stdin to stdout. */
Status=MpegAudioDecoder(stdin,stdout);
if(Status)
fprintf(stderr,"%s: an error occured during decoding.\n",ProgName);
/* All done. */
return(Status);
}
/*
* Local Variables:
* tab-width: 4
* End:
*/
/****************************************************************************
* End of file madllc.c *
****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -