JD2022-TU1/main/extern/Raki/Source/RakiTests/Sounds/ADPCMDataProvider_Wii.cpp

194 lines
3.9 KiB
C++

#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