📄 mp3.c
字号:
// // The position is zero. // pMP3->ulTimePos = 0; // // There is no output buffer. // pMP3->pOutput = 0; // // Success. // return(1); } // // Set the output buffer for the decoder. // case IOCTL_CODEC_SETBUFFER: { tMP3 *pMP3; // // The first parameter is a pointer to the MP3 persistent state. // pMP3 = (tMP3 *)ulParam1; // // The second parameter is a pointer to the output buffer. // pMP3->pOutput = (BufferState *)ulParam2; // // Provide the output buffer with our data buffers. // if(pMP3->ucChannels == 2) { BufferSetBuffer(pMP3->pOutput, pMP3->psLeft, pMP3->psRight, MP3_MAX_PCM_LENGTH + MP3_MAX_PCM_LENGTH); } else { BufferSetBuffer(pMP3->pOutput, pMP3->psLeft, pMP3->psLeft, MP3_MAX_PCM_LENGTH + MP3_MAX_PCM_LENGTH); } // // Success. // return(1); } // // Determine if the next frame of data can be decoded. // case IOCTL_CODEC_CAN_DECODE: { tMP3 *pMP3; // // The first parameter is a pointer to the MP3 persistent state. // pMP3 = (tMP3 *)ulParam1; // // See if there is space available for decoding the next frame. // if(BufferSpaceAvailable(pMP3->pOutput) < MP3_MAX_PCM_LENGTH) { // // There is not enough space available, so we can not decode // the next frame. // return(0); } // // We can decode the next frame. // return(1); } // // Decode a frame of data. // case IOCTL_CODEC_DECODE: { tMP3 *pMP3; short *psLeft, *psRight; long lLength; tMPEGStatus sStatus; // // The first parameter is a pointer to the MP3 persistent state. // pMP3 = (tMP3 *)ulParam1; // // Wait until there is space in the output buffer. This tells us // when it is OK to write more data into the output buffer. // while(BufferSpaceAvailable(pMP3->pOutput) < MP3_MAX_PCM_LENGTH) { // // Busy wait until space is available. // } // // Get a pointer to the available space in the output buffer. // BufferGetWritePointer(pMP3->pOutput, &psLeft, &psRight, &lLength); // // Decode the data frame. // sStatus = MP3DecodeData(pMP3->pMPEGInstance, psLeft, psRight, &(pMP3->sBS)); if((sStatus != eNoErr) && (sStatus != eFrameDiscarded)) { // // We could not decode the frame, so see if there is more data // to be docoded. // if((FSTell(pMP3->pFile) < pMP3->ulLength) || (((int)pMP3->sBS.bufptr - (int)pMP3->pcEncodedData) < pMP3->usValid)) { // // There is more data to be decoded, so re-initialize the // MP3 library (to try and minimize the artifacting). // InitMP3Audio(pMP3->pMPEGInstance); } else { // // There is no more data to be decoded, so return an error // to indicate that we are at the end of the file. // return(0); } } // // Make sure that this frame did not use garbage at the end of the // encoded data buffer to complete the decode. // if(((int)pMP3->sBS.bufptr - (int)pMP3->pcEncodedData) > pMP3->usValid) { // // All the data for this frame was not present, so see if there // is more data in to be decoded. // if(FSTell(pMP3->pFile) < pMP3->ulLength) { // // There is more data to be decoded, so move the buffer // pointer back to the end of the valid data. // pMP3->sBS.bufptr = (unsigned int *)(pMP3->pcEncodedData + pMP3->usValid); pMP3->sBS.bitidx = 32; // // Force the frame status to discarded. // sStatus = eFrameDiscarded; // // Re-initialize the MP3 library (to try and minimize the // artifacting). // InitMP3Audio(pMP3->pMPEGInstance); } else { // // There is no more data to be decoded, so return an error // to indicate that we are at the end of the file. // return(0); } } // // Determine the length of each frame, based on the sample rate of // the file. // lLength = pMP3->usSampleRate >= 32000 ? 1152 : 576; // // If this frame was not discarded, then update the output buffer's // write pointer. // if(sStatus != eFrameDiscarded) { // // Update the output buffer's write pointer. // BufferUpdateWritePointer(pMP3->pOutput, lLength); // // Increment the time based on the number of samples. // pMP3->ulTimePos += lLength; } // // Find the next frame in the bitstream. // while(MP3FindNextFrame(pMP3) == 0) { // // We could not find another frame, so see if there is more // data to be decoded. // if((FSTell(pMP3->pFile) < pMP3->ulLength) || (((int)pMP3->sBS.bufptr - (int)pMP3->pcEncodedData) < pMP3->usValid)) { // // There is more data to be decoded, so advance the buffer // pointer by one byte. // if(pMP3->sBS.bitidx == 32) { pMP3->sBS.bufptr++; pMP3->sBS.bitidx = 8; } else { pMP3->sBS.bitidx += 8; } // // Re-initialize the MP3 library (to try and minimize the // artifacting). // InitMP3Audio(pMP3->pMPEGInstance); } else { // // There is no more data to be decoded, so return an error // to indicate that we are at the end of the file. // return(0); } } // // Success. // return(1); } // // Encode a frame of data. // case IOCTL_CODEC_CAN_ENCODE: case IOCTL_CODEC_ENCODE: { // // We don't support encode, so return an error. // return(0); } // // Seek to the specified time position. // case IOCTL_CODEC_SEEK: { tMP3 *pMP3; unsigned long ulPos, ulPos2, ulFrameSize, ulPercent; // // The first parameter is a pointer to the MP3 persistent state. // pMP3 = (tMP3 *)ulParam1; // // Make sure that the specified time is valid. // if(ulParam2 > pMP3->ulTimeLength) { ulParam2 = pMP3->ulTimeLength; } // // If this file uses VBR, then we use the seek point table to // compute the new position. // if(pMP3->ucIsVBR) { // // Convert the seek position into a percentage through the // file. // ulPos = (ulParam2 * 100) / pMP3->ulTimeLength; // // Compute the fractional percentage between this percentage // and the next. // ulPercent = (((ulParam2 * 100) % pMP3->ulTimeLength) * 100) / pMP3->ulTimeLength; // // Get the two seek points that surround the requested // position. // if(ulPos >= 99) { ulPos2 = 256; } else { ulPos2 = pMP3->pucVBRSeek[ulPos + 1]; } if(ulPos > 99) { ulPos = 256; } else { ulPos = pMP3->pucVBRSeek[ulPos]; } // // Interpolate between the two seek points. // ulPos = (ulPos * (pMP3->ulLength / 256)) + (((ulPos2 - ulPos) * ulPercent * (pMP3->ulLength / 256)) / 100) + pMP3->ulFirstFrame; // // The new time position is the requested seek position. This // may be off by a little bit, but there's nothing that can be // done about this (other than to decode the file from the // beginning). // pMP3->ulTimePos = ((ulParam2 / 1000) * pMP3->usSampleRate) + (((ulParam2 % 1000) * pMP3->usSampleRate) / 1000); } else { // // Figure out the size of each frame based on the sample rate. // if(pMP3->usSampleRate >= 32000) { ulFrameSize = 1152; } else { ulFrameSize = 576; } // // Compute the number of frames that occur before the requested // time position. // ulPos = (((ulParam2 / 1000) * pMP3->usSampleRate) / ulFrameSize) + (((ulParam2 % 1000) * pMP3->usSampleRate) / (ulFrameSize * 1000)); // // Compute the time for the computed frame number. // pMP3->ulTimePos = ulPos = ulPos * ulFrameSize; // // Compute the file position based on the actual seek time. // ulPos = ((ulPos / pMP3->usSampleRate) * (pMP3->ulBitRate / 8)) + (((ulPos % pMP3->usSampleRate) * (pMP3->ulBitRate / 8)) / pMP3->usSampleRate) + pMP3->ulFirstFrame; if(ulPos) { ulPos--; } } // // Initialize the MP3 library. // InitMP3Audio(pMP3->pMPEGInstance); // // Initialize the bitstream to the position. // MP3InitBitstream(pMP3, ulPos); // // Find the next frame in the input MP3 bitstream. // while(1) { // // Look for the next frame. // if(MP3FindNextFrame(pMP3) == 1) { // // Make sure that the packed_info for the frame we found // matches (where appropriate) the packed_info for the // first frame in the file. // if((pMP3->usSampleRate == usSRMap[pMP3->sHdr.sample_rate]) && (pMP3->ucChannels == pMP3->sHdr.numchans)) { break; } } // // We could not find the next frame, so skip forward in the // input bitstream by a byte. // pMP3->sBS.bitidx += 8; if(pMP3->sBS.bitidx >= 32) { pMP3->sBS.bufptr++; pMP3->sBS.bitidx -= 32; } } // // Success. // return(1); } // // Cleanup after the codec. // case IOCTL_CODEC_CLOSE: { // // There's nothing to do, so return success. // return(1); } // // We should never get here, but just in case... // default: { // // Return a failure. // return(0); } }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -