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

📄 msadpcm.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 5 页
字号:
            {                lSamp = 32767;            }            else if(lSamp < -32768)            {                lSamp = -32768;            }                    //            //  lSamp contains the decoded sInput sample--now write it            //  out to the destination buffer            //            if(ucChannel == 0)            {                *psLeft++ = (short)lSamp;            }            else            {                *psRight++ = (short)lSamp;            }                            //            //  ripple our previous samples down making the new psSamp1            //  equal to the sample we just decoded            //            psSamp2[ucChannel] = psSamp1[ucChannel];            psSamp1[ucChannel] = (short)lSamp;        }    }    //    //  if this is a short block, then fill the remainder of the output block    //  with silence.    //    if(usSamplesPerBlock < pMSADPCM->usSamplesPerBlock)    {        memset(psLeft, 0,               (pMSADPCM->usSamplesPerBlock - usSamplesPerBlock) * 2);        if(pMSADPCM->ucChannels == 2)        {            memset(psRight, 0,                   (pMSADPCM->usSamplesPerBlock - usSamplesPerBlock) * 2);        }    }    //    //  we're done decoding the input data.  return the number of samples    //  decoded.    //    return(usSamplesPerBlock);}//****************************************************************************//// Computes the first delta value for a MS ADPCM block.////****************************************************************************shortadpcmEncode4Bit_FirstDelta(short iCoef1, short iCoef2, short iP5, short iP4,                           short iP3, short iP2, short iP1){    long    lTotal;    short   iRtn;    long    lTemp;    //    //  use average of 3 predictions    //    lTemp  = (((long)iP5 * iCoef2) + ((long)iP4 * iCoef1)) >> MSADPCM_CSCALE;    lTotal = (lTemp > iP3) ? (lTemp - iP3) : (iP3 - lTemp);    lTemp   = (((long)iP4 * iCoef2) + ((long)iP3 * iCoef1)) >> MSADPCM_CSCALE;    lTotal += (lTemp > iP2) ? (lTemp - iP2) : (iP2 - lTemp);    lTemp   = (((long)iP3 * iCoef2) + ((long)iP2 * iCoef1)) >> MSADPCM_CSCALE;    lTotal += (lTemp > iP1) ? (lTemp - iP1) : (iP1 - lTemp);        //    //  optimal iDelta is 1/4 of prediction error    //    iRtn = (short)(lTotal / 12);    if(iRtn < MSADPCM_DELTA4_MIN)    {        iRtn = MSADPCM_DELTA4_MIN;    }    return(iRtn);}//****************************************************************************//// Encodes a block of 16-bit PCM into MS ADPCM.////****************************************************************************unsigned longadpcmEncode4Bit(tMSADPCM *pMSADPCM, short *psLeft, short *psRight,                unsigned char *pucDst){    short *ppsSamples[2];    unsigned char pucBestPredictor[2];    unsigned long ppulTotalError[7][2];    short   ppsFirstDelta[7][2];    short   psDelta[2];    short   psSamp1[2];    short   psSamp2[2];    short   sCoef1;    short   sCoef2;    short   sDelta;    short   sSample;    short   sOutput;    long    lSamp;    unsigned long ulTemp;    unsigned long ulTotalConverted;    long    lError;    long    lPrediction;    unsigned char ucNextWrite = 0;    unsigned char ucFirstNibble;    unsigned short usSample;    unsigned char ucChannel;    unsigned char ucPredictor;    //    //  save the pointers to the left and right channel data    //    ppsSamples[0] = psLeft;    ppsSamples[1] = psRight;    //    //  initialize the number of output bytes to zero    //    ulTotalConverted = 0;    //    //  find the optimal predictor for each channel: to do this, we    //  must step through and encode using each coefficient set (one    //  at a time) and determine which one has the least error from    //  the original data. the one with the least error is then used    //  for the final encode (the 8th pass done below).    //    //  NOTE: keeping the encoded data of the one that has the least    //  error at all times is an obvious optimization that should be    //  done. in this way, we only need to do 7 passes instead of 8.    //    for(ucPredictor = 0; ucPredictor < 7; ucPredictor++)    {        //        //  copy the coefficient pair for the current coefficient set        //  we are using into more convenient/cheaper variables        //        sCoef1 = psCoefficient1[ucPredictor];        sCoef2 = psCoefficient2[ucPredictor];        //        //  now choose the first iDelta and setup the first two samples        //        for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)        {            //            //  reset total error calculation for new block            //            ppulTotalError[ucPredictor][ucChannel] = 0;            //            //  first 2 samples will come from real data--compute            //  starting from there            //            psSamp1[ucChannel] = ppsSamples[ucChannel][1];            psSamp2[ucChannel] = ppsSamples[ucChannel][0];                                    //            //  calculate initial iDelta            //            sDelta = adpcmEncode4Bit_FirstDelta(sCoef1, sCoef2,                                                ppsSamples[ucChannel][0],                                                ppsSamples[ucChannel][1],                                                ppsSamples[ucChannel][2],                                                ppsSamples[ucChannel][3],                                                ppsSamples[ucChannel][4]);            psDelta[ucChannel] = sDelta;            ppsFirstDelta[ucPredictor][ucChannel] = sDelta;        }        //        //  now encode the rest of the PCM data in this block--note        //  we start 2 samples ahead because the first two samples are        //  simply copied into the ADPCM block header...        //        for(usSample = 2; usSample < pMSADPCM->usSamplesPerBlock; usSample++)        {            //            //  each channel gets encoded independently... obviously.            //            for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)            {                //                //  yes, copy into cheaper variables because we access                //  them a lot                //                sDelta = psDelta[ucChannel];                //                //  calculate the prediction based on the previous two                //  samples                //                lPrediction = (((long)psSamp1[ucChannel] * sCoef1) +                               ((long)psSamp2[ucChannel] * sCoef2)) >>                              MSADPCM_CSCALE;                //                //  grab the sample (for the current channel) to encode                //  from the source                //                sSample = ppsSamples[ucChannel][usSample];                //                //  encode it                //                lError = (long)sSample - lPrediction;                sOutput = (short)(lError / sDelta);                if(sOutput > MSADPCM_OUTPUT4_MAX)                {                    sOutput = MSADPCM_OUTPUT4_MAX;                }                else if(sOutput < MSADPCM_OUTPUT4_MIN)                {                    sOutput = MSADPCM_OUTPUT4_MIN;                }                lSamp = lPrediction + ((long)sDelta * sOutput);                if(lSamp > 32767)                {                    lSamp = 32767;                }                else if(lSamp < -32768)                {                    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;                //                //  keep a running status on the error for the current                //  coefficient pair for this channel                //                lError = lSamp - sSample;                ppulTotalError[ucPredictor][ucChannel] +=                    (lError * lError) >> 7;            }        }    }    //    //  WHEW! we have now made 7 passes over the data and calculated    //  the error for each--so it's time to find the one that produced    //  the lowest error and use that predictor (this is for each    //  channel of course)    //    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        pucBestPredictor[ucChannel] = 0;        ulTemp = ppulTotalError[0][ucChannel];        for(ucPredictor = 1; ucPredictor < 7; ucPredictor++)        {            if(ppulTotalError[ucPredictor][ucChannel] < ulTemp)            {                pucBestPredictor[ucChannel] = ucPredictor;                ulTemp = ppulTotalError[ucPredictor][ucChannel];            }        }    }        //    //  grab first iDelta from our precomputed first deltas that we    //  calculated above    //    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        ucPredictor = pucBestPredictor[ucChannel];        psDelta[ucChannel] = ppsFirstDelta[ucPredictor][ucChannel];    }    //    //  get the first two samples from the source data (so we can write    //  them into the ADPCM block header and use them in our prediction    //  calculation when encoding the rest of the data).    //    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        psSamp2[ucChannel] = ppsSamples[ucChannel][0];        psSamp1[ucChannel] = ppsSamples[ucChannel][1];    }    //    //  write the block header for the encoded data    //    //  the block header is composed of the following data:    //      1 byte predictor per channel    //      2 byte delta per channel    //      2 byte first sample per channel    //      2 byte second sample per channel    //    //  this gives us (7 * nChannels) bytes of header information    //    //  so first write the 1 byte predictor for each channel into the    //  destination buffer    //    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        *pucDst++ = pucBestPredictor[ucChannel];    }    //    //  now write the 2 byte delta per channel...    //    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        *pucDst++ = psDelta[ucChannel] & 255;        *pucDst++ = psDelta[ucChannel] >> 8;    }    //    //  finally, write the first two samples (2 bytes each per channel)    //    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        *pucDst++ = psSamp1[ucChannel] & 255;        *pucDst++ = psSamp1[ucChannel] >> 8;    }    for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)    {        *pucDst++ = psSamp2[ucChannel] & 255;        *pucDst++ = psSamp2[ucChannel] >> 8;    }    //    //  the number of bytes that we have written to the destination    //  buffer is (7 * nChannels)--so add this to our total number of    //  bytes written to the destination.. for our return value.    //    ulTotalConverted += pMSADPCM->ucChannels * 7;    //    //  we have written the header for this block--now write the data    //  chunk (which consists of a bunch of encoded nibbles). note that    //  we start our count at 2 because we already wrote the first    //  two samples into the destination buffer as part of the header    //    ucFirstNibble = 1;    for(usSample = 2; usSample < pMSADPCM->usSamplesPerBlock; usSample++)    {        //        //  each channel gets encoded independently... obviously.        //        for(ucChannel = 0; ucChannel < pMSADPCM->ucChannels; ucChannel++)        {            //            //  use our chosen best predictor and grab the coefficient            //  pair to use for this channel...            //            ucPredictor = pucBestPredictor[ucChannel];            sCoef1 = psCoefficient1[ucPredictor];            sCoef2 = psCoefficient2[ucPredictor];            //            //  copy into cheaper variables because we access them a lot            //            sDelta = psDelta[ucChannel];            //            //  calculate the prediction based on the previous two samples            //            lPrediction = (((long)psSamp1[ucChannel] * sCoef1) +                           ((long)psSamp2[ucChannel] * sCoef2)) >>                          MSADPCM_CSCALE;            //            //  grab the sample to encode            //            sSample = ppsSamples[ucChannel][usSample];            //            //  encode the sample            //            lError = (long)sSample - lPrediction;            sOutput = (short)(lError / sDelta);            if(sOutput > MSADPCM_OUTPUT4_MAX)            {                sOutput = MSADPCM_OUTPUT4_MAX;            }            else if(sOutput < MSADPCM_OUTPUT4_MIN)            {                sOutput = MSADPCM_OUTPUT4_MIN;            }            lSamp = lPrediction + ((long)sDelta * sOutput);            if(lSamp > 32767)            {                lSamp = 32767;            }            else if(lSamp < -32768)

⌨️ 快捷键说明

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