diff --git a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp index 9af1ed5905..fa02ad4349 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp +++ b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp @@ -8,8 +8,7 @@ static const int channels = 2; static const int bytes_per_frame = channels*2; /* 16-bit */ - -static const int frames_to_buffer = 4096; +static int frames_to_buffer; static const int num_chunks = 8; static int chunksize() { return frames_to_buffer / num_chunks; } @@ -18,7 +17,10 @@ RageSound_Generic_Software::sound::sound() { snd = NULL; state = STOPPED; +} +void RageSound_Generic_Software::sound::Init() +{ /* Reserve enough blocks in the buffer to hold the buffer; plus some extra, since blocks * are partially read by Mix(); plus some more extra, since we can buffer one block * over frames_to_buffer (we buffer until filled >= frames_to_buffer). */ @@ -294,13 +296,26 @@ void RageSound_Generic_Software::StopMixing( RageSoundBase *snd ) void RageSound_Generic_Software::StartDecodeThread() { ASSERT( !m_DecodeThread.IsCreated() ); + + /* Initialize the sound buffers, now that frames_to_buffer is finalized. */ + for( unsigned i = 0; i < ARRAYSIZE(sounds); ++i ) + sounds[i].Init(); + m_DecodeThread.Create( DecodeThread_start, this ); } +void RageSound_Generic_Software::SetDecodeBufferSize( int frames ) +{ + ASSERT( !m_DecodeThread.IsCreated() ); + + frames_to_buffer = frames; +} + RageSound_Generic_Software::RageSound_Generic_Software() { shutdown_decode_thread = false; - + SetDecodeBufferSize( 4096 ); + m_DecodeThread.SetName("Decode thread"); } diff --git a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h index 1e81438332..a9a71c9685 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h +++ b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h @@ -72,6 +72,7 @@ class RageSound_Generic_Software: public RageSoundDriver } state; sound(); + void Init(); }; /* List of currently playing sounds: XXX no vector */ @@ -89,6 +90,12 @@ protected: /* Start the decoding. This should be called once the hardware is set up and * GetSampleRate will return the correct value. */ void StartDecodeThread(); + + /* Call this before calling StartDecodeThread to set the desired decoding buffer + * size. This is the number of frames that Mix() will try to be able to return + * at once. This should generally be slightly larger than the sound writeahead, + * to allow filling the buffer after an underrun. The default is 4096 frames. */ + void SetDecodeBufferSize( int frames ); /* Override this to set the priority of the decoding thread, which should be above * normal priority but not realtime. */ diff --git a/stepmania/src/arch/Sound/RageSoundDriver_WaveOut.cpp b/stepmania/src/arch/Sound/RageSoundDriver_WaveOut.cpp index 830cee1e20..9c9bc8ecb5 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_WaveOut.cpp +++ b/stepmania/src/arch/Sound/RageSoundDriver_WaveOut.cpp @@ -135,6 +135,9 @@ RageSound_WaveOut::RageSound_WaveOut() buffers[b].dwFlags |= WHDR_DONE; } + /* We have a very large writeahead; make sure we have a large enough decode + * buffer to recover cleanly from underruns. */ + SetDecodeBufferSize( buffersize_frames * 3/2 ); StartDecodeThread(); MixingThread.SetName("Mixer thread");