832 lines
30 KiB
C++
832 lines
30 KiB
C++
#include "Precompiled.h"
|
|
|
|
|
|
#include "RakiEngine/Data/MemoryBlock/MemoryBlock.h"
|
|
#include "RakiEngine/Data/Stream/MemoryStream/MemoryStream.h"
|
|
#include "RakiEngine/Data/Stream/SeekableStreamPart.h"
|
|
#include "RakiEngine/Data/Stream/AsyncReadStreamer.h"
|
|
#include "RakiEngine/Data/WaveFile/BinWaveData/BinWaveData.h"
|
|
#include "RakiEngine/Data/WaveFile/RiffChunkManager.h"
|
|
#include "RakiEngine/Sounds/Sequencer/Sequencer.h"
|
|
#include "RakiEngine/Sounds/Sequencer/SineNoteMemBlock.h"
|
|
#include "RakiEngine/Sounds/StreamBufferInfo.h"
|
|
#include "RakiEngine/Sounds/SoftwareEngine/StreamSoftwareSound.h"
|
|
#include "RakiEngine/System/Streaming/StreamingThread.h"
|
|
#include "RakiEngine/Utils/Calcs.h"
|
|
#include "RakiTests/Sounds/PCMDataProvider.h"
|
|
#include "RakiTests/Stream/ReadFileStream.h"
|
|
|
|
#include "RakiEngine/Utils/Calcs.h"
|
|
|
|
#if defined ( RAKI_USING_XAUDIO2 )
|
|
|
|
#include "RakiEngine/Sounds/_XAudio2/BufferSoundNative.h"
|
|
#include "RakiEngine/Sounds/_XAudio2/PCMStreamSoundNative.h"
|
|
#include "RakiEngine/Sounds/_XAudio2/XMA2StreamSoundNative_X360.h"
|
|
#include "RakiEngine/Specific/_XB360/Specific_X360.h"
|
|
#include "RakiTests/Sounds/XMA2DataProvider.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
#include <cell/mstream.h>
|
|
#include "RakiEngine/Sounds/_PS3/BufferSoundNative_PS3.h"
|
|
#include "RakiEngine/Sounds/_PS3/MP3StreamSoundNative_PS3.h"
|
|
#include "RakiTests/Sounds/MP3DataProvider.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
|
|
#include <revolution/vi.h>
|
|
|
|
#include "RakiTests/Sounds/ADPCMDataProvider_Wii.h"
|
|
#include "RakiEngine/Sounds/_Wii/BufferSoundNative_Wii.h"
|
|
#include "RakiEngine/Sounds/_Wii/ADPCMStreamSoundNative_Wii.h"
|
|
#include "RakiEngine/Sounds/_Wii/PCMStreamSoundNative_Wii.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
#include "RakiTests/Sounds/ADPCMDataProvider_Cafe.h"
|
|
#include "RakiEngine/Sounds/_Cafe/ADPCMStreamSoundNative_Cafe.h"
|
|
|
|
#include "RakiTests/_Cafe/Memory/SimpleHeap_Cafe.h"
|
|
|
|
#endif
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
#include "RakiTests/_Win32/CoInitializeInitObject.h"
|
|
|
|
#endif // ( RAKI_PLATFORM_WIN32 )
|
|
|
|
|
|
|
|
#include "RakiTests/Initializer/TestInitializer.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace raki
|
|
{
|
|
|
|
extern void SystemAllocator_Initialize();
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE )
|
|
#define BUFFER_PREFETCH_SIZE 55040
|
|
#else
|
|
#define BUFFER_PREFETCH_SIZE ( 2 * 0x10000 )
|
|
//#define BUFFER_PREFETCH_SIZE ( 2 * 0x1000 )
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
class SynchroStarter : public StreamBufferInfo::AudioCallbackStreamUpdateClient
|
|
{
|
|
public:
|
|
|
|
SynchroStarter()
|
|
: m_soundToStart( NULL ), m_sampleToStart( 0 )
|
|
{
|
|
}
|
|
|
|
void setData( Sound * _soundToStart, u64 _sampleToStart )
|
|
{
|
|
m_soundToStart = _soundToStart;
|
|
m_sampleToStart = _sampleToStart;
|
|
}
|
|
|
|
virtual void audioCallbackUpdateStreamPosition( const void * /*_clientData*/, const u64 _samplePosition )
|
|
{
|
|
#if defined ( RAKI_USING_SOFTWARE_ENGINE )
|
|
if ( m_soundToStart && ( _samplePosition + 1024 ) >= m_sampleToStart )
|
|
#elif defined ( RAKI_USING_XAUDIO2 ) // hum hum order :)
|
|
if ( m_soundToStart && ( _samplePosition + 1024 ) >= m_sampleToStart )
|
|
#elif defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE )
|
|
if ( m_soundToStart && ( _samplePosition + 96 ) >= m_sampleToStart )
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
if ( m_soundToStart && ( _samplePosition + 512 ) >= m_sampleToStart )
|
|
#else
|
|
if ( m_soundToStart && _samplePosition >= m_sampleToStart )
|
|
#endif
|
|
{
|
|
RAKI_OUTPUT("audioCallbackUpdateStreamPosition calling m_soundToStart->startFromAudioCallback");
|
|
|
|
m_soundToStart->startFromAudioCallback();
|
|
|
|
m_soundToStart = NULL;
|
|
}
|
|
}
|
|
private:
|
|
|
|
Sound * m_soundToStart;
|
|
u64 m_sampleToStart;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TestSynchroStreams( const char * _path1, const char * _path2, const u64 _sampleOffset );
|
|
void TestSynchroStreams( const char * _path1, const char * _path2, const u64 _sampleOffset )
|
|
{
|
|
StreamingThread streamingThread;
|
|
streamingThread.start();
|
|
|
|
ReadFileStream fileStream1, fileStream2;
|
|
|
|
bool opened = fileStream1.open( _path1 );
|
|
RAKI_ASSERT_WITH_MESSAGE( opened, "Invalid path1" );
|
|
|
|
BinWaveData binWaveData1( MemoryBlock::ms_nativeMemoryType );
|
|
|
|
bool readOK = binWaveData1.readOnlyHeader( &fileStream1 );
|
|
RAKI_ASSERT( readOK );
|
|
|
|
opened = fileStream2.open( _path2 );
|
|
RAKI_ASSERT_WITH_MESSAGE( opened, "Invalid path2" );
|
|
|
|
BinWaveData binWaveData2( MemoryBlock::ms_nativeMemoryType );
|
|
|
|
readOK = binWaveData2.readOnlyHeader( &fileStream2 );
|
|
RAKI_ASSERT( readOK );
|
|
|
|
|
|
SoundStreamDataProvider * dataProvider1 = NULL;
|
|
SoundStreamDataProvider * dataProvider2 = NULL;
|
|
SeekableStreamPart * seekableStreamPart1 = NULL;
|
|
SeekableStreamPart * seekableStreamPart2 = NULL;
|
|
AsyncReadStreamer * asyncReader1 = RAKI_NEW( AsyncReadStreamer );
|
|
AsyncReadStreamer * asyncReader2 = RAKI_NEW( AsyncReadStreamer );
|
|
|
|
SynchroStarter synchroStarter;
|
|
|
|
bool buffersAllocated = false;
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
#if defined ( RAKI_USING_SOFTWARE_ENGINE )
|
|
StreamSoftwareSound pcmStreamSound1;
|
|
StreamSoftwareSound pcmStreamSound2;
|
|
#else
|
|
PCMStreamSoundNative pcmStreamSound1;
|
|
PCMStreamSoundNative pcmStreamSound2;
|
|
#endif
|
|
|
|
buffersAllocated = pcmStreamSound1.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
buffersAllocated = pcmStreamSound2.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
pcmStreamSound1.getStreamBufferInfo()->setAudioCallbackStreamUpdateClient( &synchroStarter );
|
|
synchroStarter.setData( &pcmStreamSound2, _sampleOffset );
|
|
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
XMA2StreamSoundNative xma2StreamSound1, xma2StreamSound2;
|
|
buffersAllocated = xma2StreamSound1.allocateBuffers( 0x20000 );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
buffersAllocated = xma2StreamSound2.allocateBuffers( 0x20000 );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
xma2StreamSound1.getStreamBufferInfo()->setAudioCallbackStreamUpdateClient( &synchroStarter );
|
|
synchroStarter.setData( &xma2StreamSound2, _sampleOffset );
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
ADPCMDataProvider * adpcmDataProvider1 = NULL;
|
|
ADPCMDataProvider * adpcmDataProvider2 = NULL;
|
|
ADPCMStreamSoundNative adpcmStreamSound1( 2 );
|
|
ADPCMStreamSoundNative adpcmStreamSound2( 2 );
|
|
buffersAllocated = adpcmStreamSound1.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
buffersAllocated = adpcmStreamSound2.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
adpcmStreamSound1.getStreamBufferInfo()->setAudioCallbackStreamUpdateClient( &synchroStarter );
|
|
synchroStarter.setData( &adpcmStreamSound2, _sampleOffset );
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
MP3StreamSoundNative mp3StreamSound1;
|
|
buffersAllocated = mp3StreamSound1.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
MP3StreamSoundNative mp3StreamSound2;
|
|
buffersAllocated = mp3StreamSound2.allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
mp3StreamSound1.getStreamBufferInfo()->setAudioCallbackStreamUpdateClient( &synchroStarter );
|
|
synchroStarter.setData( &mp3StreamSound2, _sampleOffset );
|
|
|
|
#endif
|
|
|
|
const bool isMusic = false;
|
|
const bool isLooping = false;
|
|
SoundParams soundParams( isMusic, isLooping );
|
|
|
|
WAVEFORMATEX * waveFormat = (WAVEFORMATEX*) binWaveData1.getChunkData( RiffChunkManager::ms_riffTagFmt );
|
|
u32 waveFormatSize = binWaveData1.getChunkSize( RiffChunkManager::ms_riffTagFmt );
|
|
RAKI_ASSERT( binWaveData1.isStreamed() );
|
|
|
|
u16 formatTag = waveFormat->wFormatTag;
|
|
|
|
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 <= 48000 );
|
|
|
|
bool create = adpcmStreamSound1.createVoice( &binWaveData1, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart1 = RAKI_NEW( SeekableStreamPart )( &fileStream1, binWaveData1.getDataOffset(), binWaveData1.getDataSize() );
|
|
asyncReader1->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
asyncReader1->setStreamData( NULL, 0, seekableStreamPart1, NULL );
|
|
asyncReader1->setStreamingThread( &streamingThread );
|
|
u32 nbChannels = binWaveData1.getChunkData( RiffChunkManager::ms_riffTagDspR ) ? 2 : 1;
|
|
adpcmDataProvider1 = RAKI_NEW( ADPCMDataProvider )( asyncReader1, NULL, nbChannels, binWaveData1.getChunkData( RiffChunkManager::ms_riffTagDspL ), binWaveData1.getChunkData( RiffChunkManager::ms_riffTagDspR ) );
|
|
/*
|
|
const u64 seekSamplePosition1 = _sampleOffset;
|
|
const u64 seekBytePosition1 = adpcmDataProvider1->getByteBlockPosition( seekSamplePosition1 );
|
|
asyncReader1->seek( seekBytePosition1, SeekableStream::fromBeginning );
|
|
*/
|
|
adpcmStreamSound1.prepare( adpcmDataProvider1 );
|
|
adpcmStreamSound1.updateRouting( true );
|
|
|
|
create = adpcmStreamSound2.createVoice( &binWaveData2, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart2 = RAKI_NEW( SeekableStreamPart )( &fileStream2, binWaveData2.getDataOffset(), binWaveData2.getDataSize() );
|
|
asyncReader2->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
asyncReader2->setStreamData( NULL, 0, seekableStreamPart2, NULL );
|
|
asyncReader2->setStreamingThread( &streamingThread );
|
|
nbChannels = binWaveData2.getChunkData( RiffChunkManager::ms_riffTagDspR ) ? 2 : 1;
|
|
adpcmDataProvider2 = RAKI_NEW( ADPCMDataProvider )( asyncReader2, NULL, nbChannels, binWaveData2.getChunkData( RiffChunkManager::ms_riffTagDspL ), binWaveData2.getChunkData( RiffChunkManager::ms_riffTagDspR ) );
|
|
|
|
const u64 seekSamplePosition2 = _sampleOffset;
|
|
const u64 seekBytePosition2 = adpcmDataProvider2->getByteBlockPosition( seekSamplePosition2 );
|
|
asyncReader2->seek( seekBytePosition2, SeekableStream::fromBeginning );
|
|
|
|
adpcmStreamSound2.prepare( adpcmDataProvider2 );
|
|
adpcmStreamSound2.updateRouting( true );
|
|
adpcmStreamSound2.pause();
|
|
|
|
adpcmStreamSound1.start();
|
|
bool isPlaying = adpcmStreamSound1.isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
|
|
}
|
|
break;
|
|
|
|
#endif // RAKI_PLATFORM_WII
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
case WAVE_FORMAT_ADPCM:
|
|
{
|
|
RAKI_ASSERT( waveFormat->nChannels <= 2 );
|
|
RAKI_ASSERT( waveFormat->wBitsPerSample <= 16 );
|
|
RAKI_ASSERT( waveFormat->nSamplesPerSec <= 48000 );
|
|
|
|
bool create = adpcmStreamSound1.createVoice( &binWaveData1, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
seekableStreamPart1 = RAKI_NEW( SeekableStreamPart )( &fileStream1, binWaveData1.getDataOffset(), binWaveData1.getDataSize() );
|
|
asyncReader1->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
asyncReader1->setStreamData( NULL, 0, seekableStreamPart1, NULL );
|
|
asyncReader1->setStreamingThread( &streamingThread );
|
|
|
|
const u32 nbChannels1 = binWaveData1.getChunkData( RiffChunkManager::ms_riffTagDspR ) ? 2 : 1;
|
|
RAKI_ASSERT( nbChannels1 == 2 ); // ADPCMStreamSoundNative adpcmStreamSound( 2 );
|
|
adpcmDataProvider1 = RAKI_NEW( ADPCMDataProvider )( asyncReader1, (void*)1, nbChannels1, true, binWaveData1.getChunkData( RiffChunkManager::ms_riffTagDspL ), binWaveData1.getChunkData( RiffChunkManager::ms_riffTagDspR ) );
|
|
const u64 seekSamplePosition1 = 0;
|
|
const u64 seekBytePosition1 = adpcmDataProvider1->getByteBlockPosition( seekSamplePosition1 );
|
|
asyncReader1->seek( seekBytePosition1, SeekableStream::fromBeginning );
|
|
|
|
adpcmStreamSound1.prepare( adpcmDataProvider1 );
|
|
adpcmStreamSound1.updateRouting( true );
|
|
|
|
|
|
|
|
create = adpcmStreamSound2.createVoice( &binWaveData2, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
seekableStreamPart2 = RAKI_NEW( SeekableStreamPart )( &fileStream2, binWaveData2.getDataOffset(), binWaveData2.getDataSize() );
|
|
asyncReader2->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
asyncReader2->setStreamData( NULL, 0, seekableStreamPart2, NULL );
|
|
asyncReader2->setStreamingThread( &streamingThread );
|
|
|
|
const u32 nbChannels2 = binWaveData2.getChunkData( RiffChunkManager::ms_riffTagDspR ) ? 2 : 1;
|
|
RAKI_ASSERT( nbChannels2 == 2 ); // ADPCMStreamSoundNative adpcmStreamSound( 2 );
|
|
adpcmDataProvider2 = RAKI_NEW( ADPCMDataProvider )( asyncReader2, (void*)2, nbChannels2, true, binWaveData2.getChunkData( RiffChunkManager::ms_riffTagDspL ), binWaveData2.getChunkData( RiffChunkManager::ms_riffTagDspR ) );
|
|
const u64 seekSamplePosition2 = _sampleOffset;
|
|
const u64 seekBytePosition2 = adpcmDataProvider2->getByteBlockPosition( seekSamplePosition2 );
|
|
asyncReader2->seek( seekBytePosition2, SeekableStream::fromBeginning );
|
|
|
|
adpcmStreamSound2.prepare( adpcmDataProvider2 );
|
|
adpcmStreamSound2.updateRouting( true );
|
|
adpcmStreamSound2.pause();
|
|
|
|
|
|
|
|
adpcmStreamSound1.start();
|
|
|
|
bool isPlaying = adpcmStreamSound1.isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
|
|
}
|
|
break;
|
|
|
|
#endif // RAKI_PLATFORM_CAFE
|
|
|
|
|
|
|
|
#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 <= 48000 );
|
|
|
|
bool create = pcmStreamSound1.createVoice( &binWaveData1, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart1 = RAKI_NEW( SeekableStreamPart )( &fileStream1, binWaveData1.getDataOffset(), binWaveData1.getDataSize() );
|
|
asyncReader1->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
asyncReader1->setStreamData( NULL, 0, seekableStreamPart1, NULL );
|
|
dataProvider1 = RAKI_NEW( PCMDataProvider )( asyncReader1, (void*)1, (u64) pcmFormat.nBlockAlign, pcmFormat.nChannels, true );
|
|
asyncReader1->setStreamingThread( &streamingThread );
|
|
pcmStreamSound1.prepare( dataProvider1 );
|
|
pcmStreamSound1.updateRouting( true );
|
|
|
|
create = pcmStreamSound2.createVoice( &binWaveData2, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart2 = RAKI_NEW( SeekableStreamPart )( &fileStream2, binWaveData2.getDataOffset(), binWaveData2.getDataSize() );
|
|
asyncReader2->allocateBuffers( BUFFER_PREFETCH_SIZE );
|
|
asyncReader2->setStreamData( NULL, 0, seekableStreamPart2, NULL );
|
|
dataProvider2 = RAKI_NEW( PCMDataProvider )( asyncReader2, (void*)2, (u64) pcmFormat.nBlockAlign, pcmFormat.nChannels, true );
|
|
const u64 seekBytePosition2 = dataProvider2->getByteBlockPosition( _sampleOffset );
|
|
asyncReader2->seek( seekBytePosition2 , SeekableStream::fromBeginning );
|
|
asyncReader2->setStreamingThread( &streamingThread );
|
|
pcmStreamSound2.prepare( dataProvider2 );
|
|
pcmStreamSound2.updateRouting( true );
|
|
|
|
|
|
pcmStreamSound1.start();
|
|
|
|
bool isPlaying = pcmStreamSound1.isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
}
|
|
break;
|
|
#endif // defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
case WAVE_FORMAT_XMA2:
|
|
{
|
|
RAKI_ASSERT( waveFormatSize >= sizeof( XMA2WAVEFORMATEX ) );
|
|
|
|
bool create = xma2StreamSound1.createVoice( &binWaveData1, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart1 = RAKI_NEW( SeekableStreamPart )( &fileStream1, binWaveData1.getDataOffset(), binWaveData1.getDataSize() );
|
|
asyncReader1->allocateBuffers( BUFFER_PREFETCH_SIZE / 2 );
|
|
asyncReader1->setStreamData( NULL, 0, seekableStreamPart1, NULL );
|
|
u32 * seekTable1 = (u32*)binWaveData1.getChunkData( RiffChunkManager::ms_riffTagSeek );
|
|
u32 seekTableSize1 = binWaveData1.getChunkSize( RiffChunkManager::ms_riffTagSeek );
|
|
XMA2WAVEFORMATEX * xma2waveFormat = (XMA2WAVEFORMATEX *)waveFormat;
|
|
const u64 seekSamplePosition1 = 0;
|
|
dataProvider1 = RAKI_NEW( XMA2DataProvider )( asyncReader1, xma2waveFormat, seekTable1, seekTableSize1, 0, 0, 0, xma2waveFormat->wfx.nChannels, seekSamplePosition1 );
|
|
const u64 seekBytePosition1 = dataProvider1->getByteBlockPosition( seekSamplePosition1 );
|
|
const u64 playStartSamplePositionInBuffer1 = dataProvider1->getSampleOffsetInBuffer( seekBytePosition1, seekSamplePosition1 );
|
|
asyncReader1->seek( seekBytePosition1, SeekableStream::fromBeginning );
|
|
asyncReader1->setStreamingThread( &streamingThread );
|
|
xma2StreamSound1.prepare( dataProvider1, playStartSamplePositionInBuffer1 );
|
|
xma2StreamSound1.setDecibelVolume( 0.f );
|
|
xma2StreamSound1.updateRouting( true );
|
|
|
|
create = xma2StreamSound2.createVoice( &binWaveData2, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart2 = RAKI_NEW( SeekableStreamPart )( &fileStream2, binWaveData2.getDataOffset(), binWaveData2.getDataSize() );
|
|
asyncReader2->allocateBuffers( BUFFER_PREFETCH_SIZE / 2 );
|
|
asyncReader2->setStreamData( NULL, 0, seekableStreamPart2, NULL );
|
|
u32 * seekTable2 = (u32*)binWaveData2.getChunkData( RiffChunkManager::ms_riffTagSeek );
|
|
u32 seekTableSize2 = binWaveData2.getChunkSize( RiffChunkManager::ms_riffTagSeek );
|
|
const u64 seekSamplePosition2 = _sampleOffset;
|
|
dataProvider2 = RAKI_NEW( XMA2DataProvider )( asyncReader2, xma2waveFormat, seekTable2, seekTableSize2, 0, 0, 0, xma2waveFormat->wfx.nChannels, seekSamplePosition2 );
|
|
const u64 seekBytePosition2 = dataProvider2->getByteBlockPosition( seekSamplePosition2 );
|
|
const u64 playStartSamplePositionInBuffer2 = dataProvider2->getSampleOffsetInBuffer( seekBytePosition2, seekSamplePosition2 );
|
|
asyncReader2->seek( seekBytePosition2, SeekableStream::fromBeginning );
|
|
asyncReader2->setStreamingThread( &streamingThread );
|
|
xma2StreamSound2.prepare( dataProvider2, playStartSamplePositionInBuffer2 );
|
|
xma2StreamSound2.setDecibelVolume( 0.f );
|
|
xma2StreamSound2.updateRouting( true );
|
|
|
|
xma2StreamSound1.start();
|
|
}
|
|
break;
|
|
#endif // ( RAKI_PLATFORM_XB360 )
|
|
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
case WAVE_FORMAT_MPEGLAYER3:
|
|
{
|
|
/* void * mp3Data = waveFile.getChunkData( dataChunck );
|
|
unsigned int tSize = 0;
|
|
unsigned int offset = 0;
|
|
float tTime = 0.f;
|
|
|
|
while(1)
|
|
{
|
|
CellMSMP3FrameHeader header;
|
|
|
|
int ret = cellMSMP3GetFrameInfo( mp3Data, &header );
|
|
if ( ret == -1 )
|
|
{
|
|
printf("Invalid MP3 header\n");
|
|
printf("Offset=0x%x\n",offset);
|
|
break;
|
|
}
|
|
|
|
tSize += header.PacketSize; // Update total file size
|
|
if ((header.ID3==0)&&(header.Tag==0))
|
|
tTime+=header.PacketTime; // Update total playing time (in seconds)
|
|
mp3Data = (void*)( header.PacketSize + (u32)mp3Data ); // Move forward to next packet
|
|
offset+=header.PacketSize;
|
|
|
|
// ** Display packet information **
|
|
// Using the packet size and packet time information, it is possible to build "Seek Tables".
|
|
// Then, by knowing approximately what time (in seconds) you require to playback from,
|
|
// you can start playback from the closest data packet by searching for the closest record in the table.
|
|
|
|
if (header.ID3!=0)
|
|
{
|
|
printf("Found ID3 Info\n");
|
|
printf("Version: %x.%x\n",header.ID3>>8, header.ID3&255);
|
|
}
|
|
else if (header.Tag!=0)
|
|
{
|
|
printf("Found Tag info\n");
|
|
}
|
|
else
|
|
{
|
|
printf("Sync: 0x%x\n",header.Sync);
|
|
printf("ID: 0x%x\n",header.ID);
|
|
printf("Layer: 0x%x\n",header.Layer);
|
|
printf("ProtBit: 0x%x\n",header.ProtBit);
|
|
printf("BitRate: %d\n",header.BitRate);
|
|
printf("Frequency: %d\n",header.Frequency);
|
|
printf("PadBit: 0x%x\n",header.PadBit);
|
|
printf("PrivBit: 0x%x\n",header.PrivBit);
|
|
printf("Mode: 0x%x\n",header.Mode);
|
|
printf("Copy: 0x%x\n",header.Copy);
|
|
printf("Home: 0x%x\n",header.Home);
|
|
printf("Emphasis: 0x%x\n",header.Emphesis);
|
|
printf("Packet Time (secs): %f\n",header.PacketTime);
|
|
}
|
|
printf("Packet Size (bytes): 0x%x\n",header.PacketSize);
|
|
|
|
if ( tSize == waveFile.getChunkSize( dataChunck ) )
|
|
{
|
|
printf("MP3 File is valid.\n");
|
|
printf("Total Playback Time at %d Hz = (secs): %f\n",header.Frequency,tTime);
|
|
break;
|
|
}
|
|
else if (tSize > waveFile.getChunkSize( dataChunck ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
bool create = mp3StreamSound1.createVoice( &binWaveData1, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart1 = RAKI_NEW( SeekableStreamPart )( &fileStream1, binWaveData1.getDataOffset(), binWaveData1.getDataSize() );
|
|
asyncReader1->allocateBuffers( BUFFER_PREFETCH_SIZE / 2 );
|
|
asyncReader1->setStreamData( NULL, 0, seekableStreamPart1, NULL );
|
|
asyncReader1->setStreamingThread( &streamingThread );
|
|
dataProvider1 = RAKI_NEW( MP3DataProvider )( asyncReader1, NULL, waveFormat->nChannels );
|
|
mp3StreamSound1.prepare( dataProvider1 );
|
|
mp3StreamSound1.updateRouting( true );
|
|
|
|
create = mp3StreamSound2.createVoice( &binWaveData2, soundParams );
|
|
RAKI_ASSERT( create );
|
|
seekableStreamPart2 = RAKI_NEW( SeekableStreamPart )( &fileStream2, binWaveData2.getDataOffset(), binWaveData2.getDataSize() );
|
|
asyncReader2->allocateBuffers( BUFFER_PREFETCH_SIZE / 2 );
|
|
asyncReader2->setStreamData( NULL, 0, seekableStreamPart2, NULL );
|
|
asyncReader2->setStreamingThread( &streamingThread );
|
|
dataProvider2 = RAKI_NEW( MP3DataProvider )( asyncReader2, NULL, waveFormat->nChannels );
|
|
|
|
const u64 seekSamplePosition2 = _sampleOffset;
|
|
const u64 seekBytePosition2 = dataProvider2->getByteBlockPosition( seekSamplePosition2 );
|
|
asyncReader2->seek( seekBytePosition2, SeekableStream::fromBeginning );
|
|
|
|
mp3StreamSound2.prepare( dataProvider2 );
|
|
mp3StreamSound2.updateRouting( true );
|
|
mp3StreamSound2.pause();
|
|
|
|
|
|
mp3StreamSound1.start();
|
|
}
|
|
break;
|
|
#endif // ( RAKI_PLATFORM_PS3 )
|
|
|
|
default:
|
|
RAKI_ASSERT_FALSE;
|
|
}
|
|
|
|
// #define COUNT_LOOP 50
|
|
// #define COUNT_STOP 20
|
|
// #define COUNT_START 34
|
|
|
|
int count = 0;
|
|
|
|
for ( ;; )
|
|
{
|
|
bool isPlaying = false;
|
|
|
|
#ifdef RAKI_PLATFORM_WII
|
|
VIWaitForRetrace();
|
|
#else // RAKI_PLATFORM_WII
|
|
Thread::sleep( 25 );
|
|
#endif // RAKI_PLATFORM_WII
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
pcmStreamSound1.update();
|
|
pcmStreamSound2.update();
|
|
isPlaying |= pcmStreamSound1.isPlaying();
|
|
isPlaying |= pcmStreamSound2.isPlaying();
|
|
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
xma2StreamSound1.update();
|
|
isPlaying |= xma2StreamSound1.isPlaying();
|
|
xma2StreamSound2.update();
|
|
isPlaying |= xma2StreamSound2.isPlaying();
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
adpcmStreamSound1.update();
|
|
isPlaying |= adpcmStreamSound1.isPlaying();
|
|
adpcmStreamSound2.update();
|
|
isPlaying |= adpcmStreamSound2.isPlaying();
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
mp3StreamSound1.update();
|
|
isPlaying |= mp3StreamSound1.isPlaying();
|
|
mp3StreamSound2.update();
|
|
isPlaying |= mp3StreamSound2.isPlaying();
|
|
|
|
#endif
|
|
|
|
asyncReader1->update( true );
|
|
asyncReader2->update( true );
|
|
/*
|
|
if ( ( count % COUNT_LOOP ) == COUNT_STOP )
|
|
xma2StreamSound.stop();
|
|
|
|
if ( ( count % COUNT_LOOP ) == COUNT_START )
|
|
xma2StreamSound.play();
|
|
*/
|
|
++count;
|
|
|
|
if ( !isPlaying )
|
|
break;
|
|
}
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
pcmStreamSound1.stop();
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
xma2StreamSound1.stop();
|
|
xma2StreamSound2.stop();
|
|
#elif defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE )
|
|
adpcmStreamSound1.stop();
|
|
adpcmStreamSound2.stop();
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
mp3StreamSound1.stop();
|
|
mp3StreamSound2.stop();
|
|
#endif
|
|
|
|
// XAudio2 doc: Stop is always asynchronous, even if called within a callback
|
|
Thread::sleep( 5000 );
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
pcmStreamSound1.destroyVoice();
|
|
pcmStreamSound2.destroyVoice();
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
xma2StreamSound1.destroyVoice();
|
|
xma2StreamSound2.destroyVoice();
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
adpcmStreamSound1.destroyVoice();
|
|
adpcmStreamSound2.destroyVoice();
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
mp3StreamSound1.destroyVoice();
|
|
mp3StreamSound2.destroyVoice();
|
|
#endif
|
|
|
|
Thread::sleep( 500 );
|
|
|
|
if ( asyncReader1 ) RAKI_DELETE( asyncReader1 );
|
|
asyncReader2 = NULL;
|
|
|
|
if ( asyncReader2 ) RAKI_DELETE( asyncReader2 );
|
|
asyncReader2 = NULL;
|
|
|
|
if ( seekableStreamPart1 ) RAKI_DELETE( seekableStreamPart1 );
|
|
seekableStreamPart1 = NULL;
|
|
|
|
if ( seekableStreamPart2 ) RAKI_DELETE( seekableStreamPart2 );
|
|
seekableStreamPart2 = NULL;
|
|
|
|
if ( dataProvider1 ) RAKI_DELETE( dataProvider1 );
|
|
dataProvider1 = NULL;
|
|
|
|
if ( dataProvider2 ) RAKI_DELETE( dataProvider2 );
|
|
dataProvider2 = NULL;
|
|
|
|
streamingThread.stop();
|
|
|
|
Thread::sleep( 500 );
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace raki
|
|
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
|
|
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 run_demo (int intArg, void *ptrArg)
|
|
{
|
|
raki::SimpleHeap_Cafe::init();
|
|
|
|
raki::TestInitializer initializer;
|
|
|
|
const char path1[] = "/vol/content/_raki_/BeatsOnLeft.wav.cafe";
|
|
const char path2[] = "/vol/content/_raki_/BeatsOnRight.wav.cafe";
|
|
|
|
const raki::u64 sampleOffset = 123456;
|
|
raki::TestSynchroStreams( path1, path2, sampleOffset );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined ( RAKI_USING_XAUDIO2 )
|
|
int _tmain( int /*argc*/, _TCHAR* /*argv[]*/ )
|
|
#else // RAKI_USING_XAUDIO2
|
|
int main( int /*argc*/, char * /*argv[]*/ )
|
|
#endif // RAKI_USING_XAUDIO2
|
|
{
|
|
#if defined ( RAKI_PLATFORM_WII )
|
|
DVDInit();
|
|
VIInit();
|
|
|
|
raki::SystemAllocator_Initialize();
|
|
|
|
#elif defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
raki::CoInitializeInitObject coInitializeInitObject;
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
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;
|
|
|
|
#endif
|
|
|
|
|
|
#if !defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
|
|
const raki::u64 sampleOffset = 123456;
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
const char path1[] = "Y:/JD5/JD/main/extern/Raki/TestData/BeatsOnLeft.wav.w32pcm";
|
|
const char path2[] = "Y:/JD5/JD/main/extern/Raki/TestData/BeatsOnRight.wav.w32pcm";
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
const char path1[] = "game:\\BeatsOnLeft.wav.x360";
|
|
const char path2[] = "game:\\BeatsOnRight.wav.x360";
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
const char path1[] = "/app_home/Y:/JD5/JD/main/extern/Raki/TestData/BeatsOnLeft.wav.ps3";
|
|
const char path2[] = "/app_home/Y:/JD5/JD/main/extern/Raki/TestData/BeatsOnRight.wav.ps3";
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
const char path1[] = "_raki_/BeatsOnLeft.wav.wii";
|
|
const char path2[] = "_raki_/BeatsOnRight.wav.wii";
|
|
#endif
|
|
|
|
raki::TestInitializer initializer;
|
|
|
|
raki::TestSynchroStreams( path1, path2, sampleOffset );
|
|
|
|
return 0;
|
|
|
|
#endif // !defined ( RAKI_PLATFORM_CAFE )
|
|
}
|
|
|
|
|
|
|
|
|