Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions code/sound/audiostr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "sound/ffmpeg/FFmpegWaveFile.h"
#endif

#define MAX_STREAM_BUFFERS 4
constexpr size_t MAX_STREAM_BUFFERS = 8;

// status
#define ASF_FREE 0
Expand Down Expand Up @@ -438,7 +438,7 @@ bool AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service
const auto alFormat = openal_get_format(m_fileProps.bytes_per_sample * 8, m_fileProps.num_channels);

if ( !service ) {
for (int ib = 0; ib < MAX_STREAM_BUFFERS; ib++) {
for (auto &buffer_id : m_buffer_ids) {
num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize);

// if looping then maybe reset wavefile and keep going
Expand All @@ -452,8 +452,8 @@ bool AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service
m_bReadingDone = 1;
break;
} else if (num_bytes_read > 0) {
OpenAL_ErrorCheck( alBufferData(m_buffer_ids[ib], alFormat, uncompressed_wave_data, num_bytes_read, m_fileProps.sample_rate), { fRtn = false; goto ErrorExit; } );
OpenAL_ErrorCheck( alSourceQueueBuffers(m_source_id, 1, &m_buffer_ids[ib]), { fRtn = false; goto ErrorExit; } );
OpenAL_ErrorCheck( alBufferData(buffer_id, alFormat, uncompressed_wave_data, num_bytes_read, m_fileProps.sample_rate), { fRtn = false; goto ErrorExit; } );
OpenAL_ErrorCheck( alSourceQueueBuffers(m_source_id, 1, &buffer_id), { fRtn = false; goto ErrorExit; } );

*num_bytes_written += num_bytes_read;
}
Expand Down Expand Up @@ -511,7 +511,7 @@ uint AudioStream::GetMaxWriteSize (void)

OpenAL_ErrorCheck( alGetSourcei(m_source_id, AL_BUFFERS_QUEUED, &q), return 0 );

if (!n && (q >= MAX_STREAM_BUFFERS)) //all buffers queued
if (!n && (q >= sz2i(MAX_STREAM_BUFFERS))) //all buffers queued
dwMaxSize = 0;

// nprintf(("Alan","Max write size: %d\n", dwMaxSize));
Expand Down Expand Up @@ -600,6 +600,20 @@ bool AudioStream::ServiceBuffer (void)
m_bPastLimit = true;
}

// Recover from buffer underrun: if the source stopped because the queue drained
// between service ticks, OpenAL will not auto-resume even after WriteWaveData
// queues more buffers. We have to call alSourcePlay again ourselves.
ALint state = AL_PLAYING;
OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_SOURCE_STATE, &state) );
if (state == AL_STOPPED && m_fPlaying && !m_bReadingDone) {
ALint queued = 0;
OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_QUEUED, &queued) );
if (queued > 0) {
nprintf(("Sound", "SOUND => Audiostream underrun, restarting playback\n"));
OpenAL_ErrorPrint( alSourcePlay(m_source_id) );
}
}

if ( PlaybackDone() ) {
if ( m_bDestroy_when_faded == true ) {
SDL_UnlockMutex( write_lock );
Expand Down
Loading