[Scummvm-cvs-logs] CVS: tools compress_scumm_bun.cpp,1.29,1.30
Max Horn
fingolfin at users.sourceforge.net
Mon Jan 9 13:03:03 CET 2006
Update of /cvsroot/scummvm/tools
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7544
Modified Files:
compress_scumm_bun.cpp
Log Message:
Sync compress_scumm_bun.cpp with dimuse_codecs.cpp (as a side effect this fixes bug #1400506)
Index: compress_scumm_bun.cpp
===================================================================
RCS file: /cvsroot/scummvm/tools/compress_scumm_bun.cpp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- compress_scumm_bun.cpp 18 Oct 2005 03:00:44 -0000 1.29
+++ compress_scumm_bun.cpp 9 Jan 2006 21:02:14 -0000 1.30
@@ -49,120 +49,93 @@
}
-static byte _destImcTable[89];
-static uint32 _destImcTable2[89 * 64];
+/*
+ * The "IMC" codec below (see cases 13 & 15 in decompressCodec) is actually a
+ * variant of the IMA codec, see also
+ * <http://www.multimedia.cx/simpleaudio.html>
+ *
+ * It is somewhat different, though: the standard ADPCM codecs use a fixed
+ * size for their data packets (4 bits), while the codec implemented here
+ * varies the size of each "packet" between 2 and 7 bits.
+ */
-static const int16 imcTable[] = {
- 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011,
- 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D,
- 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076,
- 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
- 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C,
- 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812,
- 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE,
- 0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
- 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF
+static byte _imcTableEntryBitCount[89];
+
+static const int16 imcTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 16, 17, 19, 21, 23, 25, 28, 31,
+ 34, 37, 41, 45, 50, 55, 60, 66,
+ 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411,
+ 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
+ 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
+ 7132, 7845, 8630, 9493,10442,11487,12635,13899,
+ 15289,16818,18500,20350,22385,24623,27086,29794,
+ 32767
};
-static const byte imxOtherTable[6][128] = {
+static const byte imxOtherTable[6][64] = {
{
- 0xFF, 0x04, 0xFF, 0x04
+ 0xFF,
+ 4
},
-
+
{
- 0xFF, 0xFF, 0x02, 0x08, 0xFF, 0xFF, 0x02, 0x08
+ 0xFF, 0xFF,
+ 2, 8
},
-
+
{
- 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x04, 0x06,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x04, 0x06
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 1, 2, 4, 6
},
-
+
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x02, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x20,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x02, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x20
+ 1, 2, 4, 6, 8, 12, 16, 32
},
-
+
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x20,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x20
+ 1, 2, 4, 6, 8, 10, 12, 14,
+ 16, 18, 20, 22, 24, 26, 28, 32
},
-
+
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32
}
};
-static const byte imxShortTable[] = {
- 0, 0, 1, 3, 7, 15, 31, 63
-};
-
void initializeImcTables() {
- int32 destTablePos = 0;
- int32 pos = 0;
-
- do {
- byte put = 1;
+ int pos;
+
+ for (pos = 0; pos < ARRAYSIZE(imcTable); ++pos) {
+ byte put = 0;
int32 tableValue = ((imcTable[pos] * 4) / 7) / 2;
while (tableValue != 0) {
tableValue /= 2;
put++;
}
- if (put < 3) {
- put = 3;
+ if (put < 2) {
+ put = 2;
}
- if (put > 8) {
- put = 8;
+ if (put > 7) {
+ put = 7;
}
- put--;
- assert(pos < 89);
- _destImcTable[pos] = put;
- } while (++pos <= 88);
- _destImcTable[89] = 0;
-
- for (int n = 0; n < 64; n++) {
- pos = 0;
- destTablePos = n;
- do {
- int32 count = 32;
- int32 put = 0;
- int32 tableValue = imcTable[pos];
- do {
- if ((count & n) != 0) {
- put += tableValue;
- }
- count /= 2;
- tableValue /= 2;
- } while (count != 0);
- assert(destTablePos < 89 * 64);
- _destImcTable2[destTablePos] = put;
- destTablePos += 64;
- } while (++pos <= 88);
+ _imcTableEntryBitCount[pos] = put;
}
}
+
#define NextBit \
do { \
bit = mask & 1; \
@@ -537,91 +510,107 @@
}
{
+ // Decoder for the the IMA ADPCM variants used in COMI.
+ // Contrary to regular IMA ADPCM, this codec uses a variable
+ // bitsize for the encoded data.
+
const int MAX_CHANNELS = 2;
- int32 left, startPos, origLeft, curTableEntry, destPos, esiReg;
+ int32 outputSamplesLeft;
+ int32 destPos;
int16 firstWord;
- byte sByte[MAX_CHANNELS] = {0, 0};
- int32 sDWord1[MAX_CHANNELS] = {0, 0};
- int32 sDWord2[MAX_CHANNELS] = {0, 0};
- int32 tableEntrySum, imcTableEntry, curTablePos, outputWord, adder;
- byte decompTable, otherTablePos, bitMask;
- byte *readPos, *dst;
- uint16 readWord;
-
- assert(0 <= channels && channels <= MAX_CHANNELS);
+ byte initialTablePos[MAX_CHANNELS] = {0, 0};
+ int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7};
+ int32 initialOutputWord[MAX_CHANNELS] = {0, 0};
+ int32 totalBitOffset, curTablePos, outputWord;
+ byte *dst;
+ int i;
+
+ // We only support mono and stereo
+ assert(channels == 1 || channels == 2);
src = comp_input;
dst = comp_output;
- if (channels == 2) {
- output_size = left = 0x2000;
- } else {
- left = 0x1000;
- output_size = 0x2000;
- }
+ output_size = 0x2000;
+ outputSamplesLeft = 0x1000;
+
+ // Every data packet contains 0x2000 bytes of audio data
+ // when extracted. In order to encode bigger data sets,
+ // one has to split the data into multiple blocks.
+ //
+ // Every block starts with a 2 byte word. If that word is
+ // non-zero, it indicates the size of a block of raw audio
+ // data (not encoded) following it. That data we simply copy
+ // to the output buffer and the proceed by decoding the
+ // remaining data.
+ //
+ // If on the other hand the word is zero, then what follows
+ // are 7*channels bytes containing seed data for the decoder.
firstWord = READ_BE_UINT16(src);
src += 2;
if (firstWord != 0) {
+ // Copy raw data
memcpy(dst, src, firstWord);
dst += firstWord;
src += firstWord;
- startPos = 0;
- if (channels == 2) {
- left = 0x2000 - firstWord;
- output_size = left;
- } else {
- left = 0x1000 - (firstWord >> 1);
- output_size = left << 1;
- }
- output_size += firstWord;
+ assert((firstWord & 1) == 0);
+ outputSamplesLeft -= firstWord / 2;
} else {
- startPos = 1;
- for (int i = 0; i < channels; i++) {
- sByte[i] = *(src++);
- sDWord1[i] = READ_BE_UINT32(src);
+ // Read the seed values for the decoder.
+ for (i = 0; i < channels; i++) {
+ initialTablePos[i] = *src;
+ src += 1;
+ initialimcTableEntry[i] = READ_BE_UINT32(src);
src += 4;
- sDWord2[i] = READ_BE_UINT32(src);
+ initialOutputWord[i] = READ_BE_UINT32(src);
src += 4;
}
}
- origLeft = left >> (channels - 1);
- tableEntrySum = 0;
- for (int l = 0; l < channels; l++) {
- if (startPos != 0) {
- curTablePos = sByte[l];
- imcTableEntry = sDWord1[l];
- outputWord = sDWord2[l];
- } else {
- curTablePos = 0;
- imcTableEntry = 7;
- outputWord = 0;
- }
+ totalBitOffset = 0;
+ // The channels are encoded separately.
+ for (int chan = 0; chan < channels; chan++) {
+ // Read initial state (this makes it possible for the data stream
+ // to be split & spread across multiple data chunks.
+ curTablePos = initialTablePos[chan];
+ //imcTableEntry = initialimcTableEntry[chan];
+ outputWord = initialOutputWord[chan];
- left = origLeft;
- destPos = l << 1;
+ // We need to interleave the channels in the output; we achieve
+ // that by using a variables dest offset:
+ destPos = chan * 2;
- if (channels == 2) {
- if (l == 0)
- left++;
- left >>= 1;
- }
+ const int bound = (channels == 1)
+ ? outputSamplesLeft
+ : ((chan == 0)
+ ? (outputSamplesLeft+1) / 2
+ : outputSamplesLeft / 2);
+ for (i = 0; i < bound; ++i) {
+ // Determine the size (in bits) of the next data packet
+ const int32 curTableEntryBitCount = _imcTableEntryBitCount[curTablePos];
+ assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7);
- while (left--) {
- curTableEntry = _destImcTable[curTablePos];
- decompTable = (byte)(curTableEntry - 2);
- bitMask = 2 << decompTable;
- readPos = src + (tableEntrySum >> 3);
- readWord = (uint16)(READ_BE_UINT16(readPos) << (tableEntrySum & 7));
- otherTablePos = (byte)(readWord >> (16 - curTableEntry));
- tableEntrySum += curTableEntry;
- esiReg = ((imxShortTable[curTableEntry] & otherTablePos)
- << (7 - curTableEntry)) + (curTablePos * 64);
- imcTableEntry >>= (curTableEntry - 1);
- adder = imcTableEntry + _destImcTable2[esiReg];
- if ((otherTablePos & bitMask) != 0) {
- adder = -adder;
+ // Read the next data packet
+ const byte *readPos = src + (totalBitOffset >> 3);
+ const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7));
+ const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount));
+
+ // Advance read position to the next data packet
+ totalBitOffset += curTableEntryBitCount;
+
+ // Decode the data packet into a delta value for the output signal.
+ const byte signBitMask = (1 << (curTableEntryBitCount - 1));
+ const byte dataBitMask = (signBitMask - 1);
+ const byte data = (packet & dataBitMask);
+
+ int32 delta = imcTable[curTablePos] * (2 * data + 1) >> (curTableEntryBitCount - 1);
+
+ // The topmost bit in the data packet tells is a sign bit
+ if ((packet & signBitMask) != 0) {
+ delta = -delta;
}
- outputWord += adder;
+
+ // Accumulate the delta onto the output data
+ outputWord += delta;
// Clip outputWord to 16 bit signed, and write it into the destination stream
if (outputWord > 0x7fff)
@@ -629,17 +618,14 @@
if (outputWord < -0x8000)
outputWord = -0x8000;
WRITE_BE_UINT16(dst + destPos, outputWord);
+ destPos += channels << 1;
- // Adjust the curTablePos / imcTableEntry
- assert(decompTable < 6);
- curTablePos += (signed char)imxOtherTable[decompTable][otherTablePos];
- if (curTablePos > 88)
- curTablePos = 88;
+ // Adjust the curTablePos
+ curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data];
if (curTablePos < 0)
curTablePos = 0;
- imcTableEntry = imcTable[curTablePos];
-
- destPos += channels << 1;
+ else if (curTablePos >= ARRAYSIZE(imcTable))
+ curTablePos = ARRAYSIZE(imcTable) - 1;
}
}
}
More information about the Scummvm-git-logs
mailing list