Descent3/libacm/libacm.cpp
Azamat H. Hackimov 9e6ebbc8fb Remove dublicate byteswap.h
Linux-specific byteswap.h just includes BYTESWAP.H, so there no need platform-specific header.

Fixes "non-portable path to file" ([-Wnonportable-include-path]) warnings.
2024-04-18 03:20:36 +03:00

1090 lines
34 KiB
C++

// Interplay ACM audio codec decoder
//
// Based on code from the decoder source of libacm, licensed under a minimal BSD/ISC license:
// Copyright (c) 2004-2008, Marko Kreen
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "Adecode.h"
#include <stdlib.h>
#ifdef MACOSX
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif
#include <cstring>
#include "pserror.h"
#include "byteswap.h"
using namespace AudioDecoder;
namespace {
// default memory allocation function
void *DefaultMalloc(uint32 size) { return malloc(size); }
// default memory release function
void DefaultFree(void *pPtr) { free(pPtr); }
// Constants
const uint32 kBitBufferSize = 64 * 1024;
const uint32 kNumAmpSamples = 64 * 1024;
const uint32 kACMId = 0x032897;
const uint32 kACMVersion = 1;
// Internal Classes
struct ACMInfo {
uint32 m_id;
uint32 m_version;
uint32 m_sampleCount;
uint32 m_numChannels;
uint32 m_sampleRate;
uint32 m_level;
uint32 m_columns;
uint32 m_rows;
};
class InternalAudioDecoder : public IAudioDecoder {
public:
InternalAudioDecoder(ReadDataFunction readerFunction, void *pReaderData);
~InternalAudioDecoder();
// Extract the header information
const ACMInfo &GetHeader() const { return m_acm; }
// Initialize the decoder
bool Initialize();
// Read data from the audio decoder.
// pBuffer: The buffer to receive the data from
// amount: How much data to read
// Returns the number of bytes read - zero when we're at the end of the file
uint32 Read(void *pBuffer, uint32 amount);
// Operator overloads
void *operator new(size_t numBytes);
void operator delete(void *pPtr);
// Unpackers
static bool UnpackZeroFill(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackIgnore(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackLinear(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK13(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK12(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK24(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK23(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK35(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK34(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK45(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackK44(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackT15(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackT27(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static bool UnpackT37(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static void SetMemoryFunctions(MemoryAllocFunc memAlloc, MemoryFreeFunc memFree);
private:
// Read data from the read function
sint32 ReadData(void *pBuffer, uint32 amount);
uint32 InternalRead(void *pBuffer, uint32 amount);
bool LoadBitBufferFromFile();
bool LoadBitBuffer();
bool ReloadBits(uint32 bits, uint32 &newData, bool &hitEOF);
bool GetBits(uint32 bits, uint32 &resultData);
bool GetBitsEOF(uint32 bits, uint32 &resultData, bool &hadEOF);
bool DecodeBlock(bool &atEOF);
bool UnpackBlock(bool &atEOF);
void OutputValues(const sint32 *pSrcData, void *pBuffer, uint32 numWords);
void JuggleBlock();
ACMInfo m_acm;
ReadDataFunction m_readerFunction;
void *m_pReaderData;
uint8 *m_pFileBitBuffer;
uint32 m_bitBufferAvailableSize;
uint32 m_bitBufferCurrPos;
uint32 m_numBitsAvailable;
uint32 m_bitData;
uint32 m_blockLengthInSamples;
uint32 m_wrapBufferLength;
sint32 *m_pBlock;
sint32 *m_pWrapBuffer;
sint32 *m_pAmpBuffer;
sint32 *m_pMidBuffer;
bool m_blockReady;
bool m_bitBufferAtEOF;
uint32 m_streamPos;
uint32 m_blockPos;
// Memory management
void *m_pMemoryBuffer;
static MemoryAllocFunc s_Malloc;
static MemoryFreeFunc s_Free;
};
// Tables
const sint32 gMap1Bit[] = {-1, +1};
const sint32 gMap2BitNear[] = {-2, -1, +1, +2};
const sint32 gMap2BitFar[] = {-3, -2, +2, +3};
const sint32 gMap3Bit[] = {-4, -3, -2, -1, +1, +2, +3, +4};
const uint16 gMul3x3[27] = {
0x0000, 0x0001, 0x0002, 0x0010, 0x0011, 0x0012, 0x0020, 0x0021, 0x0022, 0x0100, 0x0101, 0x0102, 0x0110, 0x0111,
0x0112, 0x0120, 0x0121, 0x0122, 0x0200, 0x0201, 0x0202, 0x0210, 0x0211, 0x0212, 0x0220, 0x0221, 0x0222,
};
const uint16 gMul3x5[125] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0020, 0x0021, 0x0022, 0x0023,
0x0024, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0100, 0x0101, 0x0102,
0x0103, 0x0104, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0130, 0x0131,
0x0132, 0x0133, 0x0134, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0210,
0x0211, 0x0212, 0x0213, 0x0214, 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0230, 0x0231, 0x0232, 0x0233, 0x0234,
0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0310, 0x0311, 0x0312, 0x0313,
0x0314, 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0340, 0x0341, 0x0342,
0x0343, 0x0344, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0420, 0x0421,
0x0422, 0x0423, 0x0424, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444,
};
const uint8 gMul2x11[121] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4A, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
0x66, 0x67, 0x68, 0x69, 0x6A, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x80, 0x81,
0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9A, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA};
} // namespace
/**************************************************************/
/* Interface Functions */
/**************************************************************/
// Optional interface for supplying your own malloc and free functions
// Default is to use standard malloc and free.
void RegisterMemoryFunctions(MemoryAllocFunc memAlloc, MemoryFreeFunc memFree) {
InternalAudioDecoder::SetMemoryFunctions(memAlloc, memFree);
}
// Create an audio decoder
// You supply a function for reading bytes from the compressed data via a
// void* pData handle, and the handle itself (typically a FILE *).
// Create_AudioDecoder returns a new AudioDecoder which can be used to
// read uncompressed decoded data from the compressed stream,
// and also returns the number of channels (1 or 2), the sample rate
// (e.g. 22050), and the number of samples contained in the compressed file
// (in case you want to pre-allocate a buffer to load them all into memory).
IAudioDecoder *AudioDecoder::CreateDecoder(ReadDataFunction readerFunction, void *pReaderData, uint32 &numChannels,
uint32 &sampleRate, uint32 &sampleCount) {
// allocate our decoder
InternalAudioDecoder *pDecoder = new InternalAudioDecoder(readerFunction, pReaderData);
if (pDecoder == NULL)
return NULL;
// initialize
if (!pDecoder->Initialize()) {
// Failed
delete pDecoder;
return NULL;
}
// extract the header information for the caller
const ACMInfo &header = pDecoder->GetHeader();
numChannels = header.m_numChannels;
sampleRate = header.m_sampleRate;
sampleCount = header.m_sampleCount;
// return the decoder back to the user
return pDecoder;
}
/**************************************************************/
/* Memory Management */
/**************************************************************/
// Static memory
MemoryAllocFunc InternalAudioDecoder::s_Malloc = DefaultMalloc;
MemoryFreeFunc InternalAudioDecoder::s_Free = DefaultFree;
void InternalAudioDecoder::SetMemoryFunctions(MemoryAllocFunc memAlloc, MemoryFreeFunc memFree) {
if ((memAlloc && !memFree) || (!memAlloc && memFree))
return;
s_Malloc = (memAlloc) ? memAlloc : DefaultMalloc;
s_Free = (memFree) ? memFree : DefaultFree;
}
void *InternalAudioDecoder::operator new(size_t numBytes) { return s_Malloc(static_cast<uint32>(numBytes)); }
void InternalAudioDecoder::operator delete(void *pPtr) {
if (pPtr) {
s_Free(pPtr);
}
}
/**************************************************************/
/* Construction */
/**************************************************************/
InternalAudioDecoder::InternalAudioDecoder(ReadDataFunction readerFunction, void *pReaderData)
: m_readerFunction(readerFunction), m_pReaderData(pReaderData), m_pFileBitBuffer(NULL), m_bitBufferAvailableSize(0),
m_bitBufferCurrPos(0), m_numBitsAvailable(0), m_bitData(0), m_blockLengthInSamples(0), m_wrapBufferLength(0),
m_pBlock(NULL), m_pWrapBuffer(NULL), m_pAmpBuffer(NULL), m_pMidBuffer(NULL), m_blockReady(false),
m_bitBufferAtEOF(false), m_streamPos(0), m_blockPos(0), m_pMemoryBuffer(NULL) {
std::memset(&m_acm, 0, sizeof(m_acm));
}
// Initialize the decoder
bool InternalAudioDecoder::Initialize() {
// Allocate the bit buffer before we start reading it
m_pFileBitBuffer = reinterpret_cast<uint8 *>(s_Malloc(kBitBufferSize));
if (!m_pFileBitBuffer)
return false;
// Read in the ACM header
if (!GetBits(24, m_acm.m_id))
return false;
if (m_acm.m_id != kACMId)
return false;
if (!GetBits(8, m_acm.m_version))
return false;
if (m_acm.m_version != kACMVersion)
return false;
// total value count
uint32 temp;
if (!GetBits(16, m_acm.m_sampleCount))
return false;
if (!GetBits(16, temp))
return false;
m_acm.m_sampleCount += temp << 16;
if (m_acm.m_sampleCount == 0)
return false;
// num channels
if (!GetBits(16, m_acm.m_numChannels))
return false;
if (m_acm.m_numChannels < 1 || m_acm.m_numChannels > 2)
return false;
// sample rate
if (!GetBits(16, m_acm.m_sampleRate))
return false;
if (m_acm.m_sampleRate < 4096)
return false;
// level
if (!GetBits(4, m_acm.m_level))
return false;
// rows
if (!GetBits(12, m_acm.m_rows))
return false;
if (m_acm.m_rows == 0)
return false;
// Calculate the blocks
m_acm.m_columns = 1 << m_acm.m_level;
m_wrapBufferLength = 2 * m_acm.m_columns - 2;
m_blockLengthInSamples = m_acm.m_rows * m_acm.m_columns;
// Calculate the amount of memory that needs to be allocated
const size_t blockMemSize = m_blockLengthInSamples * sizeof(uint32);
const size_t wrapMemSize = m_wrapBufferLength * sizeof(uint32);
const size_t ampMemSize = kNumAmpSamples * sizeof(uint32);
const size_t totalMemSize = blockMemSize + wrapMemSize + ampMemSize;
m_pMemoryBuffer = s_Malloc(static_cast<uint32>(totalMemSize));
if (m_pMemoryBuffer == NULL)
return false;
// Assign buffer pointers
m_pBlock = reinterpret_cast<sint32 *>(m_pMemoryBuffer);
m_pWrapBuffer = reinterpret_cast<sint32 *>(m_pBlock + m_blockLengthInSamples);
m_pAmpBuffer = reinterpret_cast<sint32 *>(m_pWrapBuffer + m_wrapBufferLength);
m_pMidBuffer = reinterpret_cast<sint32 *>(m_pAmpBuffer + (kNumAmpSamples >> 1));
// Initialize data buffers
std::memset(m_pWrapBuffer, 0, m_wrapBufferLength * sizeof(uint32));
// Lets get going
return true;
}
/**************************************************************/
/* Destruction */
/**************************************************************/
InternalAudioDecoder::~InternalAudioDecoder() {
if (m_pMemoryBuffer) {
s_Free(m_pMemoryBuffer);
}
if (m_pFileBitBuffer) {
s_Free(m_pFileBitBuffer);
}
}
/**************************************************************/
/* Reading */
/**************************************************************/
// Read data from the audio decoder.
// pBuffer: The buffer to receive the data from
// amount: How much data to read
// Returns the number of bytes read - zero when we're at the end of the file
uint32 InternalAudioDecoder::Read(void *pBuffer, uint32 amount) {
uint32 totalBytesRead = 0;
uint8 *pBuf = reinterpret_cast<uint8 *>(pBuffer);
do {
uint32 numWords = amount >> 1;
if (m_streamPos + numWords > m_acm.m_sampleCount) {
// Don't read past the end of file
numWords = m_acm.m_sampleCount - m_streamPos;
}
if (m_acm.m_numChannels > 1) {
// Read full channel data
numWords -= numWords & 1;
}
if (numWords == 0)
break;
uint32 res = InternalRead(pBuf, numWords << 1);
if (res == 0)
break;
pBuf += res;
amount -= res;
totalBytesRead += res;
} while (amount > 0);
return totalBytesRead;
}
uint32 InternalAudioDecoder::InternalRead(void *pBuffer, uint32 amount) {
// Check for End-of-File
if (m_streamPos >= m_acm.m_sampleCount)
return 0;
uint32 numWords = amount >> 1;
if (!m_blockReady) {
bool atEOF;
if (!DecodeBlock(atEOF)) {
// TODO: Report proper error?
return atEOF ? 0 : 0;
}
}
uint32 numAvailableWords = m_blockLengthInSamples - m_blockPos;
if (numAvailableWords < numWords) {
// Don't read too past the end of the block
numWords = numAvailableWords;
}
if (m_streamPos + numWords > m_acm.m_sampleCount) {
// Don't read past the end of file
numWords = m_acm.m_sampleCount - m_streamPos;
}
if (m_acm.m_numChannels > 1) {
// Read full channel data
numWords -= numWords & 1;
}
const sint32 *pSrcData = m_pBlock + m_blockPos;
OutputValues(pSrcData, pBuffer, numWords);
m_streamPos += numWords;
m_blockPos += numWords;
if (m_blockPos == m_blockLengthInSamples) {
m_blockReady = false;
}
return numWords << 1;
}
/**************************************************************/
/* Output */
/**************************************************************/
void InternalAudioDecoder::OutputValues(const sint32 *pSrcData, void *pBuffer, uint32 numWords) {
uint8 *pDst = reinterpret_cast<uint8 *>(pBuffer);
const uint32 shiftAmount = m_acm.m_level;
while (numWords--) {
sint32 src = *pSrcData++;
sint32 val = INTEL_INT(src) >> shiftAmount;
*pDst++ = val & 0xFF;
*pDst++ = (val >> 8) & 0xFF;
}
}
/**************************************************************/
/* Decoding */
/**************************************************************/
bool InternalAudioDecoder::DecodeBlock(bool &atEOF) {
// Reset block state
m_blockReady = false;
m_blockPos = 0;
// Read in data
uint32 bitPower;
if (!GetBitsEOF(4, bitPower, atEOF))
return false;
uint32 bitValue;
if (!GetBitsEOF(16, bitValue, atEOF))
return false;
// Process
sint32 x;
uint32 i, count = 1 << bitPower;
for (i = 0, x = 0; i < count; ++i) {
m_pMidBuffer[i] = x;
x += bitValue;
}
for (i = 1, x = -static_cast<sint32>(bitValue); i <= count; ++i) {
m_pMidBuffer[-static_cast<sint32>(i)] = x;
x -= bitValue;
}
if (!UnpackBlock(atEOF))
return false;
JuggleBlock();
m_blockReady = true;
return true;
}
static void Juggle(sint32 *pWrap, sint32 *pBlock, uint32 subLen, uint32 subCount) {
for (uint32 i = 0; i < subLen; ++i) {
sint32 *pPtr = pBlock;
sint32 r0 = pWrap[0];
sint32 r1 = pWrap[1];
uint32 cnt = subCount >> 1;
for (uint32 j = 0; j < cnt; ++j) {
sint32 r2 = *pPtr;
*pPtr = (r1 << 1) + (r0 + r2);
pPtr += subLen;
sint32 r3 = *pPtr;
*pPtr = (r2 << 1) - (r1 + r3);
pPtr += subLen;
r0 = r2;
r1 = r3;
}
*pWrap++ = r0;
*pWrap++ = r1;
++pBlock;
}
}
void InternalAudioDecoder::JuggleBlock() {
// check subblock length
if (m_acm.m_level == 0)
return;
// Apply juggle() (rows)x(cols)
// from (step_subcount * 2) x (subblock_len/2)
// to (step_subcount * subblock_len) x (1)
const uint32 stepSubCount = (m_acm.m_level > 9) ? 1 : ((2048 >> m_acm.m_level) - 2);
uint32 todoCount = m_acm.m_rows;
sint32 *pBlock = m_pBlock;
while (true) {
sint32 *pWrap = m_pWrapBuffer;
uint32 subCount = stepSubCount;
if (subCount > todoCount) {
subCount = todoCount;
}
uint32 subLen = m_acm.m_columns >> 1;
subCount <<= 1;
Juggle(pWrap, pBlock, subLen, subCount);
pWrap += subLen << 1;
uint32 i;
sint32 *pPtr;
for (i = 0, pPtr = pBlock; i < subCount; ++i) {
++pPtr[0];
pPtr += subLen;
}
while (subLen > 1) {
subLen >>= 1;
subCount <<= 1;
Juggle(pWrap, pBlock, subLen, subCount);
pWrap += subLen << 1;
}
if (todoCount <= stepSubCount)
break;
todoCount -= stepSubCount;
pBlock += stepSubCount << m_acm.m_level;
}
}
/**************************************************************/
/* Unpacking */
/**************************************************************/
bool InternalAudioDecoder::UnpackZeroFill(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
const sint32 midZero = decoder.m_pMidBuffer[0];
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
const uint32 pos = (i << level) + col;
pBlock[pos] = midZero;
}
return true;
}
bool InternalAudioDecoder::UnpackIgnore(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
return true;
}
bool InternalAudioDecoder::UnpackLinear(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 middleIndex = 1 << (id - 1);
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(id, offset, atEOF))
return false;
const uint32 pos = (i << level) + col;
pBlock[pos] = decoder.m_pMidBuffer[offset - middleIndex];
}
return true;
}
bool InternalAudioDecoder::UnpackK13(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 flag;
if (!decoder.GetBitsEOF(1, flag, atEOF))
return false;
if (flag == 0) {
pBlock[(i++ << level) + col] = midZero;
if (i >= numRows)
break;
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, flag, atEOF))
return false;
if (flag == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, flag, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap1Bit[flag]];
}
return true;
}
bool InternalAudioDecoder::UnpackK12(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap1Bit[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackK24(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i++ << level) + col] = midZero;
if (i >= numRows)
break;
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(2, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap2BitNear[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackK23(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(2, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap2BitNear[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackK35(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i++ << level) + col] = midZero;
if (i >= numRows)
break;
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap1Bit[offset]];
continue;
}
if (!decoder.GetBitsEOF(2, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap2BitFar[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackK34(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap1Bit[offset]];
continue;
}
if (!decoder.GetBitsEOF(2, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap2BitFar[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackK45(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i++ << level) + col] = midZero;
if (i >= numRows)
break;
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(3, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap3Bit[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackK44(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const sint32 midZero = decoder.m_pMidBuffer[0];
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(1, offset, atEOF))
return false;
if (offset == 0) {
pBlock[(i << level) + col] = midZero;
continue;
}
if (!decoder.GetBitsEOF(3, offset, atEOF))
return false;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[gMap3Bit[offset]];
}
return true;
}
bool InternalAudioDecoder::UnpackT15(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(5, offset, atEOF))
return false;
uint32 n1 = (gMul3x3[offset] & 0x0F) - 1;
uint32 n2 = ((gMul3x3[offset] >> 4) & 0x0F) - 1;
uint32 n3 = ((gMul3x3[offset] >> 8) & 0x0F) - 1;
pBlock[(i++ << level) + col] = decoder.m_pMidBuffer[n1];
if (i >= numRows)
break;
pBlock[(i++ << level) + col] = decoder.m_pMidBuffer[n2];
if (i >= numRows)
break;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[n3];
}
return true;
}
bool InternalAudioDecoder::UnpackT27(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(7, offset, atEOF))
return false;
uint32 n1 = (gMul3x5[offset] & 0x0F) - 2;
uint32 n2 = ((gMul3x5[offset] >> 4) & 0x0F) - 2;
uint32 n3 = ((gMul3x5[offset] >> 8) & 0x0F) - 2;
pBlock[(i++ << level) + col] = decoder.m_pMidBuffer[n1];
if (i >= numRows)
break;
pBlock[(i++ << level) + col] = decoder.m_pMidBuffer[n2];
if (i >= numRows)
break;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[n3];
}
return true;
}
bool InternalAudioDecoder::UnpackT37(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF) {
const uint32 numRows = decoder.m_acm.m_rows;
const uint32 level = decoder.m_acm.m_level;
sint32 *pBlock = decoder.m_pBlock;
for (uint32 i = 0; i < numRows; ++i) {
uint32 offset;
if (!decoder.GetBitsEOF(7, offset, atEOF))
return false;
uint32 n1 = (gMul2x11[offset] & 0x0F) - 5;
uint32 n2 = ((gMul2x11[offset] >> 4) & 0x0F) - 5;
pBlock[(i++ << level) + col] = decoder.m_pMidBuffer[n1];
if (i >= numRows)
break;
pBlock[(i << level) + col] = decoder.m_pMidBuffer[n2];
}
return true;
}
typedef bool (*UnpackerFunction)(InternalAudioDecoder &decoder, uint32 id, uint32 col, bool &atEOF);
static const UnpackerFunction Unpacker[] = {
InternalAudioDecoder::UnpackZeroFill, InternalAudioDecoder::UnpackIgnore, InternalAudioDecoder::UnpackIgnore,
InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear,
InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear,
InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear,
InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear,
InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackLinear, InternalAudioDecoder::UnpackK13,
InternalAudioDecoder::UnpackK12, InternalAudioDecoder::UnpackT15, InternalAudioDecoder::UnpackK24,
InternalAudioDecoder::UnpackK23, InternalAudioDecoder::UnpackT27, InternalAudioDecoder::UnpackK35,
InternalAudioDecoder::UnpackK34, InternalAudioDecoder::UnpackIgnore, InternalAudioDecoder::UnpackK45,
InternalAudioDecoder::UnpackK44, InternalAudioDecoder::UnpackIgnore, InternalAudioDecoder::UnpackT37,
InternalAudioDecoder::UnpackIgnore, InternalAudioDecoder::UnpackIgnore,
};
bool InternalAudioDecoder::UnpackBlock(bool &atEOF) {
for (uint32 i = 0; i < m_acm.m_columns; ++i) {
uint32 unpackerId;
if (!GetBitsEOF(5, unpackerId, atEOF))
return false;
// Jump to the unpacker
if (!Unpacker[unpackerId](*this, unpackerId, i, atEOF))
return false;
}
return true;
}
/**************************************************************/
/* Loading Data */
/**************************************************************/
bool InternalAudioDecoder::LoadBitBufferFromFile() {
if (m_bitBufferAtEOF)
return true;
// Callback to the user to get more data
sint32 res = m_readerFunction(m_pReaderData, m_pFileBitBuffer, kBitBufferSize);
if (res < 0)
return false;
if (res == 0) {
// No more data
m_bitBufferAtEOF = true;
m_pFileBitBuffer[0] = 0;
m_bitBufferAvailableSize = 1;
} else {
// We still have data
m_bitBufferAvailableSize = static_cast<uint32>(res);
}
m_bitBufferCurrPos = 0;
return true;
}
bool InternalAudioDecoder::LoadBitBuffer() {
uint32 numLoadedBits = 0; // How many bits are still available
uint32 loadedDataBits = 0; // The bit data still available
// How many bytes of data remain?
const uint32 bufferRemaining = m_bitBufferAvailableSize - m_bitBufferCurrPos;
ASSERT(bufferRemaining < 4);
// Bring in the remaining bits from the buffer
const uint8 *pCurrBuffer = m_pFileBitBuffer + m_bitBufferCurrPos;
switch (bufferRemaining) {
case 3:
loadedDataBits += pCurrBuffer[2] << 16;
case 2:
loadedDataBits += pCurrBuffer[1] << 8;
case 1:
loadedDataBits += pCurrBuffer[0];
}
numLoadedBits = bufferRemaining << 3;
// Fill back up the file buffer
if (!LoadBitBufferFromFile())
return false;
// Bring in the rest of the bits that we can to fill up the 32 bits (or
// when we run out of available buffer)
while (numLoadedBits < 32) {
if (m_bitBufferAvailableSize - m_bitBufferCurrPos == 0)
break;
// Bring in the next byte
loadedDataBits |= m_pFileBitBuffer[m_bitBufferCurrPos] << numLoadedBits;
numLoadedBits += 8;
++m_bitBufferCurrPos;
}
// Continue with processing
m_bitData = loadedDataBits;
m_numBitsAvailable = numLoadedBits;
return true;
}
// Reloads the available bits back to a full 32
bool InternalAudioDecoder::ReloadBits(uint32 bits, uint32 &newData, bool &hitEOF) {
ASSERT(bits > m_numBitsAvailable);
hitEOF = false;
// Bring in the bits that we can
uint32 currBitData = m_bitData;
uint32 numLoadedBits = m_numBitsAvailable;
bits -= numLoadedBits;
// Bring in more bits from the buffer
uint32 bitData, bitsAvail;
if ((m_bitBufferAvailableSize - m_bitBufferCurrPos) >= 4) {
// We have a full 32bits available
uint8 *pCurrBuffer = m_pFileBitBuffer + m_bitBufferCurrPos;
m_bitBufferCurrPos += 4;
bitData = pCurrBuffer[0] + (pCurrBuffer[1] << 8) + (pCurrBuffer[2] << 16) + (pCurrBuffer[3] << 24);
bitsAvail = 32;
} else {
// We're almost out of buffer space - fill it back up
if (!LoadBitBuffer())
return false;
if (m_numBitsAvailable < bits) {
// Unexpected EOF
hitEOF = true;
return false;
}
bitData = m_bitData;
bitsAvail = m_numBitsAvailable;
}
// Fold in the bits necessary to fill back up
currBitData |= (bitData & ((1 << bits) - 1)) << numLoadedBits;
m_bitData = bitData >> bits;
m_numBitsAvailable = bitsAvail - bits;
newData = currBitData;
return true;
}
/**************************************************************/
/* Data Retrieval */
/**************************************************************/
bool InternalAudioDecoder::GetBits(uint32 bits, uint32 &resultData) {
if (m_numBitsAvailable >= bits) {
// We have enough data to pull from
resultData = m_bitData & ((1 << bits) - 1);
m_bitData >>= bits;
m_numBitsAvailable -= bits;
return true;
}
// Reload our bitData
bool hadEOF;
bool res = ReloadBits(bits, resultData, hadEOF);
ASSERT(!hadEOF);
return res;
}
bool InternalAudioDecoder::GetBitsEOF(uint32 bits, uint32 &resultData, bool &hadEOF) {
if (m_numBitsAvailable >= bits) {
// We have enough data to pull from
resultData = m_bitData & ((1 << bits) - 1);
m_bitData >>= bits;
m_numBitsAvailable -= bits;
return true;
}
// Reload our bitData
return ReloadBits(bits, resultData, hadEOF);
}