From 587379dc29f0c14e90f85d8d5b4706f373bec361 Mon Sep 17 00:00:00 2001 From: spacy51 Date: Sun, 9 Mar 2008 16:25:36 +0000 Subject: [PATCH] Replace Sleep function with waitable event --- src/win32/XAudio2.cpp | 81 ++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/src/win32/XAudio2.cpp b/src/win32/XAudio2.cpp index 67b64a80..3a7d2987 100644 --- a/src/win32/XAudio2.cpp +++ b/src/win32/XAudio2.cpp @@ -39,6 +39,27 @@ #include "../Globals.h" // for 'speedup' and 'synchronize' +// Synchronization Event +class XAudio2_BufferNotify : public IXAudio2VoiceCallback +{ +public: + HANDLE hBufferEndEvent; + + XAudio2_BufferNotify() { hBufferEndEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); } + ~XAudio2_BufferNotify() { CloseHandle( hBufferEndEvent ); } + + STDMETHOD_( void, OnBufferEnd ) ( void *pBufferContext ) { SetEvent( hBufferEndEvent ); } + + // dummies: + STDMETHOD_( void, OnVoiceProcessingPassStart ) () {} + STDMETHOD_( void, OnVoiceProcessingPassEnd ) () {} + STDMETHOD_( void, OnStreamEnd ) () {} + STDMETHOD_( void, OnBufferStart ) ( void *pBufferContext ) {} + STDMETHOD_( void, OnLoopEnd ) ( void *pBufferContext ) {} + STDMETHOD_( void, OnVoiceError ) ( void *pBufferContext, HRESULT Error ) {}; +}; + + // Class Declaration class XAudio2_Output : public ISound @@ -67,14 +88,15 @@ private: bool initialized; bool playing; UINT32 freq; - BYTE *buffers; + BYTE *buffers; int currentBuffer; IXAudio2 *xaud; - IXAudio2MasteringVoice *mVoice; // dest - IXAudio2SourceVoice *sVoice; // source + IXAudio2MasteringVoice *mVoice; // listener + IXAudio2SourceVoice *sVoice; // sound source XAUDIO2_BUFFER buf; XAUDIO2_VOICE_STATE vState; + XAudio2_BufferNotify notify; // buffer end notification }; @@ -85,7 +107,7 @@ XAudio2_Output::XAudio2_Output() initialized = false; playing = false; freq = 0; - buffers = 0; + buffers = NULL; currentBuffer = 0; xaud = NULL; @@ -181,7 +203,7 @@ bool XAudio2_Output::init() // Create Sound Emitter - hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, XAUDIO2_MAX_FREQ_RATIO ); + hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, ¬ify ); if( FAILED( hr ) ) { systemMessage( IDS_XAUDIO2_CANNOT_CREATE_SOURCEVOICE, NULL ); @@ -203,7 +225,25 @@ void XAudio2_Output::write() { if( !initialized || failed ) return; - bool drop = false; + while( true ) { + sVoice->GetState( &vState ); + + ASSERT( vState.BuffersQueued <= NBUFFERS ); + + if( vState.BuffersQueued < NBUFFERS ) { + // there is at least one free buffer + break; + } else { + // the maximum number of buffers is currently queued + if( synchronize && !speedup && !theApp.throttle ) { + // wait for one buffer to finish playing + WaitForSingleObject( notify.hBufferEndEvent, INFINITE ); + } else { + // drop current audio frame + return; + } + } + } // copy & protect the audio data in own memory area while playing it CopyMemory( &buffers[ currentBuffer * soundBufferLen ], soundFinalWave, soundBufferLen ); @@ -214,32 +254,7 @@ void XAudio2_Output::write() currentBuffer++; currentBuffer %= ( NBUFFERS + 1 ); - while( true ) { - sVoice->GetState( &vState ); - ASSERT( vState.BuffersQueued <= NBUFFERS ); - - if( vState.BuffersQueued == NBUFFERS ) { - // all buffers filled - if( speedup || !synchronize || theApp.throttle ) { - drop = true; - break; - } - - if( synchronize ) { - // wait for about half the time one buffer needs to finish - // unoptimized: ( sourceBufferLen * 1000 ) / ( freq * 2 * 2 ) * 1/2 - Sleep( soundBufferLen / ( freq >> 7 ) ); - } - } else { - // still room for new audio - break; - } - } - - if( !drop ) { - // add the sound buffer to the queue - sVoice->SubmitSourceBuffer( &buf ); - } + sVoice->SubmitSourceBuffer( &buf ); // send buffer to queue } @@ -281,6 +296,8 @@ void XAudio2_Output::reset() void XAudio2_Output::setThrottle( unsigned short throttle ) { + if( !initialized || failed ) return; + if( throttle == 0 ) throttle = 100; sVoice->SetFrequencyRatio( (float)throttle / 100.0f ); }