Listing 1: Partial listing of the encoder/compressor encoder.c
static iBitWidthOfCode = 6;
static INT16 iXcode = 0;
static int iXbitsTaken = 0; /* that many bits of iXcode are valid */
static const INT16 piABSCODE[17] =
{
+0x0000, +0x0001, +0x0003, +0x0007, +0x000F, +0x001F, +0x003F, +0x007F,
+0x00FF, +0x01FF, +0x03FF, +0x07FF, +0x0FFF, +0x1FFF, +0x3FFF, +0x7FFF,
(INT16) +0xFFFF
};
static const INT16 piOVFLCODE[16] =
{
+0x0000, +0x0000, +0x0002, +0x0006, +0x000E, +0x001E, +0x003E, +0x007E,
+0x00FE, +0x01FE, +0x03FE, +0x07FE, +0x0FFE, +0x1FFE, +0x3FFE, +0x7FFE
};
static const INT16 piALIGNCODE[16] =
{
-0x0001, -0x0002, -0x0004, -0x0008, -0x0010, -0x0020, -0x0040, -0x0080,
-0x0100, -0x0200, -0x0400, -0x0800, -0x1000, -0x2000, -0x4000, -0x8000
};
static INT32 piLastSamplesDiv3[3] = {0, 0, 0};
void writeCode(int iSample)
{
flash_write((WORD) iSample);
}
void storeX(INT16 iCode)
{
int iEmpty = 16 - iXbitsTaken; /* available bits in the word */
/* storeX() expects a iBitWidthOfCode-bit value;
* however, negative numbers are sign extended up to the 16-bit MSB;
* this sign extension must thus be removed */
iCode &= piABSCODE[iBitWidthOfCode];
if (iEmpty > iBitWidthOfCode) /* more bits available than needed? */
{ /* yes: write entire bit pattern */
iCode <<= iXbitsTaken; /* position new sub-word correctly */
iXcode |= iCode; /* keep it to -or- w. next pattern */
iXbitsTaken += iBitWidthOfCode;
}
else if (iEmpty == iBitWidthOfCode) /* if exactly as much bits are */
{ /* available as needed, then */
iCode <<= iXbitsTaken; /* position new sub-word, */
iCode |= iXcode; /* -or- new sample to kept val */
iXcode = 0x0000; /* reset the kept values */
iXbitsTaken = 0;
writeCode(iCode); /* store new sample + kept val.*/
}
else
{
/* we have to split the bit pattern into two words */
register WORD wTemp = iCode; /* make a copy */
iCode <<= iXbitsTaken; /* position new sub-word */
iCode |= iXcode; /* create the 1st part */
wTemp >>= iEmpty; /* position part two */
iXcode = wTemp; /* and keep it for next write */
iXbitsTaken = iBitWidthOfCode - iEmpty;
writeCode(iCode); /* store 1st part */
}
}
void flushX()
{
/* Check if the buffer of storeX() is not empty. */
if (iXbitsTaken != 0)
{
/* record that the next sample that follows will be aligned at
* WORD boundaries */
storeX(piALIGNCODE[iBitWidthOfCode - 1]);
/* check if the ALIGNCODE already managed the alignment */
if (iXbitsTaken != 0)
{
/* if not, then flush the buffer and enforce the alignment */
writeCode(iXcode);
}
iXcode = 0;
iXbitsTaken = 0;
}
} /* flushX() */
void encoder_flush()
{
flushX();
}
void storeDelta16(INT16 iDeltaCode)
{
static iSamples2MSBidentical = 0;
if ((iDeltaCode >= piOVFLCODE[iBitWidthOfCode - 1]) ||
(iDeltaCode <= piALIGNCODE[iBitWidthOfCode - 1]))
{
/* overflow/underflow: store OVFLCODE and increase bit width */
storeX(piOVFLCODE[iBitWidthOfCode - 1]);
++iBitWidthOfCode;
assert(iBitWidthOfCode < 17);
iSamples2MSBidentical = 0;
storeDelta16(iDeltaCode); /* retry with incr. width */
}
else
{
int iMaxBitMask = 3 << (iBitWidthOfCode - 2);
int iDeltaBitWidthAfterStoring = 0;
if ((iDeltaCode & iMaxBitMask) == 0x0000 ||
(iDeltaCode & iMaxBitMask) == iMaxBitMask)
{
/* the two MSBits of iSample are identical */
iSamples2MSBidentical++;
if ((iSamples2MSBidentical == BIT_REDUCTION_LENGTH) &&
(iBitWidthOfCode > MIN_BIT_WIDTH))
{
/* already the BIT_REDUCTION_LENGTH-th sample where
* MSBit is not in use --> reduce the code width */
iDeltaBitWidthAfterStoring = -1;
iSamples2MSBidentical = 0;
}
}
else
{
iSamples2MSBidentical = 0;
}
storeX(iDeltaCode);
iBitWidthOfCode += iDeltaBitWidthAfterStoring;
}
} /* storeDelta16() */
void encoder_storeADEPT(INT16 iSample)
{
static BOOL bFirstValue = TRUE; /* start-up needed */
INT32 iCodedSample; /* the delta code */
/* estimate the value x'(t) for iSample out of the last
* iSamples x(t-1), x(t-2), x(t-3) with the formula
* x'(t) = -2/3*x(t-3) + 1/3*x(t-2) + 4/3*x(t-1).
* This value x'(t) is taken as basis for the delta encoding */
INT32 iPrediction; /* linear extrapolation */
iPrediction = 4 * piLastSamplesDiv3[2] +
piLastSamplesDiv3[1] -
2 * piLastSamplesDiv3[0];
iCodedSample = iSample - iPrediction; /* delta encoding */
piLastSamplesDiv3[0] = piLastSamplesDiv3[1];
piLastSamplesDiv3[1] = piLastSamplesDiv3[2];
piLastSamplesDiv3[2] = iSample/3; /* div here to prevent overflow */
if ((iCodedSample >= piOVFLCODE[15]) ||
(iCodedSample <= piALIGNCODE[15]) ||
(bFirstValue))
{
/* signal that a 32-bit absolute value follows */
storeX(piABSCODE[iBitWidthOfCode - 1]);
/* check alignment; if not aligned,
* flush the remaining bits of the buffer */
if (iXbitsTaken != 0)
{
writeCode(iXcode);
iXbitsTaken = 0;
iXcode = 0x0000;
}
/* reset delta encoding and store the absolute value */
piLastSamplesDiv3[0] = iSample/3;
piLastSamplesDiv3[1] = iSample/3;
piLastSamplesDiv3[2] = iSample/3;
writeCode(iSample);
bFirstValue = FALSE;
}
else
{
storeDelta16((INT16) iCodedSample);
}
}