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

📄 imaalgorith.c

📁 书中的主要程序文件。在打开例题的.dsw文件后,请读者在 tools菜单下的 Options 的 Directories 标签中选择 Executable files
💻 C
📖 第 1 页 / 共 4 页
字号:
        }
        

        //
        //  write out first sample
        //
        *pbDst++ = (BYTE)((nPredSampleL >> 8) + 128);
        *pbDst++ = (BYTE)((nPredSampleR >> 8) + 128);


        //
        //  The first DWORD contains 4 left samples, the second DWORD
        //  contains 4 right samples.  We process the source in 8-byte
        //  chunks to make it easy to interleave the output correctly.
        //
        ASSERT( 0 == cbBlockLength%8 );
        while( 0 != cbBlockLength )
        {
            cbBlockLength -= 8;

            dwLeft   = *(DWORD HUGE_T *)pbSrc;
            pbSrc   += sizeof(DWORD);
            dwRight  = *(DWORD HUGE_T *)pbSrc;
            pbSrc   += sizeof(DWORD);

            for( i=8; i>0; i-- )
            {
                //
                //  LEFT channel
                //
                nEncSampleL  = (dwLeft & 0x0F);
                nStepSize    = step[nStepIndexL];
                nPredSampleL = IMAAlgorithSampleDecode(nEncSampleL, nPredSampleL, nStepSize);
                nStepIndexL  = IMAAlgorithNextStepIndex(nEncSampleL, nStepIndexL);

                //
                //  RIGHT channel
                //
                nEncSampleR  = (dwRight & 0x0F);
                nStepSize    = step[nStepIndexR];
                nPredSampleR = IMAAlgorithSampleDecode(nEncSampleR, nPredSampleR, nStepSize);
                nStepIndexR  = IMAAlgorithNextStepIndex(nEncSampleR, nStepIndexR);

                //
                //  write out sample
                //
                *pbDst++ = (BYTE)((nPredSampleL >> 8) + 128);
                *pbDst++ = (BYTE)((nPredSampleR >> 8) + 128);

                //
                //  Shift the next input sample into the low-order 4 bits.
                //
                dwLeft  >>= 4;
                dwRight >>= 4;
            }
        }
    }

    //
    //  We return the number of bytes used in the destination.  This is
    //  simply the difference in bytes from where we started.
    //
    return (DWORD)(pbDst - pbDstStart);

} // IMAAlgorithDecode4Bit_S08()



//--------------------------------------------------------------------------;
//--------------------------------------------------------------------------;

DWORD FNGLOBAL IMAAlgorithDecode4Bit_S16
(
    HPBYTE                  pbSrc,
    DWORD                   cbSrcLength,
    HPBYTE                  pbDst,
    UINT                    nBlockAlignment,
    UINT                    cSamplesPerBlock,
    int                 *   pnStepIndexL,
    int                 *   pnStepIndexR
)
{
    HPBYTE                  pbDstStart;
    UINT                    cbHeader;
    UINT                    cbBlockLength;
    int                     nStepSize;
    DWORD                   dwHeader;
    DWORD                   dwLeft;
    DWORD                   dwRight;
    int                     i;

    int                     nEncSampleL;
    int                     nPredSampleL;
    int                     nStepIndexL;

    int                     nEncSampleR;
    int                     nPredSampleR;
    int                     nStepIndexR;

    
    pbDstStart = pbDst;
    cbHeader = IMAALGORITH_HEADER_LENGTH * 2;  //  2 = number of channels.


    DPF(3,"Starting IMAAlgorithDecode4Bit_S16().");


    //
    //
    //
    while( 0 != cbSrcLength )
    {
        //
        //  The data should always be block aligned.
        //
        ASSERT( cbSrcLength >= nBlockAlignment );

        cbBlockLength  = nBlockAlignment;
        cbSrcLength   -= cbBlockLength;
        cbBlockLength -= cbHeader;


        //
        //  LEFT channel header
        //
        dwHeader = *(DWORD HUGE_T *)pbSrc;
        pbSrc   += sizeof(DWORD);
        nPredSampleL = (int)(short)LOWORD(dwHeader);
        nStepIndexL  = (int)(BYTE)HIWORD(dwHeader);

        if( !IMAAlgorithValidStepIndex(nStepIndexL) ) {
            //
            //  The step index is out of range - this is considered a fatal
            //  error as the input stream is corrupted.  We fail by returning
            //  zero bytes converted.
            //
            DPF(1,"IMAAlgorithDecode4Bit_S16: invalid step index %u (L).", nStepIndexL);
            return 0;
        }
        
        //
        //  RIGHT channel header
        //
        dwHeader = *(DWORD HUGE_T *)pbSrc;
        pbSrc   += sizeof(DWORD);
        nPredSampleR = (int)(short)LOWORD(dwHeader);
        nStepIndexR  = (int)(BYTE)HIWORD(dwHeader);

        if( !IMAAlgorithValidStepIndex(nStepIndexR) ) {
            //
            //  The step index is out of range - this is considered a fatal
            //  error as the input stream is corrupted.  We fail by returning
            //  zero bytes converted.
            //
            DPF(1,"IMAAlgorithDecode4Bit_S16: invalid step index %u (R).",nStepIndexR);
            return 0;
        }
        

        //
        //  write out first sample
        //
        *(DWORD HUGE_T *)pbDst = MAKELONG(nPredSampleL, nPredSampleR);
        pbDst += sizeof(DWORD);


        //
        //  The first DWORD contains 4 left samples, the second DWORD
        //  contains 4 right samples.  We process the source in 8-byte
        //  chunks to make it easy to interleave the output correctly.
        //
        ASSERT( 0 == cbBlockLength%8 );
        while( 0 != cbBlockLength )
        {
            cbBlockLength -= 8;

            dwLeft   = *(DWORD HUGE_T *)pbSrc;
            pbSrc   += sizeof(DWORD);
            dwRight  = *(DWORD HUGE_T *)pbSrc;
            pbSrc   += sizeof(DWORD);

            for( i=8; i>0; i-- )
            {
                //
                //  LEFT channel
                //
                nEncSampleL  = (dwLeft & 0x0F);
                nStepSize    = step[nStepIndexL];
                nPredSampleL = IMAAlgorithSampleDecode(nEncSampleL, nPredSampleL, nStepSize);
                nStepIndexL  = IMAAlgorithNextStepIndex(nEncSampleL, nStepIndexL);

                //
                //  RIGHT channel
                //
                nEncSampleR  = (dwRight & 0x0F);
                nStepSize    = step[nStepIndexR];
                nPredSampleR = IMAAlgorithSampleDecode(nEncSampleR, nPredSampleR, nStepSize);
                nStepIndexR  = IMAAlgorithNextStepIndex(nEncSampleR, nStepIndexR);

                //
                //  write out sample
                //
                *(DWORD HUGE_T *)pbDst = MAKELONG(nPredSampleL, nPredSampleR);
                pbDst += sizeof(DWORD);

                //
                //  Shift the next input sample into the low-order 4 bits.
                //
                dwLeft  >>= 4;
                dwRight >>= 4;
            }
        }
    }

    //
    //  We return the number of bytes used in the destination.  This is
    //  simply the difference in bytes from where we started.
    //
    return (DWORD)(pbDst - pbDstStart);

} // IMAAlgorithDecode4Bit_S16()



//==========================================================================;
//
//     ENCODE ROUTINES
//
//==========================================================================;

//--------------------------------------------------------------------------;
//  
//  DWORD IMAAlgorithEncode4Bit_M08
//  DWORD IMAAlgorithEncode4Bit_M16
//  DWORD IMAAlgorithEncode4Bit_S08
//  DWORD IMAAlgorithEncode4Bit_S16
//  
//  Description:
//      These functions encode a buffer of data from PCM to ADPCM in the
//      specified format.  The appropriate function is called once for each
//      ACMDM_STREAM_CONVERT message received.  Note that since these
//      functions must share the same prototype as the decoding functions
//      (see acmdStreamOpen() and acmdStreamConvert() in ACM.c for more
//      details), not all the parameters are used by these routines.
//  
//  Arguments:
//      HPBYTE pbSrc:  Pointer to the source buffer (PCM data).
//      DWORD cbSrcLength:  The length of the source buffer (in bytes).
//      HPBYTE pbDst:  Pointer to the destination buffer (ADPCM data).  Note
//                      that it is assumed that the destination buffer is
//                      large enough to hold all the encoded data; see
//                      acmdStreamSize() in ACM.c for more details.
//      UINT nBlockAlignment:  The block alignment of the ADPCM data (in
//                      bytes);  not used for encoding.
//      UINT cSamplesPerBlock:  The number of samples in each ADPCM block.
//      int *pnStepIndexL:  Pointer to the step index value (left channel)
//                      in the STREAMINSTANCE structure; this is used to
//                      maintain the step index across converts.
//      int *pnStepIndexR:  Pointer to the step index value (right channel)
//                      in the STREAMINSTANCE structure; this is used to 
//                      maintain the step index across converts.  It is only
//                      used for stereo converts.
//  
//  Return (DWORD):  The number of bytes used in the destination buffer.
//  
//--------------------------------------------------------------------------;

DWORD FNGLOBAL IMAAlgorithEncode4Bit_M08
(
    HPBYTE                  pbSrc,
    DWORD                   cbSrcLength,
    HPBYTE                  pbDst,
    UINT                    nBlockAlignment,
    UINT                    cSamplesPerBlock,
    int                 *   pnStepIndexL,
    int                 *   pnStepIndexR
)
{
    HPBYTE                  pbDstStart;
    DWORD                   cSrcSamples;
    UINT                    cBlockSamples;
    int                     nSample;
    int                     nStepSize;

    int                     nEncSample1;
    int                     nEncSample2;
    int                     nPredSample;
    int                     nStepIndex;


    pbDstStart = pbDst;
    cSrcSamples = pcmM08BytesToSamples(cbSrcLength);

    //
    //  Restore the Step Index to that of the final convert of the previous
    //  buffer.  Remember to restore this value to psi->nStepIndexL.
    //
    nStepIndex = (*pnStepIndexL);


    //
    //
    //
    //
    while (0 != cSrcSamples)
    {
        cBlockSamples = (UINT)min(cSrcSamples, cSamplesPerBlock);
        cSrcSamples  -= cBlockSamples;

        //
        //  block header
        //
        nPredSample = ((short)*pbSrc++ - 128) << 8;
        cBlockSamples--;

        *(LONG HUGE_T *)pbDst = MAKELONG(nPredSample, nStepIndex);
        pbDst += sizeof(LONG);


        //
        //  We have written the header for this block--now write the data
        //  chunk (which consists of a bunch of encoded nibbles).  Note
        //  that if we don't have enough data to fill a complete byte, then
        //  we add a 0 nibble on the end.
        //
        while( cBlockSamples>0 )
        {
            //
            //  sample 1
            //
            nSample = ((short)*pbSrc++ - 128) << 8;
            cBlockSamples--;

            nStepSize    = step[nStepIndex];
            IMAAlgorithFastEncode(nEncSample1,nPredSample,nSample,nStepSize);
            nStepIndex   = IMAAlgorithNextStepIndex(nEncSample1, nStepIndex);

            //
            //  sample 2
            //
            nEncSample2  = 0;
            if( cBlockSamples>0 ) {

                nSample = ((short)*pbSrc++ - 128) << 8;
                cBlockSamples--;

                nStepSize    = step[nStepIndex];
                IMAAlgorithFastEncode(nEncSample2,nPredSample,nSample,nStepSize);
                nStepIndex   = IMAAlgorithNextStepIndex(nEncSample2, nStepIndex);
            }

            //
            //  Write out encoded byte.
            //
            *pbDst++ = (BYTE)(nEncSample1 | (nEncSample2 << 4));
        }
    }


    //
    //  Restore the value of the Step Index, to be used on the next buffer.
    //
    (*pnStepIndexL) = nStepIndex;


    //
    //  We return the number of bytes used in the destination.  This is
    //  simply the difference in bytes from where we started.
    //
    return (DWORD)(pbDst - pbDstStart);

} // IMAAlgorithEncode4Bit_M08()



//--------------------------------------------------------------------------;
//--------------------------------------------------------------------------;

DWORD FNGLOBAL IMAAlgorithEncode4Bit_M16
(
    HPBYTE                  pbSrc,
    DWORD                   cbSrcLength,
    HPBYTE                  pbDst,
    UINT                    nBlockAlignment,
    UINT                    cSamplesPerBlock,
    int                 *   pnStepIndexL,
    int                 *   pnStepIndexR
)
{
    HPBYTE                  pbDstStart;

⌨️ 快捷键说明

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