#include "Precompiled.h" #include "RakiTests/Sounds/ADPCMDataProvider_Wii.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( SeekableStream * _stream, const void * _clientData, const u32 _nbChannels, const void * _dspadpcmL, const void * _dspadpcmR ) : AdpcmSoundStreamDataProvider( _nbChannels ) , m_stream( _stream ) , m_nextStream( NULL ) , m_clientData( _clientData ) , m_nextClientData( NULL ) , m_sampleSize( 0 ) , m_dspadpcmL( _dspadpcmL ) , m_dspadpcmR( _dspadpcmR ) { RAKI_ASSERT( m_stream ); RAKI_ASSERT( _dspadpcmL ); DSPADPCM * dspadpcm = (DSPADPCM*)_dspadpcmL; m_sampleSize = (u64)dspadpcm->num_samples; } const u64 ADPCMDataProvider::pullData( void * const _buffer, const u64 _sizeToRead ) { RAKI_ASSERT( m_stream ); return m_stream->stream( _buffer, _sizeToRead ); } const u64 ADPCMDataProvider::getRemainingByteSize() const { if ( m_stream ) { u64 size = m_stream->getSize(); u64 position = m_stream->getCurrentPos(); RAKI_ASSERT( position <= size ); return ( size - position ); } return 0; } void ADPCMDataProvider::prefetchNextStream() { } void ADPCMDataProvider::setNextStreamNow() { 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; } m_isFirstBuffer = true; } const u64 ADPCMDataProvider::getEntireSampleSize() const { return m_sampleSize; } const u64 ADPCMDataProvider::getEntireByteSize() const { return m_stream ? m_stream->getSize() : 0; } void ADPCMDataProvider::setNextStream( SeekableStream * _nextStream, void * _nextClientData ) { m_nextStream = _nextStream; m_nextClientData = _nextClientData; } const u64 ADPCMDataProvider::getCurrentSamplePosition() const { u64 position = m_stream ? m_stream->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; default: RAKI_ASSERT_FALSE; return NULL; } } void ADPCMDataProvider::update( bool /*_launchNewReadRequests*/ ) { } u64 ADPCMDataProvider::getByteBlockPosition( const u64 _startSamplePosition ) const { // ADPCM is 14 samples per 8 byte block u64 adpcmBlockNumber = 0; adpcmBlockNumber = _startSamplePosition / 14; u64 bytePosition = adpcmBlockNumber * 8 * getNbChannels(); return bytePosition; } } // namespace raki