2424#include " sound/ffmpeg/FFmpegWaveFile.h"
2525#endif
2626
27- # define MAX_STREAM_BUFFERS 4
27+ constexpr size_t MAX_STREAM_BUFFERS = 8 ;
2828
2929// status
3030#define ASF_FREE 0
@@ -438,7 +438,7 @@ bool AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service
438438 const auto alFormat = openal_get_format (m_fileProps.bytes_per_sample * 8 , m_fileProps.num_channels );
439439
440440 if ( !service ) {
441- for (int ib = 0 ; ib < MAX_STREAM_BUFFERS ; ib++ ) {
441+ for (auto &buffer_id : m_buffer_ids ) {
442442 num_bytes_read = m_pwavefile->Read (uncompressed_wave_data, m_cbBufSize);
443443
444444 // if looping then maybe reset wavefile and keep going
@@ -452,8 +452,8 @@ bool AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service
452452 m_bReadingDone = 1 ;
453453 break ;
454454 } else if (num_bytes_read > 0 ) {
455- OpenAL_ErrorCheck ( alBufferData (m_buffer_ids[ib] , alFormat, uncompressed_wave_data, num_bytes_read, m_fileProps.sample_rate ), { fRtn = false ; goto ErrorExit; } );
456- OpenAL_ErrorCheck ( alSourceQueueBuffers (m_source_id, 1 , &m_buffer_ids[ib] ), { fRtn = false ; goto ErrorExit; } );
455+ OpenAL_ErrorCheck ( alBufferData (buffer_id , alFormat, uncompressed_wave_data, num_bytes_read, m_fileProps.sample_rate ), { fRtn = false ; goto ErrorExit; } );
456+ OpenAL_ErrorCheck ( alSourceQueueBuffers (m_source_id, 1 , &buffer_id ), { fRtn = false ; goto ErrorExit; } );
457457
458458 *num_bytes_written += num_bytes_read;
459459 }
@@ -511,7 +511,7 @@ uint AudioStream::GetMaxWriteSize (void)
511511
512512 OpenAL_ErrorCheck ( alGetSourcei (m_source_id, AL_BUFFERS_QUEUED , &q), return 0 );
513513
514- if (!n && (q >= MAX_STREAM_BUFFERS )) // all buffers queued
514+ if (!n && (q >= sz2i ( MAX_STREAM_BUFFERS ) )) // all buffers queued
515515 dwMaxSize = 0 ;
516516
517517 // nprintf(("Alan","Max write size: %d\n", dwMaxSize));
@@ -600,6 +600,20 @@ bool AudioStream::ServiceBuffer (void)
600600 m_bPastLimit = true ;
601601 }
602602
603+ // Recover from buffer underrun: if the source stopped because the queue drained
604+ // between service ticks, OpenAL will not auto-resume even after WriteWaveData
605+ // queues more buffers. We have to call alSourcePlay again ourselves.
606+ ALint state = AL_PLAYING ;
607+ OpenAL_ErrorPrint ( alGetSourcei (m_source_id, AL_SOURCE_STATE , &state) );
608+ if (state == AL_STOPPED && m_fPlaying && !m_bReadingDone) {
609+ ALint queued = 0 ;
610+ OpenAL_ErrorPrint ( alGetSourcei (m_source_id, AL_BUFFERS_QUEUED , &queued) );
611+ if (queued > 0 ) {
612+ nprintf ((" Sound" , " SOUND => Audiostream underrun, restarting playback\n " ));
613+ OpenAL_ErrorPrint ( alSourcePlay (m_source_id) );
614+ }
615+ }
616+
603617 if ( PlaybackDone () ) {
604618 if ( m_bDestroy_when_faded == true ) {
605619 SDL_UnlockMutex ( write_lock );
0 commit comments