⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msadpcm.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 5 页
字号:
            {                lSamp = -32768;            }            //            //  compute the next iDelta            //            sDelta = (short)((psP4[sOutput & 15] * (long)sDelta) >>                             MSADPCM_PSCALE);             if(sDelta < MSADPCM_DELTA4_MIN)            {                sDelta = MSADPCM_DELTA4_MIN;            }            //            //  save updated values for this channel back into the            //  original arrays...            //            psDelta[ucChannel] = sDelta;            psSamp2[ucChannel] = psSamp1[ucChannel];            psSamp1[ucChannel] = (short)lSamp;            //            //  we have another nibble of encoded data--either combine            //  this with the previous nibble and write out a full             //  byte, or save this nibble for the next nibble to be            //  combined into a full byte and written to the destination            //  buffer... uhg!            //            if(ucFirstNibble)            {                ucNextWrite = (sOutput & 15) << 4;                ucFirstNibble = 0;            }            else            {                *pucDst++ = ucNextWrite | (sOutput & 15);                ulTotalConverted++;                ucFirstNibble = 1;            }        }    }    //    //  return the number of bytes in the encoded ADPCM block    //    return (ulTotalConverted);}//****************************************************************************//// MSADPCMSetupDecoder prepares to decode a file using the MS ADPCM decoder.////****************************************************************************unsigned longMSADPCMSetupDecoder(tMSADPCM *pMSADPCM){    ADPCMWaveFormat sWaveFormat;    unsigned long ulOffset, ulLength;    //    // Seek to the beginning of the file.    //    FSSeek(pMSADPCM->pFile, 0);    //    // Read the first portion of the file.    //    pMSADPCM->usValid = FSRead(pMSADPCM->pFile, pMSADPCM->pucEncodedData,                               4096);    //    // Make sure that this is a RIFF WAVE file.    //    if((pMSADPCM->usValid < 12) ||       (pMSADPCM->pucEncodedData[0] != 'R') ||       (pMSADPCM->pucEncodedData[1] != 'I') ||       (pMSADPCM->pucEncodedData[2] != 'F') ||       (pMSADPCM->pucEncodedData[3] != 'F') ||       (pMSADPCM->pucEncodedData[8] != 'W') ||       (pMSADPCM->pucEncodedData[9] != 'A') ||       (pMSADPCM->pucEncodedData[10] != 'V') ||       (pMSADPCM->pucEncodedData[11] != 'E'))    {        return(0);    }    //    // Find the "fmt " chunk.    //    ulOffset = CodecFindRIFFChunk(pMSADPCM->pucEncodedData, pMSADPCM->usValid,                                  12, "fmt ");    if(ulOffset == -1)    {        return(0);    }    //    // Get the length of the "fmt " chunk.    //    ulLength = ((pMSADPCM->pucEncodedData[ulOffset + 7] << 24) |                (pMSADPCM->pucEncodedData[ulOffset + 6] << 16) |                (pMSADPCM->pucEncodedData[ulOffset + 5] << 8) |                pMSADPCM->pucEncodedData[ulOffset + 4]);    //    // If the length of the "fmt " chunk is not the same as the size of the MS    // ADPCM wave format sturcture, then we can not decode this file.    //    if(ulLength != sizeof(ADPCMWaveFormat))    {        return(0);    }    //    // Make sure that the entire "fmt " chunk is in the data buffer.    //    if((ulOffset + ulLength + 8) > pMSADPCM->usValid)    {        return(0);    }    //    // Copy the wave format structure from the "fmt " chunk into a/ local.  We    // do this instead of grabbing the values directly from the data buffer    // since the "fmt " chunk can occur with any alignment, making it a lot    // easier to simply copy the structure.    //    memcpy((void *)&sWaveFormat, pMSADPCM->pucEncodedData + ulOffset + 8,           sizeof(ADPCMWaveFormat));    //    // Perform some sanity checks on the wave format structure.    //    if((sWaveFormat.wFormatTag != 2) ||       (sWaveFormat.nChannels > 2) ||       (sWaveFormat.nSamplesPerSec > 48000) ||       (sWaveFormat.nBlockAlign > 4096) ||       (sWaveFormat.wBitsPerSample != 4) ||       (sWaveFormat.cbSize != 32) ||       (sWaveFormat.wSamplesPerBlock > MSADPCM_MAX_PCM_LENGTH) ||       (sWaveFormat.wNumCoef != 7))    {        //        // The wave format does not pass the sanity checks, so we can not        // decode this file.        //        return(0);    }    //    // Make sure that the coefficients match the MS ADPCM coefficients.    //    for(ulLength = 0; ulLength < 7; ulLength++)    {        if((sWaveFormat.aCoef[ulLength].iCoef1 != psCoefficient1[ulLength]) ||           (sWaveFormat.aCoef[ulLength].iCoef2 != psCoefficient2[ulLength]))        {            //            // The coefficients do not match the MS ADPCM coefficients, so we            // can not decode this file.            //            return(0);        }    }    //    // Save information about this file which we will need.    //    pMSADPCM->usSampleRate = sWaveFormat.nSamplesPerSec;    pMSADPCM->ucChannels = sWaveFormat.nChannels;    pMSADPCM->usBytesPerBlock = sWaveFormat.nBlockAlign;    pMSADPCM->usSamplesPerBlock = sWaveFormat.wSamplesPerBlock;    //    // Compute the byte rate as the header is often inaccurate (thanks    // Microsoft).    //    pMSADPCM->ulBitRate = ((sWaveFormat.nSamplesPerSec * 8 *                            sWaveFormat.nBlockAlign) /                           sWaveFormat.wSamplesPerBlock);    //    // Find the "data" chunk.    //    ulOffset = CodecFindRIFFChunk(pMSADPCM->pucEncodedData, pMSADPCM->usValid,                                  12, "data");    if(ulOffset == -1)    {        return(0);    }    //    // Save the starting position of the "data" chunk.    //    pMSADPCM->ulDataStart = ulOffset + 8;    //    // Get the length of the "data" chunk.    //    pMSADPCM->ulLength = ((pMSADPCM->pucEncodedData[ulOffset + 7] << 24) |                          (pMSADPCM->pucEncodedData[ulOffset + 6] << 16) |                          (pMSADPCM->pucEncodedData[ulOffset + 5] << 8) |                          pMSADPCM->pucEncodedData[ulOffset + 4]);    //    // Advance to the current buffer offset to the first byte of the "data"    // chunk.    //    pMSADPCM->usOffset = ulOffset + 8;    //    // Compute the time length of the file.  We ignore the "fact" chunk in the    // file since Microsoft's Sound Recorder on the PC (for example) does not    // put the correct value into this chunk (it over-states the number of    // samples in the file).    //    pMSADPCM->ulTimeLength = ((((pMSADPCM->ulLength * 8) /                                pMSADPCM->ulBitRate) * 1000) +                              ((((pMSADPCM->ulLength * 8) %                                 pMSADPCM->ulBitRate) * 1000) /                               pMSADPCM->ulBitRate));    //    // The position is zero.    //    pMSADPCM->ulTimePos = 0;    //    // Initially, all the data in the file is valid.    //    pMSADPCM->ulDataValid = pMSADPCM->ulLength + pMSADPCM->usOffset;    //    // There is no output buffer.    //    pMSADPCM->pBuffer = 0;    //    // Success.    //    return(1);}//****************************************************************************//// MSADPCMSetupEncoder prepares to encode a file using the MS ADPCM encoder.////****************************************************************************unsigned longMSADPCMSetupEncoder(tMSADPCM *pMSADPCM){    ADPCMWaveFormat sWaveFormat;    unsigned long ulIdx;    //    // We encode files at 8kHz, mono.  So, the following parameters are fixed.    //    pMSADPCM->ulBitRate = 32768;    pMSADPCM->usSampleRate = 8000;    pMSADPCM->ucChannels = 1;    pMSADPCM->usBytesPerBlock = 256;    pMSADPCM->usSamplesPerBlock = 500;    //    // Build the RIFF header in the encoded data buffer.    //    pMSADPCM->pucEncodedData[0] = 'R';    pMSADPCM->pucEncodedData[1] = 'I';    pMSADPCM->pucEncodedData[2] = 'F';    pMSADPCM->pucEncodedData[3] = 'F';    pMSADPCM->pucEncodedData[4] = 0;    pMSADPCM->pucEncodedData[5] = 0;    pMSADPCM->pucEncodedData[6] = 0;    pMSADPCM->pucEncodedData[7] = 0;    pMSADPCM->pucEncodedData[8] = 'W';    pMSADPCM->pucEncodedData[9] = 'A';    pMSADPCM->pucEncodedData[10] = 'V';    pMSADPCM->pucEncodedData[11] = 'E';    //    // Fill in the wave format structure.    //    sWaveFormat.wFormatTag = 2;    sWaveFormat.nChannels = pMSADPCM->ucChannels;    sWaveFormat.nSamplesPerSec = pMSADPCM->usSampleRate;    sWaveFormat.nAvgBytesPerSec = pMSADPCM->ulBitRate / 8;    sWaveFormat.nBlockAlign = pMSADPCM->usBytesPerBlock;    sWaveFormat.wBitsPerSample = 4;    sWaveFormat.cbSize = 32;    sWaveFormat.wSamplesPerBlock = pMSADPCM->usSamplesPerBlock;    sWaveFormat.wNumCoef = 7;    for(ulIdx = 0; ulIdx < 7; ulIdx++)    {        sWaveFormat.aCoef[ulIdx].iCoef1 = psCoefficient1[ulIdx];        sWaveFormat.aCoef[ulIdx].iCoef2 = psCoefficient2[ulIdx];    }    //    // Add the "fmt " chunk in the encoded data buffer.    //    pMSADPCM->pucEncodedData[12] = 'f';    pMSADPCM->pucEncodedData[13] = 'm';    pMSADPCM->pucEncodedData[14] = 't';    pMSADPCM->pucEncodedData[15] = ' ';    pMSADPCM->pucEncodedData[16] = 50;    pMSADPCM->pucEncodedData[17] = 0;    pMSADPCM->pucEncodedData[18] = 0;    pMSADPCM->pucEncodedData[19] = 0;    memcpy(pMSADPCM->pucEncodedData + 20, (void *)&sWaveFormat, 50);    //    // Add the "fact" chunk in the encoded data buffer.    //    pMSADPCM->pucEncodedData[70] = 'f';    pMSADPCM->pucEncodedData[71] = 'a';    pMSADPCM->pucEncodedData[72] = 'c';    pMSADPCM->pucEncodedData[73] = 't';    pMSADPCM->pucEncodedData[74] = 4;    pMSADPCM->pucEncodedData[75] = 0;    pMSADPCM->pucEncodedData[76] = 0;    pMSADPCM->pucEncodedData[77] = 0;    pMSADPCM->pucEncodedData[78] = 0;    pMSADPCM->pucEncodedData[79] = 0;    pMSADPCM->pucEncodedData[80] = 0;    pMSADPCM->pucEncodedData[81] = 0;    //    // Add the "data" chunk in the encoded data buffer.    //    pMSADPCM->pucEncodedData[82] = 'd';    pMSADPCM->pucEncodedData[83] = 'a';    pMSADPCM->pucEncodedData[84] = 't';    pMSADPCM->pucEncodedData[85] = 'a';    pMSADPCM->pucEncodedData[86] = 0;    pMSADPCM->pucEncodedData[87] = 0;    pMSADPCM->pucEncodedData[88] = 0;    pMSADPCM->pucEncodedData[89] = 0;    //    // There are 90 bytes of valid data in the encoded data buffer.    //    pMSADPCM->usValid = 90;    //    // The initial length of the encoded data is 0.    //    pMSADPCM->ulLength = 0;    pMSADPCM->ulTimePos = 0;    pMSADPCM->ulDataValid = 0;    //    // There is no input buffer.    //    pMSADPCM->pBuffer = 0;    //    // Success.    //    return(1);}//****************************************************************************//// The codec plug-in entry point for the MS ADPCM encoder/decoder.////****************************************************************************unsigned longMSADPCMIoctl(unsigned long ulIoctl, unsigned long ulParam1,             unsigned long ulParam2, unsigned long ulParam3,             unsigned long ulParam4){    //    // Determine what to do based on the specified IOCTL.    //    switch(ulIoctl)    {        //        // Return the name for this codec.        //        case IOCTL_CODEC_GETNAME:        {            const unsigned short **ppusName;            //            // The secod parameter is a pointer for the name.            //            ppusName = (const unsigned short **)ulParam2;            //            // Return the name of this codec.  The first four characters are            // the short name and the string starting at the fifth character            // is the long name.            //            *ppusName = pusCodecName;            //            // Success.            //            return(1);        }        //        // Return the name of the artist.        //        case IOCTL_CODEC_GETARTIST:        {            unsigned short **ppusName;            //            // The second parameter is a pointer for the name.            //            ppusName = (unsigned short **)ulParam2;            //            // There is no way to store the artist name in a MS ADPCM file.            //            *ppusName = 0;            //            // Success.            //            return(1);        }        //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -