internal PCMStream(WaveInfo* pWAVE, VoidPtr dataAddr)
        {
            _frequency = pWAVE->_sampleRate;
            _numSamples = pWAVE->NumSamples;
            _numChannels = pWAVE->_format._channels;

            _bps = pWAVE->_format._encoding == 0 ? 8 : 16;

            if (_numSamples <= 0) return;

            _loopStart = (int)pWAVE->LoopSample;
            _loopEnd = _numSamples;

            _source = (short*)dataAddr;
            _samplePos = 0;
        }
        public void Init(VoidPtr strmAddr, int strmLen, WaveInfo* info)
        {
            Info = *info;

            _streamBuffer = new UnsafeBuffer(strmLen);
            Memory.Move(_streamBuffer.Address, strmAddr, (uint)strmLen);
            _audioSource = new DataSource(_streamBuffer.Address, _streamBuffer.Length);

            if (info->_format._encoding == 2)
                _stream = new ADPCMStream(info, _audioSource.Address);
            else
                _stream = new PCMStream(info, _audioSource.Address);
        }
        public ADPCMStream(WaveInfo* pWAVE, VoidPtr dataAddr)
        {
            _dataAddress = dataAddr;

            ADPCMInfo*[] info;
            int loopBlock, loopChunk;
            byte* sPtr;

            info = new ADPCMInfo*[_numChannels = pWAVE->_format._channels];
            _currentStates = new ADPCMState[_numChannels];
            _loopStates = new ADPCMState[_numChannels];
            _isLooped = pWAVE->_format._looped != 0;
            _sampleRate = pWAVE->_sampleRate;
            _numSamples = pWAVE->NumSamples;

            if (_numSamples <= 0) return;

            _blockLen = (_numSamples.Align(14) / 14 * 8).Align(0x20);
            _loopStartSample = (int)pWAVE->LoopSample;
            _loopEndSample = _numSamples;

            Init();

            _blockStates = new ADPCMState[_numChannels, _numBlocks];

            loopBlock = _loopStartSample / _samplesPerBlock;
            loopChunk = (_loopStartSample - (loopBlock * _samplesPerBlock)) / 14;

            int x = (loopBlock * _blockLen * _numChannels) + (loopChunk * 8);
            int y = (_loopStartSample / 14 * 8);
            sPtr = (byte*)dataAddr + x;

            //Get channel info
            for (int i = 0; i < _numChannels; i++)
            //{
            //    //sPtr = (byte*)dataAddr + pWAVE->GetChannelInfo(i)->_channelDataOffset + loopStart;
                info[i] = pWAVE->GetADPCMInfo(i);
            //    //Fill loop state
            //    _loopStates[i] = new ADPCMState(sPtr, info[i]->_lps, info[i]->_lyn1, info[i]->_lyn2, info[i]->Coefs);
            //    //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++)
                {
                    //sPtr = (byte*)dataAddr + pWAVE->GetChannelInfo(cIndex)->_channelDataOffset;
                    //Get block state
                    ADPCMInfo* i = info[cIndex];
                    _blockStates[cIndex, bIndex] = new ADPCMState(sPtr, i->_ps, i->_yn1, i->_yn2, i->_lps, i->_lyn1, i->_lyn2, i->Coefs); //Use ps from data stream
                    //Advance address
                    sPtr += (bIndex == _numBlocks - 1) ? _lastBlockSize : _blockLen;
                }
        }