📄 mp3decode.cpp
字号:
}
/* Pipe the new buffer content to libmad's stream decoder
* facility.
*/
mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
Stream.error=MAD_ERROR_NONE;
}
/* 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.
*
* {4} 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
* {2} 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))
{
// char s[300];
// sprintf(s,"%s: recoverable frame level error (%s)\n",
// ProgName,MadErrorString(&Stream));
// fprintf(stderr,"%s: recoverable frame level error (%s)\n",
// ProgName,MadErrorString(&Stream));
// fflush(stderr);
return 0;//Stream.error;
}
else
if(Stream.error==MAD_ERROR_BUFLEN)
return 0;//MAD_ERROR_BUFLEN;
else
{
// fprintf(stderr,"%s: unrecoverable frame level error (%s).\n",
// ProgName,MadErrorString(&Stream));
Status=1;
return -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;
// return 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);
/* Between the frame decoding and samples synthesis we can
* perform some operations on the audio data. We do this only
* if some processing was required. Detailed explanations are
* given in the ApplyFilter() function.
*/
// if(DoFilter)
ApplyFilter(&Frame);
/* Once decoded the frame is synthesized to PCM samples. No errors
* are reported by mad_synth_frame();
*/
Frame.options |= MAD_OPTION_IGNORECRC;
if(Frame.header.samplerate>=iResampleRate*2)
Frame.options |= MAD_OPTION_HALFSAMPLERATE;
mad_synth_frame(&Synth,&Frame);
int samplerate=Synth.pcm.samplerate;
{
resample_state resample;
resample_init(&resample,samplerate,iResampleRate);
int iLen=resample_block(&resample, Synth.pcm.length, Synth.pcm.samples[0], &OutputPtr[iOutputBufferLength[iOutputBufferCurrent]]);
iOutputBufferLength[iOutputBufferCurrent]+=iLen;
// iSoundBuf2[iOutputBufferCurrent]->SetLength(iOutputBufferLength[iOutputBufferCurrent]*2);
}
/* 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.
*/
// int i;
// iOutputBufferLength[iOutputBufferCurrent]=Synth.pcm.length;
// iSoundBuf2[iOutputBufferCurrent]->SetLength(iOutputBufferLength[iOutputBufferCurrent]*2);
// for(i=0;i<Synth.pcm.length;i++)
// {
// signed short Sample;
/* Left channel */
// Sample=MP3FixedToShort/*MadFixedToSshort*/(Synth.pcm.samples[0][i]);
// *(OutputPtr++)=Sample;
// *(OutputPtr++)=(Sample>>0)&0xff;
// *(OutputPtr++)=(Sample>>8)&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=MP3FixedToShort/*MadFixedToSshort*/(Synth.pcm.samples[1][i]);
// *(OutputPtr++)=Sample;
// *(OutputPtr++)=(Sample>>0)&0xff;
// *(OutputPtr++)=(Sample>>8)&0xff;
/* Flush the output buffer if it is full. */
/* if(OutputPtr==OutputBufferEnd)
{
if(fwrite(OutputBuffer,1,OUTPUT_BUFFER_SIZE,fw)!=OUTPUT_BUFFER_SIZE)
{
// fprintf(stderr,"%s: PCM write error (%s).\n",
// ProgName,strerror(errno));
Status=2;
return 1;
// break;
}
OutputPtr=OutputBuffer;
}*/
// }
}
return 0;
}
void CMP3Decode::ApplyFilter(mad_frame *Frame)
{
//mono
if (Frame->header.mode != MAD_MODE_SINGLE_CHANNEL)
{
unsigned int ns, s, sb;
mad_fixed_t left, right;
ns = MAD_NSBSAMPLES(&Frame->header);
for (s = 0; s < ns; ++s)
{
for (sb = 0; sb < 32; ++sb)
{
left = Frame->sbsample[0][s][sb];
right = Frame->sbsample[1][s][sb];
Frame->sbsample[0][s][sb] = (left + right) / 2;
// Frame->sbsample[0][s][sb] = mad_f_div(left + right,mad_f_tofixed(2));
// Frame->sbsample[0][s][sb] = Frame->sbsample[1][s][sb];
// frame->sbsample[1][s][sb] = 0;
}
}
Frame->header.mode = MAD_MODE_SINGLE_CHANNEL;
}
//Frame->header.mode = MAD_MODE_SINGLE_CHANNEL;
int Channel,
Sample,
Samples,
SubBand;
/* There is two application loops, each optimized for the number
* of audio channels to process. The first alternative is for
* two-channel frames, the second is for mono-audio.
*/
mad_fixed_t *Filter=iEqualizer;
Samples=MAD_NSBSAMPLES(&Frame->header);
if(Frame->header.mode!=MAD_MODE_SINGLE_CHANNEL)
for(Channel=0;Channel<2;Channel++)
for(Sample=0;Sample<Samples;Sample++)
for(SubBand=0;SubBand<32;SubBand++)
Frame->sbsample[Channel][Sample][SubBand]=
mad_f_mul(Frame->sbsample[Channel][Sample][SubBand],
Filter[SubBand]);
else
for(Sample=0;Sample<Samples;Sample++)
for(SubBand=0;SubBand<32;SubBand++)
Frame->sbsample[0][Sample][SubBand]=
mad_f_mul(Frame->sbsample[0][Sample][SubBand],
Filter[SubBand]);
}
signed int CMP3Decode::MP3FixedToShort(mad_fixed_t sample)
{
/* round */
sample += (1L << (MAD_F_FRACBITS - 16));
/* clip */
if (sample >= MAD_F_ONE)
sample = MAD_F_ONE - 1;
else if (sample < -MAD_F_ONE)
sample = -MAD_F_ONE;
/* quantize */
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
int CMP3Decode::resample_init(resample_state *state, unsigned int oldrate, unsigned int newrate)
{
mad_fixed_t ratio;
if (newrate == 0)
return -1;
ratio = mad_f_div(oldrate, newrate);
if (ratio <= 0 || ratio > MAX_RESAMPLEFACTOR * MAD_F_ONE)
return -1;
state->ratio = ratio;
state->step = 0;
state->last = 0;
return 0;
}
unsigned int CMP3Decode::resample_block(resample_state *state, unsigned int nsamples, const mad_fixed_t *old, TInt16 *newb)
{
mad_fixed_t const *end;
TInt16 *begin;
/*
* This resampling algorithm is based on a linear interpolation, which is
* not at all the best sounding but is relatively fast and efficient.
*
* A better algorithm would be one that implements a bandlimited
* interpolation.
*/
if (state->ratio == MAD_F_ONE)
{
unsigned int i;
for(i=0;i<nsamples;i++)
{
signed short Sample;
/* Left channel */
Sample=MP3FixedToShort/*MadFixedToSshort*/(old[i]);
(*newb++)=Sample;
}
// memcpy(newb, old, nsamples * sizeof(mad_fixed_t));
// return nsamples;
}
end = old + nsamples;
begin = newb;
if (state->step < 0)
{
state->step = mad_f_fracpart(-state->step);
while (state->step < MAD_F_ONE)
{
*newb++ = MP3FixedToShort (state->step ? state->last + mad_f_mul(*old - state->last, state->step) : state->last);
state->step += state->ratio;
if (((state->step + 0x00000080L) & 0x0fffff00L) == 0)
state->step = (state->step + 0x00000080L) & ~0x0fffffffL;
}
state->step -= MAD_F_ONE;
}
while (end - old > 1 + mad_f_intpart(state->step))
{
old += mad_f_intpart(state->step);
state->step = mad_f_fracpart(state->step);
*newb++ = MP3FixedToShort (state->step ? *old + mad_f_mul(old[1] - old[0], state->step) : *old);
state->step += state->ratio;
if (((state->step + 0x00000080L) & 0x0fffff00L) == 0)
state->step = (state->step + 0x00000080L) & ~0x0fffffffL;
}
if (end - old == 1 + mad_f_intpart(state->step))
{
state->last = end[-1];
state->step = -state->step;
}
else
state->step -= mad_f_fromint(end - old);
return newb - begin;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -