#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/Sources/SineSource.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/Specific/_XB360/Specific_X360.h" #include "RakiTests/Sounds/XMA2DataProvider.h" #include "RakiEngine/Mics/XMicManager_X360.h" #elif defined ( RAKI_PLATFORM_PS3 ) #include "RakiEngine/Sounds/_PS3/PCMStreamSoundNative_PS3.h" #include "RakiEngine/Mics/Mic_PS3.h" #elif defined ( RAKI_PLATFORM_CAFE ) #include "RakiEngine/Mics/Mic_Cafe.h" #include "RakiEngine/Sounds/_Cafe/PCMStreamSoundNative_Cafe.h" #include "RakiTests/_Cafe/Memory/SimpleHeap_Cafe.h" #elif defined ( RAKI_PLATFORM_ORBIS ) #include "RakiEngine/Mics/Mic_Orbis.h" #endif #if defined ( RAKI_PLATFORM_WIN32 ) #include "RakiTests/_Win32/CoInitializeInitObject.h" #include "RakiEngine/Mics/MicWasapi.h" #endif // ( RAKI_PLATFORM_WIN32 ) #include "RakiTests/Initializer/TestInitializer.h" #define TESTSTREAMING_WITHOUT_PREFETCHBUFFER namespace raki { class FakeMicWaveData : public WaveData { public: FakeMicWaveData() { m_waveData.wFormatTag = WAVE_FORMAT_PCM; m_waveData.nChannels = 1; const u32 samplingRate = 16000; //RAKI_NATIVE_SAMPLING_RATE; m_waveData.nSamplesPerSec = samplingRate; m_waveData.nAvgBytesPerSec = m_waveData.nSamplesPerSec * 2; m_waveData.nBlockAlign = 2; m_waveData.wBitsPerSample = 16; m_waveData.cbSize = 0; } virtual const void * getChunkData( const char * _name ) const { if ( RiffChunkManager::singleton().getTypeIdFromName( _name ) == RiffChunkManager::singleton().getTypeIdFromName( RiffChunkManager::ms_riffTagFmt ) ) return &m_waveData; return NULL; } virtual u32 getChunkSize( const char * _name ) const { if ( RiffChunkManager::singleton().getTypeIdFromName( _name ) == RiffChunkManager::singleton().getTypeIdFromName( RiffChunkManager::ms_riffTagFmt ) ) return sizeof( m_waveData ); return 0; } virtual u32 getByteBlockPosForSamplePos( const u32 /*_samplePosition*/ ) const { RAKI_ASSERT_FALSE; return 0; } virtual u32 getSamplePosForByteBlockPos( const u32 /*_byteBlockPosition*/ ) const { RAKI_ASSERT_FALSE; return 0; } virtual u32 getSampleOffsetInBuffer( const u32 /*_byteBlockPosition*/, const u32 /*_samplePosition*/ ) const { RAKI_ASSERT_FALSE; return 0; } private: WAVEFORMATEX m_waveData; }; class TestMicDataProvider : public SoundStreamDataProvider { public: TestMicDataProvider( MicDataProvider * _micDataProvider, const u64 _sampleSize ) : m_micDataProvider( _micDataProvider ) , SoundStreamDataProvider( 1 ) // mono mic , m_sineSource( 1 ) , m_sampleSize( _sampleSize ) , m_samplePos( 0 ) { RAKI_ASSERT( _sampleSize > 0 ) } virtual u64 pullData( void * _buffer, const u64 _sizeToRead ) //, bool /*_emergencyPull*/ ) { u32 available = m_micDataProvider->getAvailableSampleSize(); // 16 kHz -> 48 kHz if ( available > _sizeToRead / 2 ) { u32 samplesRead = m_micDataProvider->pullSamples( _buffer, (u32)_sizeToRead / 2 ); RAKI_OUTPUT("MicDataProvider::pullData read %d samples", samplesRead); } else { // RAKI_OUTPUT("MicDataProvider::pullData unable to read any sample (available %d - size/2 %d)", available, _sizeToRead/2); return 0; } return _sizeToRead; // AudioBuffer buffer( AudioBuffer::pcm16, _buffer, _sizeToRead, 1 ); // return m_sineSource.pullSourceBuffer( buffer ); } inline virtual u64 getRemainingByteSize() const { return ( m_sampleSize - m_samplePos ) * 2; } inline virtual u64 getEntireByteSize() const { return m_sampleSize * 2; } inline virtual u64 getEntireSampleSize() const { return m_sampleSize - m_samplePos; } inline virtual u64 getCurrentSamplePosition() const { return m_samplePos; } virtual const void * getClientData() const { return NULL; } virtual bool isReadyToStart() const { return true; } virtual u64 getByteBlockPosition( const u64 _startSamplePosition ) const { return _startSamplePosition * 2; } virtual u64 getSampleOffsetInBuffer( const u64 /*_byteBlockPosition*/, const u64 /*_samplePosition*/ ) const { RAKI_ASSERT_FALSE; return 0; } virtual bool isFirstBuffer( const u64 _samplePositionBeforeSubmit ) const { return _samplePositionBeforeSubmit == 0; } virtual void prefetchNextStream(){} virtual void setNextStreamNow(){} virtual void update( bool /*_launchNewReadRequests*/ ) { } private: MicDataProvider * m_micDataProvider; SineSource m_sineSource; u64 m_samplePos; u64 m_sampleSize; }; extern void SystemAllocator_Initialize(); #if defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE ) #define BUFFER_SIZE 55040 #else #define BUFFER_SIZE 4608 #endif static void TestSoundStreaming() { #if defined ( RAKI_PLATFORM_XB360 ) XMicManager mic; #elif defined ( RAKI_PLATFORM_WIN32 ) MicWasapi mic( 16000 ); #elif defined ( RAKI_PLATFORM_CAFE ) MicCafe mic; #elif defined ( RAKI_PLATFORM_PS3 ) MicPS3 mic( 16000 ); #endif mic.init(); mic.startMicrophone(); TestMicDataProvider testMicDataProvider( &mic, 0x100000000 ); FakeMicWaveData fakeMicWaveData; bool buffersAllocated = false; #if defined ( RAKI_PLATFORM_WIN32 ) #if defined ( RAKI_USING_SOFTWARE_ENGINE ) StreamSoftwareSound sound; #else PCMStreamSoundNative sound; #endif // pcmStreamSound.getStreamBufferInfo()->setStreamUpdateClient( &testUpdateClient ); buffersAllocated = sound.allocateBuffers( BUFFER_SIZE ); RAKI_ASSERT( buffersAllocated ); #elif defined ( RAKI_PLATFORM_XB360 ) PCMStreamSoundNative sound; // xma2StreamSound.getStreamBufferInfo()->setStreamUpdateClient( &testUpdateClient ); buffersAllocated = sound.allocateBuffers( BUFFER_SIZE ); RAKI_ASSERT( buffersAllocated ); #elif defined ( RAKI_PLATFORM_WII ) ADPCMStreamSoundNative adpcmStreamSound( 2 ); // adpcmStreamSound.getStreamBufferInfo()->setStreamUpdateClient( &testUpdateClient ); buffersAllocated = adpcmStreamSound.allocateBuffers( BUFFER_SIZE ); RAKI_ASSERT( buffersAllocated ); #elif defined ( RAKI_PLATFORM_CAFE ) PCMStreamSoundNative sound( 2 ); buffersAllocated = sound.allocateBuffers( BUFFER_SIZE ); RAKI_ASSERT( buffersAllocated ); #elif defined ( RAKI_PLATFORM_PS3 ) PCMStreamSoundNative sound; buffersAllocated = sound.allocateBuffers( BUFFER_SIZE ); RAKI_ASSERT( buffersAllocated ); #endif SoundParams soundParams; bool create = sound.createVoice( &fakeMicWaveData, soundParams ); RAKI_ASSERT( create ); sound.prepare( &testMicDataProvider ); sound.updateRouting( true ); sound.start(); bool isPlaying = sound.isPlaying(); RAKI_ASSERT( isPlaying ); #define COUNT_LOOP 50 #define COUNT_STOP 20 #define COUNT_START 34 int count = 0; const u32 bufferSampleSize = 2400; void * tempBuffer = Memory::malloc( bufferSampleSize * 2, Memory::engine ); f32 timeBeginning = Time::getTime(); while ( Time::getTime() < 5000.f + timeBeginning ) { bool isPlaying = false; mic.update(); // if ( bufferSampleSize < micManager.getAvailableSampleSize() ) // micManager.pullSamples( tempBuffer, bufferSampleSize ); #ifdef RAKI_PLATFORM_WII VIWaitForRetrace(); #else // RAKI_PLATFORM_WII Thread::sleep( 15 ); #endif // RAKI_PLATFORM_WII sound.update(); isPlaying |= sound.isPlaying(); testMicDataProvider.update( true ); ++count; // if ( !isPlaying ) // break; } sound.stop(); mic.stopMicrophone(); mic.uninit(); // XAudio2 doc: Stop is always asynchronous, even if called within a callback Thread::sleep( 500 ); sound.destroyVoice(); Thread::sleep( 500 ); Memory::free( tempBuffer ); } } // 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; raki::TestSoundStreaming(); 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 ) raki::TestInitializer initializer; raki::TestSoundStreaming(); return 0; #endif // !defined ( RAKI_PLATFORM_CAFE ) }