openal: Don't assume alSourceUnqueueBuffers is FIFO

This commit is contained in:
Sam Edwards 2018-03-01 14:55:41 -07:00
parent 89799bc024
commit 1862100bac

View File

@ -446,18 +446,34 @@ pull_used_buffers() {
int err = alGetError(); int err = alGetError();
if (err == AL_NO_ERROR) { if (err == AL_NO_ERROR) {
if (_stream_queued[0]._buffer != buffer) { if (_stream_queued[0]._buffer != buffer) {
audio_error("corruption in stream queue"); // This is certainly atypical: most implementations of OpenAL unqueue
cleanup(); // buffers in FIFO order. However, some (e.g. Apple's) can unqueue
return; // buffers out-of-order if playback is interrupted. So, we don't freak
} // out unless `buffer` isn't in _stream_queued at all.
_stream_queued.pop_front(); bool found_culprit = false;
if (_stream_queued.size()) { for (auto it = _stream_queued.begin(); it != _stream_queued.end(); ++it) {
double al = _stream_queued[0]._time_offset + _stream_queued[0]._loop_index * _length; if (it->_buffer == buffer) {
double rtc = TrueClock::get_global_ptr()->get_short_time(); // Phew. Found it. Just remove that.
correct_calibrated_clock(rtc, al); _stream_queued.erase(it);
} found_culprit = true;
if (buffer != _sd->_sample) { break;
alDeleteBuffers(1,&buffer); }
}
if (!found_culprit) {
audio_error("corruption in stream queue");
cleanup();
return;
}
} else {
_stream_queued.pop_front();
if (_stream_queued.size()) {
double al = _stream_queued[0]._time_offset + _stream_queued[0]._loop_index * _length;
double rtc = TrueClock::get_global_ptr()->get_short_time();
correct_calibrated_clock(rtc, al);
}
if (buffer != _sd->_sample) {
alDeleteBuffers(1,&buffer);
}
} }
} else { } else {
break; break;