From 790b35d9504e23d9ff7ec9c7de067e832dc7364b Mon Sep 17 00:00:00 2001
From: "Daniel K. O. (dkosmari)" <[EMAIL REDACTED]>
Date: Mon, 19 Jan 2026 22:13:21 -0300
Subject: [PATCH] Remap and don't discard buffers also on music_ogg_stb
backend.
---
src/codecs/music_ogg.c | 7 +-
src/codecs/music_ogg_stb.c | 60 +++++++++--------
src/codecs/music_opus.c | 7 +-
src/codecs/remap_channels.c | 124 ++++++++++++++++++++++++++++++++----
src/codecs/remap_channels.h | 4 +-
5 files changed, 160 insertions(+), 42 deletions(-)
diff --git a/src/codecs/music_ogg.c b/src/codecs/music_ogg.c
index 0338ac8cb..a15801628 100644
--- a/src/codecs/music_ogg.c
+++ b/src/codecs/music_ogg.c
@@ -222,8 +222,9 @@ static int OGG_UpdateSection(OGG_music *music)
return -1;
}
- /* Note: never shrink the buffer, we just decoded data in there. */
new_buffer_size = music_spec.samples * (int)sizeof(Sint16) * vi->channels;
+
+ /* Note: never shrink the buffer, we just decoded data in there. */
if (new_buffer_size > music->buffer_size) {
char *new_buffer = (char *)SDL_realloc(music->buffer, new_buffer_size);
if (!new_buffer) {
@@ -408,7 +409,9 @@ static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
}
}
- remap_channels_vorbis((Sint16 *)music->buffer, amount / (int)sizeof(Sint16), music->vi.channels);
+ remap_channels_vorbis_s16((Sint16 *)music->buffer,
+ amount / (int)sizeof(Sint16),
+ music->vi.channels);
pcmPos = vorbis.ov_pcm_tell(&music->vf);
if (music->loop && (music->play_count != 1) && (pcmPos >= music->loop_end)) {
diff --git a/src/codecs/music_ogg_stb.c b/src/codecs/music_ogg_stb.c
index f9b36d46a..c3e7386ec 100644
--- a/src/codecs/music_ogg_stb.c
+++ b/src/codecs/music_ogg_stb.c
@@ -24,6 +24,7 @@
/* This file supports Ogg Vorbis music streams using a modified stb_vorbis module */
#include "music_ogg.h"
+#include "remap_channels.h"
#include "utils.h"
#include "SDL_assert.h"
@@ -74,7 +75,6 @@ typedef struct {
int volume;
stb_vorbis *vf;
stb_vorbis_info vi;
- int section;
SDL_AudioStream *stream;
char *buffer;
int buffer_size;
@@ -123,18 +123,15 @@ static void OGG_Delete(void *context);
static int OGG_UpdateSection(OGG_music *music)
{
stb_vorbis_info vi;
+ int new_buffer_size;
vi = stb_vorbis_get_info(music->vf);
if (vi.channels == music->vi.channels && vi.sample_rate == music->vi.sample_rate) {
return 0;
}
- SDL_memcpy(&music->vi, &vi, sizeof(vi));
- if (music->buffer) {
- SDL_free(music->buffer);
- music->buffer = NULL;
- }
+ music->vi = vi;
if (music->stream) {
SDL_FreeAudioStream(music->stream);
@@ -144,17 +141,30 @@ static int OGG_UpdateSection(OGG_music *music)
music->stream = SDL_NewAudioStream(AUDIO_F32SYS, (Uint8)vi.channels, (int)vi.sample_rate,
music_spec.format, music_spec.channels, music_spec.freq);
if (!music->stream) {
+ SDL_free(music->buffer);
+ music->buffer = NULL;
+ music->buffer_size = 0;
return -1;
}
- music->buffer_size = music_spec.samples * (int)sizeof(float) * vi.channels;
- if (music->buffer_size <= 0) {
+ new_buffer_size = music_spec.samples * (int)sizeof(float) * vi.channels;
+ if (new_buffer_size <= 0) {
+ music->buffer = NULL;
+ music->buffer_size = 0;
return -1;
}
- music->buffer = (char *)SDL_malloc((size_t)music->buffer_size);
- if (!music->buffer) {
- return -1;
+ /* Note: never shrink the buffer, we just decoded data in there. */
+ if (new_buffer_size > music->buffer_size) {
+ char *new_buffer = (char *)SDL_realloc(music->buffer, new_buffer_size);
+ if (!new_buffer) {
+ SDL_free(music->buffer);
+ music->buffer = NULL;
+ music->buffer_size = 0;
+ return -1;
+ }
+ music->buffer = new_buffer;
+ music->buffer_size = new_buffer_size;
}
return 0;
}
@@ -175,7 +185,6 @@ static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
}
music->src = src;
music->volume = MIX_MAX_VOLUME;
- music->section = -1;
music->vf = stb_vorbis_open_rwops(src, 0, &error, NULL);
@@ -308,8 +317,7 @@ static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
{
OGG_music *music = (OGG_music *)context;
SDL_bool looped = SDL_FALSE;
- int filled, amount, result;
- int section;
+ int filled, amount, samples, result;
Sint64 pcmPos;
filled = SDL_AudioStreamGet(music->stream, data, bytes);
@@ -323,21 +331,21 @@ static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
return 0;
}
- section = music->section;
- amount = stb_vorbis_get_samples_float_interleaved(music->vf,
- music->vi.channels,
- (float *)music->buffer,
- music_spec.samples * music->vi.channels);
+ samples = stb_vorbis_get_samples_float_interleaved(music->vf,
+ music->vi.channels,
+ (float *)music->buffer,
+ music->buffer_size / (int)sizeof(float));
- amount *= music->vi.channels * sizeof(float);
-
- if (section != music->section) {
- music->section = section;
- if (OGG_UpdateSection(music) < 0) {
- return -1;
- }
+ if (OGG_UpdateSection(music) < 0) {
+ return -1;
}
+ amount = samples * music->vi.channels * sizeof(float);
+
+ remap_channels_vorbis_flt((float *)music->buffer,
+ samples * music->vi.channels,
+ music->vi.channels);
+
pcmPos = stb_vorbis_get_playback_sample_offset(music->vf);
if (music->loop && (music->play_count != 1) && (pcmPos >= music->loop_end)) {
amount -= (int)((pcmPos - music->loop_end) * music->vi.channels) * (int)sizeof(float);
diff --git a/src/codecs/music_opus.c b/src/codecs/music_opus.c
index 648d50cb6..4ddae9f14 100644
--- a/src/codecs/music_opus.c
+++ b/src/codecs/music_opus.c
@@ -196,8 +196,9 @@ static int OPUS_UpdateSection(OPUS_music *music)
return -1;
}
- /* Note: never shrink the buffer, we just decoded data in there. */
new_buffer_size = (int)music_spec.samples * (int)sizeof(opus_int16) * op_info->channel_count;
+
+ /* Note: never shrink the buffer, we just decoded data in there. */
if (new_buffer_size > music->buffer_size) {
char *new_buffer = (char *)SDL_realloc(music->buffer, (size_t)new_buffer_size);
if (!new_buffer) {
@@ -387,7 +388,9 @@ static int OPUS_GetSome(void *context, void *data, int bytes, SDL_bool *done)
}
if (music->op_info->mapping_family == 1) {
- remap_channels_vorbis((Sint16 *)music->buffer, samples * music->op_info->channel_count, music->op_info->channel_count);
+ remap_channels_vorbis_s16((Sint16 *)music->buffer,
+ samples * music->op_info->channel_count,
+ music->op_info->channel_count);
}
pcmPos = opus.op_pcm_tell(music->of);
diff --git a/src/codecs/remap_channels.c b/src/codecs/remap_channels.c
index 552b06c1d..9c057e6dd 100644
--- a/src/codecs/remap_channels.c
+++ b/src/codecs/remap_channels.c
@@ -107,7 +107,7 @@
#include "remap_channels.h"
-static void remap_channels_vorbis_3(Sint16 *samples, int num_samples)
+static void remap_channels_vorbis_3_s16(Sint16 *samples, int num_samples)
{
/* Note: this isn't perfect, because we map FC to LFE */
int i;
@@ -119,7 +119,19 @@ static void remap_channels_vorbis_3(Sint16 *samples, int num_samples)
}
}
-static void remap_channels_vorbis_5(Sint16 *samples, int num_samples)
+static void remap_channels_vorbis_3_flt(float *samples, int num_samples)
+{
+ /* Note: this isn't perfect, because we map FC to LFE */
+ int i;
+ for (i = 0; i < num_samples; i += 3) {
+ float FC = samples[i + 1];
+ float FR = samples[i + 2];
+ samples[i + 1] = FR;
+ samples[i + 2] = FC;
+ }
+}
+
+static void remap_channels_vorbis_5_s16(Sint16 *samples, int num_samples)
{
/* Note: this isn't perfect, because we map FC to LFE. */
int i;
@@ -131,7 +143,19 @@ static void remap_channels_vorbis_5(Sint16 *samples, int num_samples)
}
}
-static void remap_channels_vorbis_5_1(Sint16 *samples, int num_samples)
+static void remap_channels_vorbis_5_flt(float *samples, int num_samples)
+{
+ /* Note: this isn't perfect, because we map FC to LFE. */
+ int i;
+ for (i = 0; i < num_samples; i += 5) {
+ float FC = samples[i + 1];
+ float FR = samples[i + 2];
+ samples[i + 1] = FR;
+ samples[i + 2] = FC;
+ }
+}
+
+static void remap_channels_vorbis_5_1_s16(Sint16 *samples, int num_samples)
{
int i;
for (i = 0; i < num_samples; i += 6) {
@@ -148,7 +172,24 @@ static void remap_channels_vorbis_5_1(Sint16 *samples, int num_samples)
}
}
-static void remap_channels_vorbis_7(Sint16 *samples, int num_samples)
+static void remap_channels_vorbis_5_1_flt(float *samples, int num_samples)
+{
+ int i;
+ for (i = 0; i < num_samples; i += 6) {
+ float FC = samples[i + 1];
+ float FR = samples[i + 2];
+ float RL = samples[i + 3];
+ float RR = samples[i + 4];
+ float LFE = samples[i + 5];
+ samples[i + 1] = FR;
+ samples[i + 2] = FC;
+ samples[i + 3] = LFE;
+ samples[i + 4] = RL;
+ samples[i + 5] = RR;
+ }
+}
+
+static void remap_channels_vorbis_7_s16(Sint16 *samples, int num_samples)
{
int i = 0;
for (i = 0; i < num_samples; i += 7) {
@@ -167,7 +208,26 @@ static void remap_channels_vorbis_7(Sint16 *samples, int num_samples)
}
}
-static void remap_channels_vorbis_7_1(Sint16 *samples, int num_samples)
+static void remap_channels_vorbis_7_flt(float *samples, int num_samples)
+{
+ int i = 0;
+ for (i = 0; i < num_samples; i += 7) {
+ float FC = samples[i + 1];
+ float FR = samples[i + 2];
+ float SL = samples[i + 3];
+ float SR = samples[i + 4];
+ float RC = samples[i + 5];
+ float LFE = samples[i + 6];
+ samples[i + 1] = FR;
+ samples[i + 2] = FC;
+ samples[i + 3] = LFE;
+ samples[i + 4] = RC;
+ samples[i + 5] = SL;
+ samples[i + 6] = SR;
+ }
+}
+
+static void remap_channels_vorbis_7_1_s16(Sint16 *samples, int num_samples)
{
int i = 0;
for (i = 0; i < num_samples; i += 8) {
@@ -188,23 +248,65 @@ static void remap_channels_vorbis_7_1(Sint16 *samples, int num_samples)
}
}
-void remap_channels_vorbis(Sint16 *samples, int num_samples, int num_channels)
+static void remap_channels_vorbis_7_1_flt(float *samples, int num_samples)
+{
+ int i = 0;
+ for (i = 0; i < num_samples; i += 8) {
+ float FC = samples[i + 1];
+ float FR = samples[i + 2];
+ float SL = samples[i + 3];
+ float SR = samples[i + 4];
+ float RL = samples[i + 5];
+ float RR = samples[i + 6];
+ float LFE = samples[i + 7];
+ samples[i + 1] = FR;
+ samples[i + 2] = FC;
+ samples[i + 3] = LFE;
+ samples[i + 4] = RL;
+ samples[i + 5] = RR;
+ samples[i + 6] = SL;
+ samples[i + 7] = SR;
+ }
+}
+
+void remap_channels_vorbis_s16(Sint16 *samples, int num_samples, int num_channels)
+{
+ switch (num_channels) {
+ case 3:
+ remap_channels_vorbis_3_s16(samples, num_samples);
+ break;
+ case 5:
+ remap_channels_vorbis_5_s16(samples, num_samples);
+ break;
+ case 6:
+ remap_channels_vorbis_5_1_s16(samples, num_samples);
+ break;
+ case 7:
+ remap_channels_vorbis_7_s16(samples, num_samples);
+ break;
+ case 8:
+ remap_channels_vorbis_7_1_s16(samples, num_samples);
+ break;
+ }
+}
+
+void remap_channels_vorbis_flt(float *samples, int num_samples, int num_channels)
{
switch (num_channels) {
case 3:
- remap_channels_vorbis_3(samples, num_samples);
+ remap_channels_vorbis_3_flt(samples, num_samples);
break;
case 5:
- remap_channels_vorbis_5(samples, num_samples);
+ remap_channels_vorbis_5_flt(samples, num_samples);
break;
case 6:
- remap_channels_vorbis_5_1(samples, num_samples);
+ remap_channels_vorbis_5_1_flt(samples, num_samples);
break;
case 7:
- remap_channels_vorbis_7(samples, num_samples);
+ remap_channels_vorbis_7_flt(samples, num_samples);
break;
case 8:
- remap_channels_vorbis_7_1(samples, num_samples);
+ remap_channels_vorbis_7_1_flt(samples, num_samples);
break;
}
}
diff --git a/src/codecs/remap_channels.h b/src/codecs/remap_channels.h
index 235364871..3f5d03bb3 100644
--- a/src/codecs/remap_channels.h
+++ b/src/codecs/remap_channels.h
@@ -24,6 +24,8 @@
#include "SDL_types.h"
-extern void remap_channels_vorbis(Sint16 *samples, int num_samples, int num_channels);
+extern void remap_channels_vorbis_s16(Sint16 *samples, int num_samples, int num_channels);
+
+extern void remap_channels_vorbis_flt(float *samples, int num_samples, int num_channels);
#endif /* CHANNEL_REMAP_H_ */