📄 mp3dec.c.svn-base
字号:
* * Description: zero out pcm buffer if error decoding MP3 frame * * Inputs: mp3DecInfo struct with correct frame size parameters filled in * pointer pcm output buffer * * Outputs: zeroed out pcm buffer * * Return: none **************************************************************************************/static void MP3ClearBadFrame(MP3DecInfo *mp3DecInfo, short *outbuf){ int i; if (!mp3DecInfo) return; for (i = 0; i < mp3DecInfo->nGrans * mp3DecInfo->nGranSamps * mp3DecInfo->nChans; i++) outbuf[i] = 0;}/************************************************************************************** * Function: MP3Decode * * Description: decode one frame of MP3 data * * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) * double pointer to buffer of MP3 data (containing headers + mainData) * number of valid bytes remaining in inbuf * pointer to outbuf, big enough to hold one frame of decoded PCM samples * flag indicating whether MP3 data is normal MPEG format (useSize = 0) * or reformatted as "self-contained" frames (useSize = 1) * * Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo * number of output samples = nGrans * nGranSamps * nChans * updated inbuf pointer, updated bytesLeft * * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error) * * Notes: switching useSize on and off between frames in the same stream * is not supported (bit reservoir is not maintained if useSize on) **************************************************************************************/int MP3Decode(HMP3Decoder hMP3Decoder, unsigned char **inbuf, int *bytesLeft, short *outbuf, int useSize){ int offset, bitOffset, mainBits, gr, ch, fhBytes, siBytes, freeFrameBytes; int prevBitOffset, sfBlockBits, huffBlockBits; unsigned char *mainPtr; MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; #ifdef PROFILE long time; #endif if (!mp3DecInfo) return ERR_MP3_NULL_POINTER; /* unpack frame header */ fhBytes = UnpackFrameHeader(mp3DecInfo, *inbuf); if (fhBytes < 0) return ERR_MP3_INVALID_FRAMEHEADER; /* don't clear outbuf since we don't know size (failed to parse header) */ *inbuf += fhBytes; #ifdef PROFILE time = systime_get();#endif /* unpack side info */ siBytes = UnpackSideInfo(mp3DecInfo, *inbuf); if (siBytes < 0) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_SIDEINFO; } *inbuf += siBytes; *bytesLeft -= (fhBytes + siBytes);#ifdef PROFILE time = systime_get() - time; printf("UnpackSideInfo: %i ms\n", time);#endif /* if free mode, need to calculate bitrate and nSlots manually, based on frame size */ if (mp3DecInfo->bitrate == 0 || mp3DecInfo->freeBitrateFlag) { if (!mp3DecInfo->freeBitrateFlag) { /* first time through, need to scan for next sync word and figure out frame size */ mp3DecInfo->freeBitrateFlag = 1; mp3DecInfo->freeBitrateSlots = MP3FindFreeSync(*inbuf, *inbuf - fhBytes - siBytes, *bytesLeft); if (mp3DecInfo->freeBitrateSlots < 0) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_FREE_BITRATE_SYNC; } freeFrameBytes = mp3DecInfo->freeBitrateSlots + fhBytes + siBytes; mp3DecInfo->bitrate = (freeFrameBytes * mp3DecInfo->samprate * 8) / (mp3DecInfo->nGrans * mp3DecInfo->nGranSamps); } mp3DecInfo->nSlots = mp3DecInfo->freeBitrateSlots + CheckPadBit(mp3DecInfo); /* add pad byte, if required */ } /* useSize != 0 means we're getting reformatted (RTP) packets (see RFC 3119) * - calling function assembles "self-contained" MP3 frames by shifting any main_data * from the bit reservoir (in previous frames) to AFTER the sync word and side info * - calling function should set mainDataBegin to 0, and tell us exactly how large this * frame is (in bytesLeft) */ if (useSize) { mp3DecInfo->nSlots = *bytesLeft; if (mp3DecInfo->mainDataBegin != 0 || mp3DecInfo->nSlots <= 0) { /* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */ MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_FRAMEHEADER; } /* can operate in-place on reformatted frames */ mp3DecInfo->mainDataBytes = mp3DecInfo->nSlots; mainPtr = *inbuf; *inbuf += mp3DecInfo->nSlots; *bytesLeft -= (mp3DecInfo->nSlots); } else { /* out of data - assume last or truncated frame */ if (mp3DecInfo->nSlots > *bytesLeft) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INDATA_UNDERFLOW; }#ifdef PROFILE time = systime_get();#endif /* fill main data buffer with enough new data for this frame */ if (mp3DecInfo->mainDataBytes >= mp3DecInfo->mainDataBegin) { /* adequate "old" main data available (i.e. bit reservoir) */ memmove(mp3DecInfo->mainBuf, mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes - mp3DecInfo->mainDataBegin, mp3DecInfo->mainDataBegin); memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBegin, *inbuf, mp3DecInfo->nSlots); mp3DecInfo->mainDataBytes = mp3DecInfo->mainDataBegin + mp3DecInfo->nSlots; *inbuf += mp3DecInfo->nSlots; *bytesLeft -= (mp3DecInfo->nSlots); mainPtr = mp3DecInfo->mainBuf; } else { /* not enough data in bit reservoir from previous frames (perhaps starting in middle of file) */ memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes, *inbuf, mp3DecInfo->nSlots); mp3DecInfo->mainDataBytes += mp3DecInfo->nSlots; *inbuf += mp3DecInfo->nSlots; *bytesLeft -= (mp3DecInfo->nSlots); MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_MAINDATA_UNDERFLOW; }#ifdef PROFILE time = systime_get() - time; printf("data buffer filling: %i ms\n", time);#endif } bitOffset = 0; mainBits = mp3DecInfo->mainDataBytes * 8; /* decode one complete frame */ for (gr = 0; gr < mp3DecInfo->nGrans; gr++) { for (ch = 0; ch < mp3DecInfo->nChans; ch++) { #ifdef PROFILE time = systime_get(); #endif /* unpack scale factors and compute size of scale factor block */ prevBitOffset = bitOffset; offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch); #ifdef PROFILE time = systime_get() - time; printf("UnpackScaleFactors: %i ms\n", time); #endif sfBlockBits = 8*offset - prevBitOffset + bitOffset; huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits; mainPtr += offset; mainBits -= sfBlockBits; if (offset < 0 || mainBits < huffBlockBits) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_SCALEFACT; } #ifdef PROFILE time = systime_get(); #endif /* decode Huffman code words */ prevBitOffset = bitOffset; offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch); if (offset < 0) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_HUFFCODES; } #ifdef PROFILE time = systime_get() - time; printf("Huffman: %i ms\n", time); #endif mainPtr += offset; mainBits -= (8*offset - prevBitOffset + bitOffset); } #ifdef PROFILE time = systime_get(); #endif /* dequantize coefficients, decode stereo, reorder short blocks */ if (Dequantize(mp3DecInfo, gr) < 0) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_DEQUANTIZE; } #ifdef PROFILE time = systime_get() - time; printf("Dequantize: %i ms\n", time); #endif /* alias reduction, inverse MDCT, overlap-add, frequency inversion */ for (ch = 0; ch < mp3DecInfo->nChans; ch++) { #ifdef PROFILE time = systime_get(); #endif if (IMDCT(mp3DecInfo, gr, ch) < 0) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_IMDCT; } #ifdef PROFILE time = systime_get() - time; printf("IMDCT: %i ms\n", time); #endif } #ifdef PROFILE time = systime_get(); #endif /* subband transform - if stereo, interleaves pcm LRLRLR */ if (Subband(mp3DecInfo, outbuf + gr*mp3DecInfo->nGranSamps*mp3DecInfo->nChans) < 0) { MP3ClearBadFrame(mp3DecInfo, outbuf); return ERR_MP3_INVALID_SUBBAND; } #ifdef PROFILE time = systime_get() - time; printf("Subband: %i ms\n", time); #endif } return ERR_MP3_NONE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -