Skip to content

Commit 295291e

Browse files
authored
Merge pull request scp-fs2open#7456 from Goober5000/fix/openal_underrun
fix audiostream cutouts from openal buffer underrun
2 parents 65a5c1f + 1245546 commit 295291e

1 file changed

Lines changed: 19 additions & 5 deletions

File tree

code/sound/audiostr.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
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

Comments
 (0)