Listing 2: Partial listing of decoder.cpp
class TDecoder
{
private: TDecoder();
// no default constructor wanted
public: TDecoder(vector<int> &tiDestination);
// init the TDecoder and pass a vector whereto decoded data shall
// be written;
public: void Decode(WORD wCode);
// decode the word wCode and push_back the result into tiDestination
private: int DeltaDecode(int iDelta);
int miXsample;
// the untouched fraction of the last 16-bit code passed to Decode()
int miXbitsTaken;
// denotes what number of bits are valid in miXsample
int miBitWidthOfCode;
// holds the bit width of the code
int miAbsValueCoded;
// this holds the number of WORDs left that code an absolute value
int mpiLastSamplesDiv3[3];
// usually holds the last 3 decoded samples
int miSamples2MSBidentical;
// this counter is used for the reduction of the bit width (in
// the adaption)
vector<int> *mptiDestination;
// pointer to the result vector
static const int mpiABSCODE[17];
static const int mpiOVFLCODE[16];
static const int mpiALIGNCODE[16];
static const int mpiSIGNEXTENSION[16];
};
const int TDecoder::mpiABSCODE[17] = { ... }; // as in listing 1
const int TDecoder::mpiOVFLCODE[16] = { ... }; // as in listing 1
const int TDecoder::mpiALIGNCODE[16] = { ... }; // as in listing 1
const int TDecoder::mpiSIGNEXTENSION[16] =
{
// the value at index i denotes a bitmask for 32-bits sign extension
// for an i-bits value
0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, 0xFFFFFFF0,
0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, 0xFFFFFF00,
0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, 0xFFFFF000,
0xFFFFE000, 0xFFFFC000, 0xFFFF8000, 0xFFFF0000
};
TDecoder::TDecoder(vector<int> &tiDestination):
miXsample(0),
miXbitsTaken(0),
miBitWidthOfCode(6),
miAbsValueCoded(0),
miSamples2MSBidentical(0),
mptiDestination(&tiDestination)
{
assert( sizeof(int) >= 4 ); // TDecoder does not run on 16-bit
// platforms
for(int i = 0; i < 3; i++) mpiLastSamplesDiv3[i] = 0;
}
int TDecoder::DeltaDecode(int iDelta)
{
int iPrediction = 4 * mpiLastSamplesDiv3[2] + mpiLastSamplesDiv3[1] -
2 * mpiLastSamplesDiv3[0];
int iDecodedSample = iPrediction + iDelta;
mpiLastSamplesDiv3[0] = mpiLastSamplesDiv3[1];
mpiLastSamplesDiv3[1] = mpiLastSamplesDiv3[2];
mpiLastSamplesDiv3[2] = iDecodedSample / 3;
return iDecodedSample;
}
void TDecoder::Decode(WORD wCode)
{
unsigned uiCode = wCode; // use full 32-bit register width
if( miAbsValueCoded == 1 )
{
miXsample = uiCode;
if (uiCode & 0x8000) miXsample -=0x10000; // unsigned -> int16
// conversion
(*mptiDestination).push_back(miXsample);
mpiLastSamplesDiv3[0] = miXsample/3; // update for
// delta encoding
mpiLastSamplesDiv3[1] = miXsample/3;
mpiLastSamplesDiv3[2] = miXsample/3;
miAbsValueCoded--; // switch back to delta
// encoding
miXsample = 0x0000; // reset buffered sub-word
}
else
{
// a delta encoded value, not necessarily aligned with a word
// boundary has been received
uiCode <<= miXbitsTaken; // shift it left to and combine it with
miXsample |= uiCode; // a buffered rest of preceding iCode:s
miXbitsTaken += 16; // 16 new bits to decode were passed
while( miXbitsTaken >= miBitWidthOfCode )
{
// cut out a complete code; reduce contents of the buffer by
// the code cut out; reduce number of valid bits accordingly
int iSubword = miXsample & mpiABSCODE[miBitWidthOfCode];
int iSignBitMask = 1 << (miBitWidthOfCode - 1);
miXsample >>= miBitWidthOfCode;
miXbitsTaken -= miBitWidthOfCode;
int iMaxBitMask = 3 << (miBitWidthOfCode - 2);
if( iSignBitMask & iSubword)
{
// a negative number was coded; sign extension is needed
// as well for the comparison to mpiALIGNCODE[] as for
// delta decoding
iSubword |= mpiSIGNEXTENSION[miBitWidthOfCode - 1];
}
if( iSubword == mpiOVFLCODE[miBitWidthOfCode - 1] )
{
miBitWidthOfCode++; // increase bit width of code
miSamples2MSBidentical = 0;
}
else if( iSubword == mpiABSCODE[miBitWidthOfCode - 1] )
{
miAbsValueCoded = 1;
miXbitsTaken = 0;
miXsample = 0;
}
else if( iSubword == mpiALIGNCODE[miBitWidthOfCode - 1] )
{
miXbitsTaken = 0;
miXsample = 0;
}
else
{
if( (iSubword & iMaxBitMask) == 0x0000 ||
(iSubword & iMaxBitMask) == iMaxBitMask)
{
miSamples2MSBidentical++;
if ((miSamples2MSBidentical == BIT_REDUCTION_LENGTH) &&
(miBitWidthOfCode > MIN_BIT_WIDTH))
{
miBitWidthOfCode--;
miSamples2MSBidentical = 0;
}
}
else
{
miSamples2MSBidentical = 0;
}
int iNewSample = DeltaDecode( iSubword );
(*mptiDestination).push_back( iNewSample );
}
} // while
}
} // TDecoder::Decode()