public ADPCMStream(RSTMHeader* pRSTM, VoidPtr dataAddr)
{
HEADHeader* pHeader = pRSTM->HEADData;
StrmDataInfo* part1 = pHeader->Part1;
bshort* ynCache = (bshort*)pRSTM->ADPCData->Data;
byte* sPtr;
short[][] coefs;
ADPCMInfo* info;
int loopBlock, loopChunk;
short yn1 = 0, yn2 = 0;
_numChannels = part1->_format._channels;
_isLooped = part1->_format._looped != 0;
_sampleRate = part1->_sampleRate;
_numSamples = part1->_numSamples;
_numBlocks = part1->_numBlocks;
_blockLen = part1->_blockSize;
_loopStartSample = part1->_loopStartSample;
_lastBlockSamples = part1->_lastBlockSamples;
_lastBlockSize = part1->_lastBlockTotal;
_samplesPerBlock = part1->_samplesPerBlock;
_loopEndSample = _numSamples;
_blockStates = new ADPCMState[_numChannels, _numBlocks];
_currentStates = new ADPCMState[_numChannels];
_loopStates = new ADPCMState[_numChannels];
coefs = new short[_numChannels][];
loopBlock = _loopStartSample / _samplesPerBlock;
loopChunk = (_loopStartSample - (loopBlock * _samplesPerBlock)) / 14;
sPtr = (byte*)dataAddr + (loopBlock * _blockLen * _numChannels) + (loopChunk * 8);
//Get channel info
for (int i = 0; i < _numChannels; i++)
{
info = pHeader->GetChannelInfo(i);
//Get channel coefs
coefs[i] = info->Coefs;
//Fill loop state
_loopStates[i] = new ADPCMState(sPtr, info->_lps, info->_lyn1, info->_lyn2, coefs[i]);
//Advance source pointer for next channel
sPtr += _blockLen;
}
//Fill block states in a linear fashion
sPtr = (byte*)dataAddr;
for (int sIndex = 0, bIndex = 0; sIndex < _numSamples; sIndex += _samplesPerBlock, bIndex++)
for (int cIndex = 0; cIndex < _numChannels; cIndex++)
{
if (bIndex > 0) //yn values will be zero if first block
{
yn1 = *ynCache++;
yn2 = *ynCache++;
}
//Get block state
_blockStates[cIndex, bIndex] = new ADPCMState(sPtr, *sPtr, yn1, yn2, coefs[cIndex]); //Use ps from data stream
//Advance address
sPtr += (bIndex == _numBlocks - 1) ? _lastBlockSize : _blockLen;
}
}