Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ogg edge cases #55846

Merged
merged 1 commit into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion modules/minimp3/audio_stream_mp3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
#include "core/io/file_access.h"

int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!active, 0);
if (!active) {
return 0;
}

int todo = p_frames;

Expand Down
17 changes: 7 additions & 10 deletions modules/vorbis/audio_stream_ogg_vorbis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,22 @@

int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!ready, 0);
ERR_FAIL_COND_V(!active, 0);

if (!active) {
return 0;
}

int todo = p_frames;

int start_buffer = 0;

int frames_mixed_this_step = p_frames;

while (todo && active) {
while (todo > 0 && active) {
AudioFrame *buffer = p_buffer;
if (start_buffer > 0) {
buffer = buffer + start_buffer;
}
int mixed = _mix_frames_vorbis(buffer, todo);
if (mixed < 0) {
return 0;
}
ERR_FAIL_COND_V(mixed < 0, 0);
todo -= mixed;
frames_mixed += mixed;
start_buffer += mixed;
Expand All @@ -67,16 +66,14 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
// we still have buffer to fill, start from this element in the next iteration.
start_buffer = p_frames - todo;
} else {
frames_mixed_this_step = p_frames - todo;
for (int i = p_frames - todo; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0, 0);
}
active = false;
todo = 0;
}
}
}
return frames_mixed_this_step;
return p_frames - todo;
}

int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) {
Expand Down
29 changes: 13 additions & 16 deletions servers/audio/audio_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,

uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale * playback_speed_scale) / double(target_rate)) * double(FP_LEN));

int mixed_frames_total = p_frames;
int mixed_frames_total = -1;

for (int i = 0; i < p_frames; i++) {
int i;
for (i = 0; i < p_frames; i++) {
uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
//standard cubic interpolation (great quality/performance ratio)
//this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory.
Expand All @@ -147,7 +148,7 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
AudioFrame y2 = internal_buffer[idx - 1];
AudioFrame y3 = internal_buffer[idx - 0];

if (idx <= internal_buffer_end && idx >= internal_buffer_end && mixed_frames_total == p_frames) {
if (idx >= internal_buffer_end && mixed_frames_total == -1) {
// The internal buffer ends somewhere in this range, and we haven't yet recorded the number of good frames we have.
mixed_frames_total = i;
}
Expand All @@ -167,24 +168,20 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
internal_buffer[1] = internal_buffer[INTERNAL_BUFFER_LEN + 1];
internal_buffer[2] = internal_buffer[INTERNAL_BUFFER_LEN + 2];
internal_buffer[3] = internal_buffer[INTERNAL_BUFFER_LEN + 3];
if (is_playing()) {
int mixed_frames = _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
if (mixed_frames != INTERNAL_BUFFER_LEN) {
// internal_buffer[mixed_frames] is the first frame of silence.
internal_buffer_end = mixed_frames;
} else {
// The internal buffer does not contain the first frame of silence.
internal_buffer_end = -1;
}
int mixed_frames = _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
if (mixed_frames != INTERNAL_BUFFER_LEN) {
// internal_buffer[mixed_frames] is the first frame of silence.
internal_buffer_end = mixed_frames;
} else {
//fill with silence, not playing
for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) {
internal_buffer[j + 4] = AudioFrame(0, 0);
}
// The internal buffer does not contain the first frame of silence.
internal_buffer_end = -1;
}
mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS);
}
}
if (mixed_frames_total == -1 && i == p_frames) {
mixed_frames_total = p_frames;
}
return mixed_frames_total;
}

Expand Down