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

247 lines
6.1 KiB
C++

#include "Precompiled.h"
#include "RakiTests/Sounds/XMA2DataProvider.h"
#include "RakiEngine/Data/Stream/AsyncReadStreamer.h"
#include "RakiEngine/Data/Stream/SeekableStream.h"
namespace raki
{
XMA2DataProvider::XMA2DataProvider( AsyncReadStreamer * _asyncReadStreamer, XMA2WAVEFORMATEX * const _xma2Format, u32 * const _seekTable,
const u32 _seekTableSize, const u32 _sizeInTicks, const u32 _sizeInBars, const u32 _nbBeatsPerBar, const u32 _nbChannels,
const u64 _samplePositionBeforeSubmit )
: SoundStreamDataProvider( _nbChannels )
, m_asyncReadStreamer( _asyncReadStreamer )
, m_nextStream( NULL )
, m_sampleSize( 0 )
, m_xma2Format( _xma2Format )
, m_seekTable( _seekTable )
, m_nbBlocks( _seekTableSize / sizeof( u32 ) )
, m_clientData( NULL )
, m_nextClientData( NULL )
, m_samplePositionBeforeSubmit( _samplePositionBeforeSubmit )
{
RAKI_ASSERT( m_asyncReadStreamer );
RAKI_ASSERT( m_xma2Format );
RAKI_ASSERT( m_seekTable );
RAKI_ASSERT( _seekTableSize );
// // checking that compression has used the /LoopWholeFile flag in xma2encode
// RAKI_ASSERT( m_xma2Format->LoopBegin );
// RAKI_ASSERT( m_xma2Format->LoopLength );
RAKI_OUTPUT("m_xma2Format: LoopBegin %d LoopLength %d PlayBegin %d PlayLength %d SamplesEncoded %d", m_xma2Format->LoopBegin, m_xma2Format->LoopLength, m_xma2Format->PlayBegin, m_xma2Format->PlayLength, m_xma2Format->SamplesEncoded);
RAKI_ASSERT( m_xma2Format->BlockCount == m_nbBlocks );
// XAUDIO2_VOICE_STATE state = { 0 };
RAKI_OUTPUT( "XMA2DataProvider on 0x%x: m_sampleSize %d - %d blocks", this, m_sampleSize, m_nbBlocks );
for ( u32 block = 0 ; block < m_nbBlocks ; ++block )
{
RAKI_OUTPUT("seek %d: %d", block, m_seekTable[block] );
}
m_sampleSize = m_xma2Format->SamplesEncoded;
}
u64 XMA2DataProvider::pullData( void * _buffer, const u64 _sizeToRead )
{
RAKI_ASSERT( m_asyncReadStreamer );
return m_asyncReadStreamer->stream( _buffer, _sizeToRead );
}
u64 XMA2DataProvider::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 * XMA2DataProvider::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 XMA2DataProvider::prefetchNextStream()
{
if ( m_asyncReadStreamer && m_nextStream )
{
if ( m_nextStream )
m_nextStream->seek( 0, SeekableStream::fromBeginning );
}
}
void XMA2DataProvider::setNextStreamNow()
{
if ( m_nextStream )
{
m_asyncReadStreamer->setStreamData( NULL, 0, m_nextStream, m_nextClientData );
m_asyncReadStreamer->seekBeginning();
m_nextStream = NULL;
m_nextClientData = NULL;
}
/*
m_asyncReadStreamer->setStreamData( NULL, 0, m_nextStream, m_nextClientData );
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;
}*/
}
const void * XMA2DataProvider::getClientData() const
{
return m_clientData;
}
u64 XMA2DataProvider::getEntireSampleSize() const
{
return m_sampleSize;
}
u64 XMA2DataProvider::getEntireByteSize() const
{
return m_asyncReadStreamer ? m_asyncReadStreamer->getSize() : 0;
}
u64 XMA2DataProvider::getCurrentSamplePosition() const
{
const u64 bytesAlreadySubmitted = getEntireByteSize() - getRemainingByteSize();
RAKI_ASSERT( bytesAlreadySubmitted <= getEntireByteSize() );
if ( !bytesAlreadySubmitted )
return 0;
if ( bytesAlreadySubmitted == getEntireByteSize() )
return getEntireSampleSize();
RAKI_ASSERT( ( bytesAlreadySubmitted % m_xma2Format->BytesPerBlock ) == 0 );
u64 nbBlocksSubmitted = bytesAlreadySubmitted / m_xma2Format->BytesPerBlock;
RAKI_ASSERT( nbBlocksSubmitted );
RAKI_ASSERT( nbBlocksSubmitted < m_nbBlocks );
return m_seekTable[ nbBlocksSubmitted - 1 ];
}
void XMA2DataProvider::setNextStream( SeekableStream * _nextStream, const void * _nextClientData )
{
m_nextStream = _nextStream;
m_nextClientData = _nextClientData;
}
void XMA2DataProvider::update( bool /*_launchNewReadRequests*/ )
{
}
bool XMA2DataProvider::isFirstBuffer( const u64 _samplePositionBeforeSubmit ) const
{
return m_samplePositionBeforeSubmit == _samplePositionBeforeSubmit;
}
u64 XMA2DataProvider::getByteBlockPosition( const u64 _samplePosition ) const
{
RAKI_ASSERT( m_xma2Format );
RAKI_ASSERT( m_nbBlocks );
RAKI_ASSERT( m_xma2Format->SamplesEncoded > 768 ); // 2 empty 384 blocks for mp3
RAKI_ASSERT( _samplePosition < ( m_xma2Format->SamplesEncoded - 768 ) );
for ( u32 block = 0 ; block < ( m_nbBlocks - 1 ) ; ++block )
{
if ( _samplePosition < m_seekTable[block] )
return block * m_xma2Format->BytesPerBlock;
}
RAKI_ASSERT_FALSE;
return 0;
}
u64 XMA2DataProvider::getSampleOffsetInBuffer( const u64 _byteBlockPosition, const u64 _samplePosition ) const
{
RAKI_ASSERT( m_xma2Format );
RAKI_ASSERT( !(_byteBlockPosition % m_xma2Format->BytesPerBlock) );
if ( !_byteBlockPosition )
return _samplePosition;
const u32 block = _byteBlockPosition / m_xma2Format->BytesPerBlock;
RAKI_ASSERT( block );
RAKI_ASSERT( _samplePosition >= m_seekTable[block - 1] );
u64 position = _samplePosition - m_seekTable[block - 1];
// align to closest
if ( ( position % 128 ) < 64 )
return position - position % 128;
return position + 128 - position % 128;
}
} // namespace raki