📄 mp3wrap.c
字号:
// Don't leave the loop, there may be more data already available MP3DecoderNextState = searchingHeader; pBufferElement = FrameBuffer[0]; // reset last pBufferElement, not to copy the last break; } case searchingHeader: { // We are searching for the first frame header in the // compressed bistream. No data decoding happens here. Mp3DataEOF = 0; // clear Mp3DataEOPB = 0; // Update bitstream data pointers before decoding switch (MP3UpdateBitstream(MP3Bitstream_p, flag)) { case waitingForData: // not enough data return decoderWaitingFBdata; case dataEOF: // EOF Mp3DataEOF = 1; // set break; case dataReady: // data ready break; case immediateEOF: // request from Controller return decoderEOF_immediate; case dataEOPB: // end of play block (FF/FB) Mp3DataEOPB = 1; // to wrap and start header decoding again break; } ret = MP3DecodeHeader(MP3DecoderHandle, MP3Scratch_p, MP3Bitstream_p); //modify dataOffset externally if >1 to 1 in 2 special cases: // 1) in case of error, try one byte further, not per 4 bytes (dataOffset) as ARM library wants - bug in ARM lib // 2) in case of no_error (so valid header found), check 3 params: sample rate, chan.num. and bistream type if (((ret != kDecoderStatus_NoError) && (ret != kDecoderStatus_MoreData)) //is error || ((ret == kDecoderStatus_NoError) //no error &&((MP3Bitstream_p->sampleRate != CurrentSampling_fr) //wrong sampl. rate || (MP3Bitstream_p->channels.total != CurrentCh_num) //wrong chan. num. || (MP3Bitstream_p->bitstreamType != CurrentBistreamType)))) //wrong layer type { if(MP3Bitstream_p->dataOffset > 1) { //scan per bytes MP3Bitstream_p->dataOffset = 1; //dprintf("dataOffset forced to 1\r\n"); } } // set number of DECODED bytes SetDecodedBytes(MP3Bitstream_p->dataLength - MP3Bitstream_p->dataOffset); //decoderDecodedBytes = decoderReadBytes - (MP3Bitstream_p->dataLength - MP3Bitstream_p->dataOffset); //clear used FB elements FB_clearFrom = GetElementNumber((unsigned char *)(MP3Bitstream_p->data)); FB_clearTill = GetElementNumber((unsigned char *) (MP3Bitstream_p->data + MP3Bitstream_p->dataOffset)); SetEmptyFBE(FB_clearFrom, FB_clearTill); unreported_subcode_event_type |= pBufferElement.subcode.event_type; //check if sample_rate and channels are the same values as before //to make mp3 decoder more robust against lost of synchronization //especially in case of fast seek //check if sample_rate, channels, bistream type are meaning values at all if ((ret != kDecoderStatus_NoError) && (ret != kDecoderStatus_MoreData)) { //dprintf("Decode header error: %d\r\n",ret); break; } //if they are meaning values, check if they match with values from BitrateParser if(ret == kDecoderStatus_NoError) { if(MP3Bitstream_p->sampleRate != CurrentSampling_fr) { //dprintf("Sample rate error: %u\r\n",MP3Bitstream_p->sampleRate); break; } if(MP3Bitstream_p->channels.total != CurrentCh_num) { //dprintf("Channel number error: %u\r\n",MP3Bitstream_p->channels.total); break; } if(MP3Bitstream_p->bitstreamType != CurrentBistreamType) { //dprintf("Layer error: %u\r\n",MP3Bitstream_p->bitstreamType); break; } } //next processing switch (ret) { case kDecoderStatus_NoError: // cannot start decoding if AB is full, as AudioBuffer is used inplace to decode mp3 if ((AudioBuffer_p = AudioBufferHaveSpace(MP3Bitstream_p->sampleRate)) == NULL) { //output buffer is full NextStateAfterWaitAB = decodingFrames; MP3DecoderNextState = waitingAudioBuffer; return decoderWaitingABempty; } // re-set output pointers to consecutive AudioBuffer element MP3Output_p->channels[0] = (void *) AudioBuffer_p; MP3Output_p->channels[1] = (void *)(AudioBuffer_p + 1); // 4 bytes per sample // Do not leave the loop, there may be more data available for decoding. MP3DecoderNextState = decodingFrames; break; case kDecoderStatus_MoreData: // Can't proceed till mode data available, if (!(Mp3DataEOF || Mp3DataEOPB)) break; // there are more data to process //clear used FB elements FB_clearFrom = GetElementNumber((unsigned char *)(MP3Bitstream_p->data)); SetEmptyFBE(FB_clearFrom, pBufferElement.en); //if last element not cleared before, then do it here ClearFBElement(pBufferElement.en); if (Mp3DataEOPB) { MP3DecoderCloseBitstream(MP3DecoderHandle, MP3Scratch_p); MP3DecoderNextState = notInitialized; break; } else // if (Mp3DataEOF) { return decoderEOF; } case kDecoderStatus_NoFrameHeader: case kDecoderStatus_BrokenFrame: case kDecoderStatus_ReservedBitRate: case kDecoderStatus_ReservedSamplingFrequency: case kDecoderStatus_UnsupportedFeature: // Assume a false header was detected, continue silently // (hoping to reach a good sync point), but update the // data pointers otherwise we'll detect the same header! break; case kDecoderStatus_InvalidArgument: break; } //switch ret break; } //case searchingHeader case decodingFrames: { // Decoding of copressed data is ongoing. Continue until // - no more compressd data is available // - not enough space in output buffer available // - error conditions Mp3DataEOPB = 0; switch (MP3UpdateBitstream(MP3Bitstream_p, flag)) { case waitingForData: //not enough data return decoderWaitingFBdata; //return decoderOk; case dataEOF: //EOF break; case dataReady: //data ready break; case immediateEOF: // request from Controller return decoderEOF_immediate; case dataEOPB: // end of play block (FF/FB) Mp3DataEOPB = 1; // to wrap and start header decoding break; } // Update bitstream data pointers ret = MP3DecodeFrame(MP3DecoderHandle, MP3Scratch_p, MP3Output_p, MP3Bitstream_p); if (MP3Bitstream_p->channels.total == 1) { // mono for (sample = 0; sample < MP3Output_p->numberOfSamples; sample++) { *((int32 *)(MP3Output_p->channels[1]) + (sample << 1)) = *((int32 *) (MP3Output_p->channels[0]) + (sample << 1)); } } // set number of DECODED bytes SetDecodedBytes(MP3Bitstream_p->dataLength - MP3Bitstream_p->dataOffset); //decoderDecodedBytes = decoderReadBytes - (MP3Bitstream_p->dataLength - MP3Bitstream_p->dataOffset); CurrentBitRate = (uint32)GetCurrentBitRate(); GetCurrentPosition(&position); // xid,playlist position.offset = GetDecodedBytes(); time_event.subcode.event_type = CAPTURE_EVENT_SUBCODE_NONE; CurrentFilePosAfterTAG = GetDecodedBytes() - GetCurrentStartOffset() + (CurrentBitRate >> 1); Fragment = (CurrentFilePosAfterTAG / (CurrentBitRate * (DECODER_TIME_INTERVAL / 1000) + ((DECODER_TIME_INTERVAL % 1000) * CurrentBitRate / 1000))); if (Fragment != LastReportedFragment) { LastReportedFragment = Fragment; pBufferElement.subcode.event_type |= CAPTURE_EVENT_SUBCODE_REL_TIME; } // if error occured before, now attach the last event pBufferElement.subcode.event_type |= unreported_subcode_event_type; if (pBufferElement.subcode.event_type & (CAPTURE_EVENT_SUBCODE_BEGIN_OF_SONG | CAPTURE_EVENT_SUBCODE_REL_TIME) ) {#ifdef APM_PICKUP //APM: time in miliseconds (overflow?): time_event.ms.rel_time = (CurrentFilePosAfterTAG * 1000) / CurrentBitRate; time_event.ms.event_type = pBufferElement.subcode.event_type;#else //STM: calculate time into MSF format: time_event.subcode.event_type = pBufferElement.subcode.event_type; time_event.subcode.q_subcode.q_min = CurrentFilePosAfterTAG / (60*CurrentBitRate); // min; time_event.subcode.q_subcode.q_sec = (CurrentFilePosAfterTAG / CurrentBitRate) % 60; // sec; time_event.subcode.q_subcode.q_frame = 0; // frame; time_event.subcode.q_subcode.q_tno = position.song_number; time_event.subcode.q_subcode.xid = position.xfile; //timeinfo_msf += ((absolute_outcnt % CurrentSampleRateConverterFrequency) * 75) / CurrentSampleRateConverterFrequency; // frame#endif time_event.subcode.event_subcode = 0; // CA - info for AB to enable/disable de-emphasis // store event time not to lose it (if error) unreported_subcode_event_type = pBufferElement.subcode.event_type; pBufferElement.subcode.event_type = CAPTURE_EVENT_SUBCODE_NONE; } //clear used FB elements FB_clearFrom = GetElementNumber((unsigned char *)(MP3Bitstream_p->data)); FB_clearTill = GetElementNumber((unsigned char *) (MP3Bitstream_p->data + MP3Bitstream_p->dataOffset)); SetEmptyFBE(FB_clearFrom, FB_clearTill); switch (ret) { case kDecoderStatus_NoError: // check the play mode:#if (DEBUG_INCLUDE_COUNTERS==1) countMP3GoodFrames++;#endif if (MP3Output_p->numberOfSamples == 0) { MP3DecoderNextState = searchingHeader; break; // nothing to do } //some output samples have been generated AudioBufferSetFull(MP3Output_p->numberOfSamples, nextElementFlag, &time_event, &position); unreported_subcode_event_type = 0; nextElementFlag = FT_MIDDLE; MP3DecoderNextState = searchingHeader; break; case kDecoderStatus_MoreData: //some output samples may have been generated if (MP3Output_p->numberOfSamples > 0) { AudioBufferSetFull(MP3Output_p->numberOfSamples, nextElementFlag, &time_event, &position); unreported_subcode_event_type = 0; nextElementFlag = FT_MIDDLE; } //clear used FB elements FB_clearFrom = GetElementNumber((unsigned char *)(MP3Bitstream_p->data)); SetEmptyFBE(FB_clearFrom, pBufferElement.en); //if last element not cleared before, then do it here ClearFBElement(pBufferElement.en); if (Mp3DataEOPB) { // kDecoderStatus_MoreData because EOPB (Play Block) has been reached (no EOF) MP3DecoderCloseBitstream(MP3DecoderHandle, MP3Scratch_p); MP3DecoderNextState = notInitialized; break; } return decoderEOF; case kDecoderStatus_MoreSamples: // The decoder has filled AudioBuffer. Empty it and continue with MP3DecodeFrame if (MP3Output_p->numberOfSamples == 0) { MP3DecoderNextState = searchingHeader; break; // nothing to do } //some output samples have been generated AudioBufferSetFull(MP3Output_p->numberOfSamples, nextElementFlag, &time_event, &position); unreported_subcode_event_type = 0; nextElementFlag = FT_MIDDLE; NextStateAfterWaitAB = decodingFrames; if ((AudioBuffer_p = AudioBufferHaveSpace(MP3Bitstream_p->sampleRate)) == NULL) { //output buffer is full MP3DecoderNextState = waitingAudioBuffer; return decoderWaitingABempty; } // re-set output pointers to consecutive AudioBuffer element MP3Output_p->channels[0] = (void *) AudioBuffer_p; MP3Output_p->channels[1] = (void *)(AudioBuffer_p + 1); // 4 bytes per sample break; case kDecoderStatus_BrokenFrame: case kDecoderStatus_FrameDiscarded: case kDecoderStatus_CRCError: // The only thing we can do about these errors // is to skip to the next frame, just like the normal case, // but also signal to the Controller, who may want to mute the output#if (DEBUG_INCLUDE_COUNTERS==1) countMP3BadFrames++; // [RB]#endif MP3DecoderNextState = searchingHeader; break; case kDecoderStatus_InvalidChannelConfiguration: case kDecoderStatus_TooFewOutputChannels: case kDecoderStatus_InvalidArgument: break; case kDecoderStatus_Fatal_Error: case kDecoderStatus_Fatal_UnsupportedFeature: case kDecoderStatus_Fatal_TooManyChannels: // Cannot proceed, request upper layer to discard the file MP3DecoderNextState = fatalError; return decoderFatalError; default: break; } break; } //case decodingFrames case waitingAudioBuffer: { // Decoding of compressed data is going on, but the decoder // ran out of space in the AudioBuffer. This means we // decoding data faster than it is being consumed by // the audio hardware. Return to caller to be put to sleep. if ((AudioBuffer_p = AudioBufferHaveSpace(MP3Bitstream_p->sampleRate)) == NULL) { //output buffer is full return decoderWaitingABempty; } // re-set output pointers to consecutive AudioBuffer element MP3Output_p->channels[0] = (void *) AudioBuffer_p; MP3Output_p->channels[1] = (void *)(AudioBuffer_p + 1); // 4 bytes per sample MP3DecoderNextState = NextStateAfterWaitAB; break; } //case waitingAudioBuffer } //switch MP3DecoderNextState } //while}void MP3Kill(DecoderKillType killType){ /*eDecoderStatus ret;*/ //[LL] TBD - could return something if (killType == closeOnly) { /*ret = MP3DecoderCloseBitstream(MP3DecoderHandle, MP3Scratch_p);*/ MP3DecoderCloseBitstream(MP3DecoderHandle, MP3Scratch_p); MP3DecoderNextState = notInitialized; } else if (killType == destroy) { //ret = MP3DecoderCloseBitstream(MP3DecoderHandle, MP3Scratch_p); //MP3DecoderNextState = notInitialized; //FREE(MP3Requirements_p->instanceStateSize); //FREE(MP3Requirements_p->scratchSize); } FREE(MP3InstanceState_p); FREE(MP3Scratch_p); INIT_FAST_MALLOC(); //[LL] to ensure 1000% NONE items allocated}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -