Replace Sleep function with waitable event
This commit is contained in:
parent
8c9a679eca
commit
587379dc29
|
@ -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, ¬ify );
|
||||||
|
|
||||||
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 );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue