Replace Sleep function with waitable event

This commit is contained in:
spacy51 2008-03-09 16:25:36 +00:00
parent 8c9a679eca
commit 587379dc29
1 changed files with 49 additions and 32 deletions

View File

@ -39,6 +39,27 @@
#include "../Globals.h" // for 'speedup' and 'synchronize' #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 Declaration
class XAudio2_Output class XAudio2_Output
: public ISound : public ISound
@ -67,14 +88,15 @@ private:
bool initialized; bool initialized;
bool playing; bool playing;
UINT32 freq; UINT32 freq;
BYTE *buffers; BYTE *buffers;
int currentBuffer; int currentBuffer;
IXAudio2 *xaud; IXAudio2 *xaud;
IXAudio2MasteringVoice *mVoice; // dest IXAudio2MasteringVoice *mVoice; // listener
IXAudio2SourceVoice *sVoice; // source IXAudio2SourceVoice *sVoice; // sound source
XAUDIO2_BUFFER buf; XAUDIO2_BUFFER buf;
XAUDIO2_VOICE_STATE vState; XAUDIO2_VOICE_STATE vState;
XAudio2_BufferNotify notify; // buffer end notification
}; };
@ -85,7 +107,7 @@ XAudio2_Output::XAudio2_Output()
initialized = false; initialized = false;
playing = false; playing = false;
freq = 0; freq = 0;
buffers = 0; buffers = NULL;
currentBuffer = 0; currentBuffer = 0;
xaud = NULL; xaud = NULL;
@ -181,7 +203,7 @@ bool XAudio2_Output::init()
// Create Sound Emitter // Create Sound Emitter
hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, XAUDIO2_MAX_FREQ_RATIO ); hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, &notify );
if( FAILED( hr ) ) { if( FAILED( hr ) ) {
systemMessage( IDS_XAUDIO2_CANNOT_CREATE_SOURCEVOICE, NULL ); systemMessage( IDS_XAUDIO2_CANNOT_CREATE_SOURCEVOICE, NULL );
@ -203,7 +225,25 @@ void XAudio2_Output::write()
{ {
if( !initialized || failed ) return; 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 // copy & protect the audio data in own memory area while playing it
CopyMemory( &buffers[ currentBuffer * soundBufferLen ], soundFinalWave, soundBufferLen ); CopyMemory( &buffers[ currentBuffer * soundBufferLen ], soundFinalWave, soundBufferLen );
@ -214,32 +254,7 @@ void XAudio2_Output::write()
currentBuffer++; currentBuffer++;
currentBuffer %= ( NBUFFERS + 1 ); currentBuffer %= ( NBUFFERS + 1 );
while( true ) { sVoice->SubmitSourceBuffer( &buf ); // send buffer to queue
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 );
}
} }
@ -281,6 +296,8 @@ void XAudio2_Output::reset()
void XAudio2_Output::setThrottle( unsigned short throttle ) void XAudio2_Output::setThrottle( unsigned short throttle )
{ {
if( !initialized || failed ) return;
if( throttle == 0 ) throttle = 100; if( throttle == 0 ) throttle = 100;
sVoice->SetFrequencyRatio( (float)throttle / 100.0f ); sVoice->SetFrequencyRatio( (float)throttle / 100.0f );
} }