1
0
Fork 0

Use permanent audio buffer

As a side effect, fixes crackling sound when the audio buffer isn't big enough to hold a full Vorbis packet. Not related
to the buffer being permanent but a bug in the previous code. It would happen when the video had 6 channel audio tracks.
This commit is contained in:
Bernat Arlandis 2025-02-10 11:27:34 +01:00
parent 06f865452f
commit ca8664b4b6
2 changed files with 35 additions and 10 deletions

View File

@ -504,28 +504,32 @@ void VideoStreamPlaybackTheora::update(double p_delta) {
ogg_packet op;
while (!audio_ready && !audio_done) {
// Send remaining frames
if (!send_audio()) {
audio_ready = true;
break;
}
float **pcm;
int ret = vorbis_synthesis_pcmout(&vd, &pcm);
if (ret > 0) {
const int AUXBUF_LEN = 4096;
int to_read = ret;
float aux_buffer[AUXBUF_LEN];
while (to_read) {
int m = MIN(AUXBUF_LEN / vi.channels, to_read);
int frames_read = 0;
while (frames_read < ret) {
int m = MIN(AUXBUF_LEN / vi.channels, ret - frames_read);
int count = 0;
for (int j = 0; j < m; j++) {
for (int i = 0; i < vi.channels; i++) {
aux_buffer[count++] = pcm[i][j];
audio_buffer[count++] = pcm[i][frames_read + j];
}
}
int mixed = mix_callback(mix_udata, aux_buffer, m);
to_read -= mixed;
if (mixed != m) { //could mix no more
frames_read += m;
audio_ptr_end = m;
if (!send_audio()) {
audio_ready = true;
break;
}
}
vorbis_synthesis_read(&vd, ret - to_read);
vorbis_synthesis_read(&vd, frames_read);
} else {
/* no pending audio; is there a pending packet to decode? */
if (ogg_stream_packetout(&vo, &op) > 0) {
@ -649,6 +653,8 @@ void VideoStreamPlaybackTheora::seek(double p_time) {
audio_done = !has_audio;
theora_eos = false;
vorbis_eos = false;
audio_ptr_start = 0;
audio_ptr_end = 0;
ogg_stream_reset(&to);
if (has_audio) {

View File

@ -52,6 +52,11 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
Point2i size;
Rect2i region;
const static int AUXBUF_LEN = 4096;
float audio_buffer[AUXBUF_LEN];
int audio_ptr_start;
int audio_ptr_end;
int buffer_data();
int queue_page(ogg_page *page);
int read_page(ogg_page *page);
@ -108,6 +113,20 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
protected:
void clear();
_FORCE_INLINE_ bool send_audio() {
if (audio_ptr_end > 0) {
int mixed = mix_callback(mix_udata, &audio_buffer[audio_ptr_start * vi.channels], audio_ptr_end - audio_ptr_start);
audio_ptr_start += mixed;
if (audio_ptr_start == audio_ptr_end) {
audio_ptr_start = 0;
audio_ptr_end = 0;
} else {
return false;
}
}
return true;
}
public:
virtual void play() override;
virtual void stop() override;