#include "Precompiled.h" #include "RakiTests/Sounds/ADPCMDataProvider_Cafe.h" #include "RakiEngine/Data/Stream/AsyncReadStreamer.h" #include "RakiEngine/Data/Stream/SeekableStream.h" namespace raki { typedef struct { // for header generation during decode u32 num_samples; // total number of RAW samples u32 num_adpcm_nibbles; // number of ADPCM nibbles (including frame headers) u32 sample_rate; // Sample rate, in Hz // DSP addressing and decode context u16 loop_flag; // 1=LOOPED, 0=NOT LOOPED u16 format; // Always 0x0000, for ADPCM u32 sa; // Start offset address for looped samples (zero for non-looped) u32 ea; // End offset address for looped samples u32 ca; // always zero u16 coef[16]; // decode coefficients (eight pairs of 16-bit words) // DSP decoder initial state u16 gain; // always zero for ADPCM u16 ps; // predictor/scale u16 yn1; // sample history u16 yn2; // sample history // DSP decoder loop context u16 lps; // predictor/scale for loop context u16 lyn1; // sample history (n-1) for loop context u16 lyn2; // sample history (n-2) for loop context u16 pad[11]; // reserved } DSPADPCM; ADPCMDataProvider::ADPCMDataProvider( AsyncReadStreamer * _asyncReadStreamer, void * _clientData, const u32 _nbChannels, const bool _isLooping, const void * _dspadpcmL, const void * _dspadpcmR ) : AdpcmSoundStreamDataProvider( _nbChannels ) , m_isLooping( _isLooping ) , m_asyncReadStreamer( _asyncReadStreamer ) , m_nextStream( NULL ) , m_clientData( _clientData ) , m_nextClientData( NULL ) , m_dspadpcmL( _dspadpcmL ) , m_dspadpcmR( _dspadpcmR ) , m_sampleSize( 0 ) , m_nextDspadpcmL( NULL ) , m_nextDspadpcmR( NULL ) { RAKI_ASSERT( m_asyncReadStreamer ); RAKI_ASSERT( _dspadpcmL ); DSPADPCM * dspadpcm = (DSPADPCM*)_dspadpcmL; m_sampleSize = (u64)dspadpcm->num_samples; } u64 ADPCMDataProvider::pullData( void * _buffer, const u64 _sizeToRead ) { RAKI_ASSERT( m_asyncReadStreamer ); return m_asyncReadStreamer->stream( _buffer, _sizeToRead ); } u64 ADPCMDataProvider::getRemainingByteSize() const { if ( m_asyncReadStreamer ) { u64 size = m_asyncReadStreamer->getSize(); u64 position = m_asyncReadStreamer->getCurrentPos(); RAKI_ASSERT( position <= size ); return ( size - position ); } return 0; } /* SoundStreamDataProvider * ADPCMDataProvider::getNextDataProvider() { if ( m_nextStream ) { m_nextStream->m_stream->seekBeginning(); m_nextStream->m_isFirstBuffer = true; return m_nextStream; } m_stream->seekBeginning(); m_isFirstBuffer = true; return this; } */ void ADPCMDataProvider::prefetchNextStream() { RAKI_OUTPUT("ADPCMDataProvider::prefetchNextStream m_asyncReadStreamer 0x%x && m_nextStream 0x%x", m_asyncReadStreamer, m_nextStream ) if ( m_asyncReadStreamer && m_nextStream ) { if ( m_nextStream ) m_nextStream->seek( 0, SeekableStream::fromBeginning ); m_asyncReadStreamer->setStreamData( NULL, 0, m_nextStream, m_nextClientData ); RAKI_ASSERT( m_nextDspadpcmL ); if ( m_dspadpcmR ) { RAKI_ASSERT( m_nextDspadpcmR ); } m_dspadpcmL = m_nextDspadpcmL; m_dspadpcmR = m_nextDspadpcmR; m_clientData = m_nextClientData; } } void ADPCMDataProvider::setNextStreamNow() { m_asyncReadStreamer->seekBeginning(); /* if ( m_nextStream ) { m_nextStream->seekBeginning(); m_stream = m_nextStream; m_clientData = m_nextClientData; m_nextStream = NULL; m_nextClientData = NULL; } else { m_stream = NULL; m_clientData = NULL; } */ } u64 ADPCMDataProvider::getEntireSampleSize() const { return m_sampleSize; } u64 ADPCMDataProvider::getEntireByteSize() const { return m_asyncReadStreamer ? m_asyncReadStreamer->getSize() : 0; } void ADPCMDataProvider::setNextStream( SeekableStream * _nextStream, const void * _nextDspadpcmL, const void * _nextDspadpcmR, const void * _nextClientData ) { m_nextStream = _nextStream; m_nextClientData = _nextClientData; m_nextDspadpcmL = _nextDspadpcmL; m_nextDspadpcmR = _nextDspadpcmR; } u64 ADPCMDataProvider::getCurrentSamplePosition() const { u64 position = m_asyncReadStreamer ? m_asyncReadStreamer->getCurrentPos() : 0; return 14 * position / ( m_dspadpcmR ? 16 : 8 ); } const void * ADPCMDataProvider::getClientData() const { return m_clientData; } const void * ADPCMDataProvider::getDspadpcm( const u32 _channel ) const { switch ( _channel ) { case 0: return m_dspadpcmL; case 1: return m_dspadpcmR; } return NULL; } void ADPCMDataProvider::update( bool _launchNewReadRequests ) { } u64 ADPCMDataProvider::getByteBlockPosition( const u64 _startSamplePosition ) const { // ADPCM is 14 samples per 8 byte block // truncate sample position to the start of the ADPCM block u64 adpcmBlockNumber = 0; adpcmBlockNumber = _startSamplePosition / 14; u64 bytePosition = adpcmBlockNumber * 8 * getNbChannels(); return bytePosition; } } // namespace raki