public ADPCMStream(RSTMHeader* pRSTM, int channels, int startChannel, 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;
                }

            _numChannels = channels;
            _startChannel = startChannel;
        }
        public static ADPCMStream[] GetStreams(RSTMHeader* pRSTM, VoidPtr dataAddr)
        {
            HEADHeader* pHeader = pRSTM->HEADData;
            StrmDataInfo* part1 = pHeader->Part1;
            int c = part1->_format._channels;
            ADPCMStream[] streams = new ADPCMStream[c.RoundUpToEven() / 2];

            for (int i = 0; i < streams.Length; i++)
            {
                int x = (i + 1) * 2 <= c ? 2 : 1;
                streams[i] = new ADPCMStream(pRSTM, x, i * 2, dataAddr);
            }

            return streams;
        }