#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 #include #include "RakiEngine/Sounds/_PS3/MP3StreamSoundNative_PS3.h" #include "RakiTests/Sounds/MP3DataProvider.h" #include "RakiTests/Sounds/MP3DeinterleaveDataProvider.h" #elif defined ( RAKI_PLATFORM_WII ) #include #include #include "RakiEngine/Sounds/_Wii/BufferSoundNative_Wii.h" #include #include #include #include #include #include #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