247 lines
6.1 KiB
C++
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
|
|
|