fix: stream stops and dies on underflow

This commit is contained in:
MihailRis 2025-10-30 19:56:07 +03:00
parent ab7bf9c709
commit cf561e78a8
6 changed files with 60 additions and 27 deletions

View file

@ -164,9 +164,10 @@ std::unique_ptr<Speaker> ALStream::createSpeaker(bool loop, int channel) {
for (uint i = 0; i < ALStream::STREAM_BUFFERS; i++) {
uint free_buffer = al->getFreeBuffer();
if (!preloadBuffer(free_buffer, loop)) {
break;
unusedBuffers.push(free_buffer);
} else {
AL_CHECK(alSourceQueueBuffers(free_source, 1, &free_buffer));
}
AL_CHECK(alSourceQueueBuffers(free_source, 1, &free_buffer));
}
return std::make_unique<ALSpeaker>(al, free_source, PRIORITY_HIGH, channel);
}
@ -213,11 +214,11 @@ void ALStream::unqueueBuffers(uint alsource) {
uint ALStream::enqueueBuffers(uint alsource) {
uint preloaded = 0;
if (!unusedBuffers.empty()) {
uint first_buffer = unusedBuffers.front();
if (preloadBuffer(first_buffer, loop)) {
uint firstBuffer = unusedBuffers.front();
if (preloadBuffer(firstBuffer, loop)) {
preloaded++;
unusedBuffers.pop();
AL_CHECK(alSourceQueueBuffers(alsource, 1, &first_buffer));
AL_CHECK(alSourceQueueBuffers(alsource, 1, &firstBuffer));
}
}
return preloaded;
@ -227,14 +228,14 @@ void ALStream::update(double delta) {
if (this->speaker == 0) {
return;
}
auto p_speaker = audio::get_speaker(this->speaker);
if (p_speaker == nullptr) {
auto speaker = audio::get_speaker(this->speaker);
if (speaker == nullptr) {
this->speaker = 0;
return;
}
ALSpeaker* alspeaker = dynamic_cast<ALSpeaker*>(p_speaker);
ALSpeaker* alspeaker = dynamic_cast<ALSpeaker*>(speaker);
assert(alspeaker != nullptr);
if (alspeaker->stopped) {
if (alspeaker->manuallyStopped) {
this->speaker = 0;
return;
}
@ -245,11 +246,11 @@ void ALStream::update(double delta) {
uint preloaded = enqueueBuffers(alsource);
// alspeaker->stopped is assigned to false at ALSpeaker::play(...)
if (p_speaker->isStopped() && !alspeaker->stopped) { //TODO: -V560 false-positive?
if (preloaded || dynamic_cast<MemoryPCMStream*>(source.get())) {
p_speaker->play();
} else {
p_speaker->stop();
if (speaker->isStopped() && !alspeaker->manuallyStopped) { //TODO: -V560 false-positive?
if (preloaded) {
speaker->play();
} else if (isStopOnEnd()){
speaker->stop();
}
}
}
@ -290,6 +291,14 @@ void ALStream::setTime(duration_t time) {
}
}
bool ALStream::isStopOnEnd() const {
return stopOnEnd;
}
void ALStream::setStopOnEnd(bool flag) {
stopOnEnd = flag;
}
ALSpeaker::ALSpeaker(ALAudio* al, uint source, int priority, int channel)
: al(al), priority(priority), channel(channel), source(source) {
}
@ -356,7 +365,7 @@ void ALSpeaker::setLoop(bool loop) {
void ALSpeaker::play() {
paused = false;
stopped = false;
manuallyStopped = false;
auto p_channel = get_channel(this->channel);
AL_CHECK(alSourcef(
source,
@ -372,7 +381,7 @@ void ALSpeaker::pause() {
}
void ALSpeaker::stop() {
stopped = true;
manuallyStopped = true;
if (source) {
AL_CHECK(alSourceStop(source));
@ -436,6 +445,11 @@ int ALSpeaker::getPriority() const {
return priority;
}
bool ALSpeaker::isManuallyStopped() const {
return manuallyStopped;
}
static bool alc_enumeration_ext = false;
ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)