📄 imaalgorith.c
字号:
}
//
// 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 + -