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

237 lines
5.2 KiB
C++

#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