995 lines
No EOL
32 KiB
C++
995 lines
No EOL
32 KiB
C++
#include "Precompiled.h"
|
|
|
|
|
|
|
|
|
|
#include "RakiEngine/Data/MemoryBlock/MemoryBlock.h"
|
|
#include "RakiEngine/Data/Serialization/Serializer.h"
|
|
#include "RakiEngine/Data/Serialization/SerializedObject.h"
|
|
#include "RakiEngine/Data/Stream/AsyncReadStreamer.h"
|
|
#include "RakiEngine/Data/Stream/MemoryStream/MemoryStream.h"
|
|
#include "RakiEngine/Data/Stream/SeekableStreamPart.h"
|
|
#include "RakiEngine/Data/Stream/Interleave/DeinterleaveStream.h"
|
|
#include "RakiEngine/Data/Stream/Interleave/Deinterleaver.h"
|
|
#include "RakiEngine/Data/Stream/Interleave/RegularTrackDeinterleaveStream.h"
|
|
#include "RakiEngine/Data/Stream/Interleave/RegularTrackDeinterleaver.h"
|
|
#include "RakiEngine/Data/Serialization/Serializer.h"
|
|
#include "RakiEngine/Data/WaveFile/DeinterleaveWaveData.h"
|
|
#include "RakiEngine/Data/WaveFile/RiffChunkManager.h"
|
|
#include "RakiEngine/Data/WaveFile/BinWaveData/BinWaveData.h"
|
|
#include "RakiEngine/Data/WaveFile/MTTConfigChunk.h"
|
|
#include "RakiEngine/Sounds/MTTSound.h"
|
|
#include "RakiEngine/Sounds/Sequencer/Sequencer.h"
|
|
#include "RakiEngine/Sounds/Sequencer/SineNoteMemBlock.h"
|
|
#include "RakiEngine/Sounds/StreamBufferInfo.h"
|
|
#include "RakiEngine/Sounds/SimpleStream/SimpleStreamSound.h"
|
|
#include "RakiEngine/System/Streaming/StreamingThread.h"
|
|
#include "RakiEngine/Utils/Calcs.h"
|
|
#include "RakiTests/Stream/ReadFileStream.h"
|
|
|
|
#include "RakiEngine/Utils/Calcs.h"
|
|
|
|
#include "RakiTests/Initializer/TestInitializer.h"
|
|
#include "RakiTests/Sounds/PCMDeinterleaveDataProvider.h"
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
#include "RakiTests/_Win32/CoInitializeInitObject.h"
|
|
|
|
#endif // ( RAKI_PLATFORM_WIN32 )
|
|
|
|
|
|
#if defined ( RAKI_USING_XAUDIO2 )
|
|
|
|
#include "RakiEngine/Sounds/_XAudio2/BufferSoundNative.h"
|
|
#include "RakiEngine/Sounds/_XAudio2/PCMStreamSoundNative.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
#include <cell/mstream.h>
|
|
#include <sysutil/sysutil_common.h>
|
|
#include "RakiEngine/Sounds/_PS3/MP3StreamSoundNative_PS3.h"
|
|
#include "RakiTests/Sounds/MP3DataProvider.h"
|
|
#include "RakiTests/Sounds/MP3DeinterleaveDataProvider.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
|
|
#include <revolution/vi.h>
|
|
#include <revolution/pad.h>
|
|
|
|
#include "RakiEngine/Sounds/_Wii/BufferSoundNative_Wii.h"
|
|
|
|
#include <revolution/os.h>
|
|
#include <revolution/ax.h>
|
|
#include <revolution/mem.h>
|
|
#include <revolution/ai.h>
|
|
#include <revolution/dvd.h>
|
|
#include <revolution/vi.h>
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
#include "RakiEngine/Sounds/_Cafe/ADPCMStreamSoundNative_Cafe.h"
|
|
#include "RakiTests/_Cafe/Memory/SimpleHeap_Cafe.h"
|
|
#include "RakiTests/Sounds/ADPCMDataProvider_Cafe.h"
|
|
#include "RakiTests/Sounds/ADPCMDeinterleaveDataProvider_Cafe.h"
|
|
|
|
#endif
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
#include "RakiEngine/Sounds/_XAudio2/XMA2StreamSoundNative_X360.h"
|
|
|
|
#include "RakiTests/Sounds/XMA2DataProvider.h"
|
|
|
|
#endif // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
|
|
|
|
|
|
#define TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
#define BUFFER_PREFETCH_SIZE 0x10000
|
|
|
|
#elif defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
#define BUFFER_PREFETCH_SIZE ( 0x30000 )
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
#define BUFFER_PREFETCH_SIZE ( 0x10000 )
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
#define BUFFER_PREFETCH_SIZE ( 0x12000 )
|
|
|
|
#else // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
#define BUFFER_PREFETCH_SIZE 0x11800 // (0x8c) 140 and 128 aligned for ADPCM on Win32...
|
|
|
|
#endif // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
|
|
|
|
|
|
|
|
namespace raki
|
|
{
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
|
|
class ClientDeinterleaver : public RegularTrackDeinterleaver
|
|
{
|
|
public:
|
|
|
|
ClientDeinterleaver( SeekableStream * _seekabableStream, AsyncReadStreamer * _asyncReadStreamer, const u64 _interleaveBlockSize,
|
|
const u32 _nbChannels, const u32 _channelUsageFlags = 0xff )
|
|
: RegularTrackDeinterleaver( _asyncReadStreamer, _interleaveBlockSize, _nbChannels, _channelUsageFlags )
|
|
, m_seekabableStream( _seekabableStream )
|
|
, m_asyncReadStreamer( _asyncReadStreamer )
|
|
{
|
|
}
|
|
|
|
private:
|
|
|
|
virtual void clientPrefetchNextStream()
|
|
{
|
|
// looping test
|
|
m_seekabableStream->seekBeginning();
|
|
m_asyncReadStreamer->setStreamData( NULL, 0, m_seekabableStream, NULL );
|
|
}
|
|
|
|
virtual void clientSetNextStreamNow()
|
|
{
|
|
|
|
}
|
|
|
|
SeekableStream * m_seekabableStream;
|
|
AsyncReadStreamer * m_asyncReadStreamer;
|
|
|
|
};
|
|
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
|
|
class ClientDeinterleaver : public RegularTrackDeinterleaver
|
|
{
|
|
public:
|
|
|
|
ClientDeinterleaver( SeekableStream * _seekabableStream, AsyncReadStreamer * _asyncReadStreamer, const u64 _interleaveBlockSize,
|
|
const u32 _nbTracks, const u32 _trackUsageFlags = 0xff )
|
|
: RegularTrackDeinterleaver( _asyncReadStreamer, _interleaveBlockSize, _nbTracks, _trackUsageFlags )
|
|
, m_seekabableStream( _seekabableStream )
|
|
, m_asyncReadStreamer( _asyncReadStreamer )
|
|
{
|
|
}
|
|
|
|
private:
|
|
|
|
virtual void clientPrefetchNextStream()
|
|
{
|
|
// looping test
|
|
m_seekabableStream->seekBeginning();
|
|
m_asyncReadStreamer->setStreamData( NULL, 0, m_seekabableStream, NULL );
|
|
}
|
|
|
|
virtual void clientSetNextStreamNow()
|
|
{
|
|
|
|
}
|
|
|
|
SeekableStream * m_seekabableStream;
|
|
AsyncReadStreamer * m_asyncReadStreamer;
|
|
|
|
};
|
|
|
|
#else // defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
class ClientDeinterleaver : public Deinterleaver
|
|
{
|
|
public:
|
|
|
|
ClientDeinterleaver( SeekableStream * _seekabableStream, AsyncReadStreamer * _asyncReadStreamer, const u64 _interleaveBlockSize,
|
|
const char * _trackConfiguration, const u32 _trackUsageFlags = 0xff )
|
|
: Deinterleaver( _asyncReadStreamer, _interleaveBlockSize, _trackConfiguration, _trackUsageFlags )
|
|
, m_seekabableStream( _seekabableStream )
|
|
, m_asyncReadStreamer( _asyncReadStreamer )
|
|
{
|
|
}
|
|
|
|
private:
|
|
|
|
virtual void clientPrefetchNextStream()
|
|
{
|
|
// looping test
|
|
m_seekabableStream->seekBeginning();
|
|
m_asyncReadStreamer->setStreamData( NULL, 0, m_seekabableStream, NULL );
|
|
}
|
|
|
|
virtual void clientSetNextStreamNow()
|
|
{
|
|
|
|
}
|
|
|
|
SeekableStream * m_seekabableStream;
|
|
AsyncReadStreamer * m_asyncReadStreamer;
|
|
|
|
};
|
|
|
|
#endif // defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
|
|
|
|
|
|
|
|
static bool TestMTT( const char * _path )
|
|
{
|
|
|
|
StreamingThread streamingThread;
|
|
streamingThread.start();
|
|
|
|
ReadFileStream fileStream;
|
|
|
|
RiffChunkManager::singleton().setShouldReadDataBlockForWaveData( false );
|
|
|
|
bool opened = fileStream.open( _path );
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
#endif
|
|
|
|
RAKI_ASSERT( opened );
|
|
|
|
BinWaveData binWaveData( MemoryBlock::ms_nativeMemoryType );
|
|
|
|
bool readOK = binWaveData.readOnlyHeader( &fileStream );
|
|
if ( !readOK )
|
|
return false;
|
|
|
|
AsyncReadStreamer asyncReadStreamer;
|
|
|
|
MTTSound * mttSound = NULL;
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
SeekableStreamPart * seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, binWaveData.getDataOffset(), binWaveData.getDataSize() );
|
|
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
SeekableStreamPart * seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, binWaveData.getDataOffset(), binWaveData.getDataSize() );
|
|
XMA2DataProvider * dataProvider = NULL;
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
|
|
WiiAdpcmSoundStreamDataProvider * adpcmDataProvider = NULL;
|
|
ADPCMStreamSoundNative adpcmStreamSound( 2 );
|
|
adpcmStreamSound.getStreamBufferInfo()->setStreamUpdateClient( &testUpdateClient );
|
|
buffersAllocated = adpcmStreamSound.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
SeekableStreamPart * seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, binWaveData.getDataOffset(), binWaveData.getDataSize() );
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
SeekableStreamPart * seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, binWaveData.getDataOffset(), binWaveData.getDataSize() );
|
|
|
|
#endif
|
|
|
|
const bool isMusic = false;
|
|
const bool isLooping = true;
|
|
SoundParams soundParams( isMusic, isLooping );
|
|
|
|
WAVEFORMATEX * waveFormat = (WAVEFORMATEX*) binWaveData.getChunkData( RiffChunkManager::ms_riffTagFmt );
|
|
u32 waveFormatSize = binWaveData.getChunkSize( RiffChunkManager::ms_riffTagFmt );
|
|
|
|
RAKI_ASSERT( binWaveData.getChunkData( RiffChunkManager::ms_riffTagMTT ) );
|
|
|
|
MTTConfigChunk mttConfigChunk( binWaveData.getChunkData( RiffChunkManager::ms_riffTagMTT ), binWaveData.getChunkSize( RiffChunkManager::ms_riffTagMTT ) );
|
|
const u32 totalNbChannels = mttConfigChunk.getTotalNbChannels();
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
const u32 channelUsageFlags = 0xff;
|
|
#else
|
|
const u32 trackUsageFlags = 2;
|
|
const u32 totalNbTracks = mttConfigChunk.getNbTracks();
|
|
#endif // defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
u16 formatTag = waveFormat->wFormatTag;
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
XMA2StreamSoundNative * xma2StreamSound = NULL;
|
|
|
|
#else
|
|
|
|
ClientDeinterleaver * deinterleaver = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
switch ( formatTag )
|
|
{
|
|
#if defined ( RAKI_PLATFORM_WII )
|
|
|
|
case WAVE_FORMAT_ADPCM:
|
|
{
|
|
RAKI_ASSERT( waveFormat->nChannels <= 2 );
|
|
RAKI_ASSERT( waveFormat->wBitsPerSample <= 16 );
|
|
RAKI_ASSERT( waveFormat->nSamplesPerSec <= 50000 );
|
|
|
|
Format format( false );
|
|
|
|
#ifdef RAKI_PLATFORM_WII
|
|
format.setFormat( waveFormat );
|
|
#else // RAKI_PLATFORM_WII
|
|
format.setData( waveFormat, sizeof( WAVEFORMATEX ) );
|
|
#endif // RAKI_PLATFORM_WII
|
|
|
|
bool create = adpcmStreamSound.createVoice( &format );
|
|
RAKI_ASSERT( create );
|
|
|
|
seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, waveFile.getChunkOffsetInStream( dataChunck ),
|
|
waveFile.getChunkSize( dataChunck ) );
|
|
asyncReadStreamer->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
u64 prefetchSize = dataBlock.getSize() > BUFFER_PREFETCH_SIZE ? BUFFER_PREFETCH_SIZE : dataBlock.getSize();
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer->setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer->setStreamData( dataBlock.getBuffer(), prefetchSize, seekableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer->setStreamingThread( &streamingThread );
|
|
|
|
const u32 nbChannels = waveFile.getChunkData( "dspR" ) ? 2 : 1;
|
|
|
|
adpcmDataProvider = RAKI_NEW( ADPCMDataProvider )( asyncReadStreamer, &clientData, nbChannels, waveFile.getChunkData( "dspL" ), waveFile.getChunkData( "dspR" ) );
|
|
|
|
// add second source
|
|
|
|
// dataProvider2 = RAKI_NEW( PCMDataProvider )( &dataStream2, &clientData2, (u64) pcmFormat.nBlockAlign );
|
|
|
|
// ( (PCMDataProvider*) dataProvider )->setNextStream( asyncReadStreamer, &clientData );
|
|
// ( (PCMDataProvider*) dataProvider2)->setNextStream( &dataStream2, &clientData2 );
|
|
|
|
|
|
adpcmStreamSound.prepare( adpcmDataProvider );
|
|
adpcmStreamSound.updateVolume( true );
|
|
adpcmStreamSound.start();
|
|
|
|
bool isPlaying = adpcmStreamSound.isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
|
|
}
|
|
break;
|
|
|
|
#endif // RAKI_PLATFORM_WII
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
case WAVE_FORMAT_PCM:
|
|
{
|
|
// hello bill...
|
|
WAVEFORMATEX pcmFormat = { 0 };
|
|
RAKI_ASSERT( waveFormatSize <= sizeof( WAVEFORMATEX ) );
|
|
memcpy( &pcmFormat, waveFormat, waveFormatSize );
|
|
pcmFormat.cbSize = 0;
|
|
|
|
RAKI_ASSERT( !( pcmFormat.nChannels % 2 ) );
|
|
RAKI_ASSERT( pcmFormat.wBitsPerSample <= 16 );
|
|
RAKI_ASSERT( pcmFormat.nSamplesPerSec <= 50000 );
|
|
RAKI_ASSERT( mttConfigChunk.getInterleaveBlockSize() );
|
|
RAKI_ASSERT( !( BUFFER_PREFETCH_SIZE % mttConfigChunk.getInterleaveBlockSize() ) );
|
|
|
|
RAKI_ASSERT( totalNbTracks > 1 );
|
|
|
|
deinterleaver = RAKI_NEW( ClientDeinterleaver )( seekableStreamPart, &asyncReadStreamer, mttConfigChunk.getInterleaveBlockSize(), mttConfigChunk.getMTTConfig(), trackUsageFlags );
|
|
|
|
mttSound = RAKI_NEW( MTTSound )( totalNbTracks );
|
|
|
|
for ( u32 track = 0 ; track < totalNbTracks ; ++track )
|
|
{
|
|
if ( ( 1 << track ) & trackUsageFlags )
|
|
{
|
|
DeinterleaveStream * deinterleaveStream = deinterleaver->getDeinterleaveStream( track );
|
|
|
|
const u32 nbChannelsForTrack = mttConfigChunk.getNbChannelsForTrack( track );
|
|
|
|
PCMStreamSoundNative * pcmStreamSound = RAKI_NEW( PCMStreamSoundNative );
|
|
pcmStreamSound->allocateBuffers( BUFFER_PREFETCH_SIZE * nbChannelsForTrack );
|
|
|
|
PCMDeinterleaveDataProvider * dataProvider = RAKI_NEW( PCMDeinterleaveDataProvider )( deinterleaver, deinterleaveStream, NULL, 2 * nbChannelsForTrack, nbChannelsForTrack, isLooping );
|
|
|
|
DeinterleaveWaveData * deinterleaveWaveData = RAKI_NEW( DeinterleaveWaveData )( &binWaveData, totalNbChannels, mttConfigChunk.getNbChannelsForTrack( track ) );
|
|
|
|
bool create = pcmStreamSound->createVoice( deinterleaveWaveData, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
pcmStreamSound->prepare( dataProvider );
|
|
|
|
mttSound->addTrack( pcmStreamSound, dataProvider );
|
|
}
|
|
}
|
|
|
|
RAKI_ASSERT( mttSound->getNbTracks() );
|
|
|
|
asyncReadStreamer.allocateBuffers( 2 * totalNbChannels * BUFFER_PREFETCH_SIZE ); // async read streamer buffers need to be able to read 2 times low level buffer sizes
|
|
// u64 prefetchSize = dataBlock.getSize() > BUFFER_PREFETCH_SIZE ? BUFFER_PREFETCH_SIZE : dataBlock.getSize();
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( dataBlock.getBuffer(), BUFFER_PREFETCH_SIZE, seekabableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer.setStreamingThread( &streamingThread );
|
|
|
|
mttSound->updateVolume( true );
|
|
mttSound->start();
|
|
|
|
bool isPlaying = mttSound->isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
/*
|
|
|
|
case WAVE_FORMAT_ADPCM:
|
|
{
|
|
RAKI_ASSERT( sizeof( ADPCMWAVEFORMAT ) <= binWaveData.getChunkSize( "fmt " ) );
|
|
ADPCMWAVEFORMAT * adpcmWaveFormat = (ADPCMWAVEFORMAT*)waveFormat;
|
|
|
|
RAKI_ASSERT( !( adpcmWaveFormat->wfx.nChannels % 2 ) );
|
|
RAKI_ASSERT( adpcmWaveFormat->wfx.wBitsPerSample <= 16 );
|
|
RAKI_ASSERT( adpcmWaveFormat->wfx.nSamplesPerSec <= 50000 );
|
|
RAKI_ASSERT( adpcmWaveFormat->wSamplesPerBlock );
|
|
RAKI_ASSERT( !( BUFFER_PREFETCH_SIZE % adpcmWaveFormat->wSamplesPerBlock ) );
|
|
|
|
const u32 nbTracks = waveFormat->nChannels / 2;
|
|
RAKI_ASSERT( nbTracks > 1 );
|
|
|
|
mttSound = RAKI_NEW( MTTSound )( nbTracks );
|
|
|
|
deinterleaver = RAKI_NEW( Deinterleaver )( &asyncReadStreamer, adpcmWaveFormat->wSamplesPerBlock, "22" );
|
|
|
|
for ( u32 track = 0 ; track < nbTracks ; ++track )
|
|
{
|
|
DeinterleaveStream * deinterleaveStream = deinterleaver->getDeinterleaveStream( track );
|
|
|
|
PCMStreamSoundNative * pcmStreamSound = RAKI_NEW( PCMStreamSoundNative );
|
|
pcmStreamSound->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
|
|
PCMDeinterleaveDataProvider * dataProvider = RAKI_NEW( PCMDeinterleaveDataProvider )( deinterleaver, deinterleaveStream, NULL, 2, 2, isLooping );
|
|
|
|
DeinterleaveWaveData * deinterleaveWaveData = RAKI_NEW( DeinterleaveWaveData )( &binWaveData, totalNbChannels, mttConfigChunk.getNbChannelsForTrack( track ) );
|
|
|
|
bool create = pcmStreamSound->createVoice( deinterleaveWaveData, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
pcmStreamSound->prepare( dataProvider );
|
|
|
|
mttSound->addTrack( pcmStreamSound, dataProvider );
|
|
}
|
|
|
|
|
|
asyncReadStreamer.allocateBuffers( nbTracks * 2 * BUFFER_PREFETCH_SIZE );
|
|
// u64 prefetchSize = dataBlock.getSize() > BUFFER_PREFETCH_SIZE ? BUFFER_PREFETCH_SIZE : dataBlock.getSize();
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( dataBlock.getBuffer(), BUFFER_PREFETCH_SIZE, seekabableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer.setStreamingThread( &streamingThread );
|
|
|
|
mttSound->updateVolume( true );
|
|
mttSound->start();
|
|
|
|
bool isPlaying = mttSound->isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
}
|
|
break;
|
|
*/
|
|
|
|
|
|
#endif // defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
case WAVE_FORMAT_XMA2:
|
|
{
|
|
RAKI_ASSERT( waveFormatSize >= sizeof( XMA2WAVEFORMATEX ) );
|
|
|
|
// MS HACK !!
|
|
XMA2WAVEFORMATEX * xma2waveFormat = (XMA2WAVEFORMATEX *)waveFormat;
|
|
xma2waveFormat->PlayBegin = xma2waveFormat->LoopBegin;
|
|
xma2waveFormat->PlayLength = xma2waveFormat->LoopLength;
|
|
|
|
xma2StreamSound = RAKI_NEW( XMA2StreamSoundNative );
|
|
|
|
xma2StreamSound->allocateBuffers( BUFFER_PREFETCH_SIZE - ( BUFFER_PREFETCH_SIZE % xma2waveFormat->BytesPerBlock ) );
|
|
|
|
bool create = xma2StreamSound->createVoice( &binWaveData, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, binWaveData.getDataOffset(), binWaveData.getChunkSize( RiffChunkManager::ms_riffTagData ) );
|
|
asyncReadStreamer.allocateBuffers( 4 * 2 * BUFFER_PREFETCH_SIZE );
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
u64 prefetchSize = dataBlock.getSize() > BUFFER_PREFETCH_SIZE ? BUFFER_PREFETCH_SIZE : dataBlock.getSize();
|
|
asyncReadStreamer->setStreamData( dataBlock.getBuffer(), BUFFER_PREFETCH_SIZE, seekableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer.setStreamingThread( &streamingThread );
|
|
|
|
u32 * seekTable = (u32*)binWaveData.getChunkData( RiffChunkManager::ms_riffTagSeek );
|
|
u32 seekTableSize = binWaveData.getChunkSize( RiffChunkManager::ms_riffTagSeek );
|
|
dataProvider = RAKI_NEW( XMA2DataProvider )( &asyncReadStreamer, xma2waveFormat, seekTable, seekTableSize, 0, 0, 0, xma2waveFormat->wfx.nChannels );
|
|
|
|
|
|
xma2StreamSound->prepare( dataProvider );
|
|
xma2StreamSound->updateVolume( true );
|
|
xma2StreamSound->start();
|
|
}
|
|
break;
|
|
#endif // ( RAKI_PLATFORM_XB360 )
|
|
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
case WAVE_FORMAT_MPEGLAYER3:
|
|
{
|
|
|
|
RAKI_ASSERT( !( BUFFER_PREFETCH_SIZE % mttConfigChunk.getInterleaveBlockSize() ) );
|
|
|
|
RAKI_ASSERT( totalNbTracks > 1 );
|
|
|
|
deinterleaver = RAKI_NEW( ClientDeinterleaver )( seekableStreamPart, &asyncReadStreamer, mttConfigChunk.getInterleaveBlockSize(), mttConfigChunk.getNbTracks(), trackUsageFlags );
|
|
|
|
mttSound = RAKI_NEW( MTTSound )( totalNbTracks );
|
|
|
|
for ( u32 track = 0 ; track < totalNbTracks ; ++track )
|
|
{
|
|
if ( ( 1 << track ) & trackUsageFlags )
|
|
{
|
|
RegularTrackDeinterleaveStream * deinterleaveStream = deinterleaver->getDeinterleaveStream( track );
|
|
|
|
const u32 nbChannelsForTrack = mttConfigChunk.getNbChannelsForTrack( track );
|
|
|
|
MP3StreamSoundNative * mp3StreamSound = RAKI_NEW( MP3StreamSoundNative );
|
|
mp3StreamSound->allocateBuffers( BUFFER_PREFETCH_SIZE ); // SAME BUFFER SIZE FOR MONO AND STEREO ON PS3/MP3 !!! * nbChannelsForTrack );
|
|
|
|
MP3DeinterleaveDataProvider * dataProvider = RAKI_NEW( MP3DeinterleaveDataProvider )( deinterleaver, deinterleaveStream, NULL, nbChannelsForTrack, isLooping );
|
|
|
|
DeinterleaveWaveData * deinterleaveWaveData = RAKI_NEW( DeinterleaveWaveData )( &binWaveData, totalNbChannels, mttConfigChunk.getNbChannelsForTrack( track ) );
|
|
|
|
bool create = mp3StreamSound->createVoice( deinterleaveWaveData, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
mp3StreamSound->prepare( dataProvider );
|
|
|
|
mttSound->addTrack( mp3StreamSound, dataProvider );
|
|
}
|
|
}
|
|
|
|
RAKI_ASSERT( mttSound->getNbTracks() );
|
|
|
|
asyncReadStreamer.allocateBuffers( 2 * totalNbTracks * BUFFER_PREFETCH_SIZE ); // async read streamer buffers need to be able to read 2 times low level buffer sizes
|
|
// u64 prefetchSize = dataBlock.getSize() > BUFFER_PREFETCH_SIZE ? BUFFER_PREFETCH_SIZE : dataBlock.getSize();
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( dataBlock.getBuffer(), BUFFER_PREFETCH_SIZE, seekabableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer.setStreamingThread( &streamingThread );
|
|
|
|
mttSound->updateVolume( true );
|
|
mttSound->start();
|
|
|
|
bool isPlaying = mttSound->isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
|
|
|
|
|
|
/*
|
|
RAKI_ASSERT( !( waveFormat->nChannels % 2 ) );
|
|
RAKI_ASSERT( waveFormat->wBitsPerSample <= 16 );
|
|
RAKI_ASSERT( waveFormat->nSamplesPerSec <= 50000 );
|
|
|
|
const u32 nbTracks = waveFormat->nChannels / 2;
|
|
RAKI_ASSERT( nbTracks > 1 );
|
|
|
|
mttSound = RAKI_NEW( MTTSound )( nbTracks );
|
|
|
|
u64 offset = 64 * nbTracks;
|
|
seekableStreamPart = RAKI_NEW( SeekableStreamPart )( &fileStream, offset + binWaveData.getDataOffset(), binWaveData.getDataSize() - offset );
|
|
|
|
deinterleaver = RAKI_NEW( ClientDeinterleaver )( 4 * BUFFER_PREFETCH_SIZE, 4, nbTracks, , &asyncReadStreamer, seekableStreamPart );
|
|
deinterleaver->setAsyncReadStreamer( &asyncReadStreamer );
|
|
|
|
for ( u32 track = 0 ; track < nbTracks ; ++track )
|
|
{
|
|
DeinterleaveStream * deinterleaveStream = deinterleaver->getDeinterleaveItem( track );
|
|
|
|
MP3StreamSoundNative * mp3StreamSound = RAKI_NEW( MP3StreamSoundNative );
|
|
mp3StreamSound->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
|
|
MP3DeinterleaveDataProvider * dataProvider = RAKI_NEW( MP3DeinterleaveDataProvider )( deinterleaver, deinterleaveStream, NULL, 2, isLooping );
|
|
|
|
DeinterleaveWaveData * deinterleaveWaveData = RAKI_NEW( DeinterleaveWaveData )( &binWaveData );
|
|
|
|
bool create = mp3StreamSound->createVoice( deinterleaveWaveData, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
mp3StreamSound->prepare( dataProvider );
|
|
|
|
mttSound->addTrack( mp3StreamSound, dataProvider );
|
|
}
|
|
|
|
asyncReadStreamer.allocateBuffers( nbTracks * 2 * BUFFER_PREFETCH_SIZE );
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( dataBlock.getBuffer(), BUFFER_PREFETCH_SIZE, seekabableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer.setStreamingThread( &streamingThread );
|
|
|
|
mttSound->updateVolume( true );
|
|
mttSound->start();
|
|
|
|
bool isPlaying = mttSound->isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
*/
|
|
}
|
|
break;
|
|
#endif // ( RAKI_PLATFORM_PS3 )
|
|
|
|
|
|
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
case WAVE_FORMAT_ADPCM:
|
|
{
|
|
RAKI_ASSERT( !( BUFFER_PREFETCH_SIZE % mttConfigChunk.getInterleaveBlockSize() ) );
|
|
|
|
RAKI_ASSERT( mttConfigChunk.getTotalNbChannels() > 1 );
|
|
|
|
deinterleaver = RAKI_NEW( ClientDeinterleaver )( seekableStreamPart, &asyncReadStreamer, mttConfigChunk.getInterleaveBlockSize(), mttConfigChunk.getTotalNbChannels(), channelUsageFlags );
|
|
|
|
mttSound = RAKI_NEW( MTTSound )( mttConfigChunk.getTotalNbChannels() );
|
|
|
|
for ( u32 channel = 0 ; channel < mttConfigChunk.getTotalNbChannels() ; ++channel )
|
|
{
|
|
if ( ( 1 << channel ) & channelUsageFlags )
|
|
{
|
|
RegularTrackDeinterleaveStream * deinterleaveStream = deinterleaver->getDeinterleaveStream( channel );
|
|
|
|
ADPCMStreamSoundNative * streamSound = RAKI_NEW( ADPCMStreamSoundNative )( 1 );
|
|
streamSound->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
|
|
AdpcmDeinterleaveDataProvider * dataProvider = RAKI_NEW( AdpcmDeinterleaveDataProvider )( deinterleaver, deinterleaveStream, NULL, 1, channel, isLooping,
|
|
(DSPADPCM*)binWaveData.getChunkData( RiffChunkManager::ms_riffTagDspM ) );
|
|
|
|
DeinterleaveWaveData * deinterleaveWaveData = RAKI_NEW( DeinterleaveWaveData )( &binWaveData, totalNbChannels, 1 );
|
|
|
|
bool create = streamSound->createVoice( deinterleaveWaveData, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
streamSound->prepare( dataProvider );
|
|
|
|
mttSound->addTrack( streamSound, dataProvider );
|
|
}
|
|
}
|
|
|
|
RAKI_ASSERT( mttSound->getNbTracks() );
|
|
|
|
asyncReadStreamer.allocateBuffers( 2 * totalNbChannels * BUFFER_PREFETCH_SIZE ); // async read streamer buffers need to be able to read 2 times low level buffer sizes
|
|
// u64 prefetchSize = dataBlock.getSize() > BUFFER_PREFETCH_SIZE ? BUFFER_PREFETCH_SIZE : dataBlock.getSize();
|
|
|
|
#ifdef TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( NULL, 0, seekableStreamPart, NULL );
|
|
#else // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
asyncReadStreamer.setStreamData( dataBlock.getBuffer(), BUFFER_PREFETCH_SIZE, seekabableStreamPart, NULL );
|
|
#endif // TESTMTT_WITHOUT_PREFETCHBUFFER
|
|
|
|
asyncReadStreamer.setStreamingThread( &streamingThread );
|
|
|
|
mttSound->updateVolume( true );
|
|
mttSound->start();
|
|
|
|
bool isPlaying = mttSound->isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
}
|
|
break;
|
|
#endif // ( RAKI_PLATFORM_CAFE )
|
|
|
|
|
|
default:
|
|
RAKI_ASSERT_FALSE;
|
|
}
|
|
|
|
#define COUNT_LOOP 50
|
|
#define COUNT_STOP 20
|
|
#define COUNT_START 34
|
|
|
|
int count = 0;
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
//xma2StreamSound->setDecibelVolume( 0, -15.f );
|
|
xma2StreamSound->updateVolume();
|
|
|
|
#else // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
// guitar 0
|
|
// percussions 1
|
|
// violins 2
|
|
|
|
//mttSound->setDecibelVolume( 1, -15.f );
|
|
//mttSound->setDecibelVolume( 2, -15.f );
|
|
|
|
mttSound->updateVolume();
|
|
|
|
#endif // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
|
|
for ( ;; )
|
|
{
|
|
bool isPlaying = false;
|
|
|
|
#ifdef RAKI_PLATFORM_WII
|
|
VIWaitForRetrace();
|
|
#else // RAKI_PLATFORM_WII
|
|
Thread::sleep( 25 );
|
|
#endif // RAKI_PLATFORM_WII
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
xma2StreamSound->update();
|
|
dataProvider->update( true );
|
|
isPlaying |= xma2StreamSound->isPlaying();
|
|
|
|
#else // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
mttSound->update();
|
|
//deinterleaver->update();
|
|
isPlaying |= mttSound->isPlaying();
|
|
|
|
#endif // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
asyncReadStreamer.update( true );
|
|
|
|
++count;
|
|
|
|
if ( !isPlaying )
|
|
break;
|
|
}
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
xma2StreamSound->stop();
|
|
|
|
// XAudio2 doc: Stop is always asynchronous, even if called within a callback
|
|
Thread::sleep( 500 );
|
|
|
|
xma2StreamSound->destroyVoice();
|
|
|
|
Thread::sleep( 500 );
|
|
|
|
RAKI_DELETE( xma2StreamSound );
|
|
RAKI_DELETE( dataProvider );
|
|
|
|
#else // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
mttSound->stop();
|
|
|
|
Thread::sleep( 500 );
|
|
|
|
mttSound->destroyVoice();
|
|
|
|
Thread::sleep( 500 );
|
|
|
|
RAKI_DELETE( deinterleaver );
|
|
RAKI_DELETE( mttSound );
|
|
|
|
#endif // defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace raki
|
|
|
|
int rakimain()
|
|
{
|
|
|
|
#if defined ( RAKI_PLATFORM_WII )
|
|
DVDInit();
|
|
VIInit();
|
|
|
|
raki::SystemAllocator_Initialize();
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
raki::SimpleHeap_Cafe::init();
|
|
|
|
#elif defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
raki::CoInitializeInitObject coInitializeInitObject;
|
|
|
|
#endif
|
|
|
|
|
|
raki::TestInitializer initializer;
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
const char path[] = "../../../../TestData/MTTSineTest.wav.w32pcm";
|
|
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
const char path[] = "game:\\MTT_6_short.wav.x360";
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
const char path[] = "/app_home/E:/ITF/RO2/extern/Raki/TestData/MTTSineTest.wav.ps3";
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
|
|
const char path_mono[] = "Sfx_ChangeCostume_01.wav.wii";
|
|
const char path_surroundTestL[] = "surroundTestL.wav.wii";
|
|
const char path_surroundTestR[] = "surroundTestR.wav.wii";
|
|
const char path_surroundTestBR[] = "surroundTestBR.wav.wii";
|
|
const char path_surroundTestBL[] = "surroundTestBL.wav.wii";
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
//const char path[] = "MTTSineTest.wav.cafe";
|
|
const char path[] = "MTT_6.wav.cafe";
|
|
|
|
#endif
|
|
|
|
bool playedOK = raki::TestMTT( path );
|
|
|
|
if ( !playedOK )
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
int run_demo (int /*intArg*/, void */*ptrArg*/)
|
|
{
|
|
return rakimain();
|
|
}
|
|
|
|
u32 running_core;
|
|
u32 main_core;
|
|
u32 first_subcore;
|
|
u32 second_subcore;
|
|
u32 wait_main_core;
|
|
u32 wait_first_subcore;
|
|
u32 wait_second_subcore;
|
|
OSRendezvous rendezvous;
|
|
|
|
void
|
|
SetupCoreIds(void)
|
|
{
|
|
running_core = OSGetCoreId();
|
|
main_core = OSGetMainCoreId();
|
|
|
|
first_subcore = 0;
|
|
second_subcore = 2;
|
|
wait_main_core = OS_WAIT_CORE_MAIN;
|
|
wait_first_subcore = OS_WAIT_CORE_SUB1;
|
|
wait_second_subcore = OS_WAIT_CORE_SUB2;
|
|
|
|
if (main_core == 0)
|
|
{
|
|
first_subcore = 1;
|
|
second_subcore = 2;
|
|
wait_main_core = OS_WAIT_CORE_SUB1;
|
|
wait_first_subcore = OS_WAIT_CORE_MAIN;
|
|
wait_second_subcore = OS_WAIT_CORE_SUB2;
|
|
}
|
|
else
|
|
if (main_core == 2)
|
|
{
|
|
first_subcore = 0;
|
|
second_subcore = 1;
|
|
wait_main_core = OS_WAIT_CORE_SUB2;
|
|
wait_first_subcore = OS_WAIT_CORE_SUB1;
|
|
wait_second_subcore = OS_WAIT_CORE_MAIN;
|
|
}
|
|
}
|
|
|
|
int main( int /*argc*/, char * /*argv[]*/ )
|
|
{
|
|
|
|
u32 gx2InitAttribs[] =
|
|
{
|
|
GX2_INIT_ATTRIB_NULL // terminates the list
|
|
};
|
|
GX2Init(gx2InitAttribs);
|
|
|
|
// launch test on Core 0 if present
|
|
if (OSGetCoreCount() == 3)
|
|
{
|
|
OSThread* defaultThread0;
|
|
|
|
SetupCoreIds();
|
|
|
|
OSReport("Running Core == %d\n", running_core);
|
|
OSReport("OS Main Core == %d\n\n", main_core);
|
|
|
|
OSInitRendezvous(&rendezvous);
|
|
|
|
//
|
|
// Restart default thread on 1st subcore, core0
|
|
//
|
|
|
|
defaultThread0 = OSGetDefaultThread(first_subcore);
|
|
OSRunThread(defaultThread0,
|
|
run_demo,
|
|
0,
|
|
(void*) 0x23232323);
|
|
|
|
OSWaitRendezvous(&rendezvous, wait_first_subcore);
|
|
}
|
|
else
|
|
{
|
|
run_demo(0, NULL);
|
|
}
|
|
|
|
GX2Shutdown();
|
|
|
|
return 0;
|
|
}
|
|
|
|
#elif defined ( RAKI_USING_XAUDIO2 )
|
|
int _tmain(int /*argc*/, _TCHAR* /*argv[]*/)
|
|
{
|
|
rakimain();
|
|
|
|
return 0;
|
|
}
|
|
#else // RAKI_USING_XAUDIO2
|
|
int main( int /*argc*/, char * /*argv[]*/
|
|
{
|
|
rakimain();
|
|
|
|
return 0;
|
|
}
|
|
#endif // RAKI_USING_XAUDIO2
|