From c7ba0a91bba7939747239846963cd182efd7e0df Mon Sep 17 00:00:00 2001 From: Jordy Nelson Samuel <35645454+jordysamuel@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:19:58 +0800 Subject: [PATCH 1/4] Update api.c --- workspace/all/common/api.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 1e1d179f9..ad4b5038f 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -2275,6 +2275,9 @@ SDL_Color GFX_mapColor(uint32_t c) #ifndef SAMPLES #define SAMPLES 512 // default #endif +#ifndef BUFFER_MULTIPLIER +#define BUFFER_MULTIPLIER 8 // default +#endif #define ms SDL_GetTicks @@ -2343,6 +2346,32 @@ void SND_setQuality(int quality) soundQuality = qualityLevels[quality]; resetSrcState = 1; } + +static int audio_buffer_samples = SAMPLES; +static int audio_buffer_multiplier = BUFFER_MULTIPLIER; + +void SND_setBufferSize(int samples) { + if (samples != audio_buffer_samples) { + audio_buffer_samples = samples; + LOG_info("Audio buffer size set to %d samples\n", samples); + if (snd.initialized) { + SND_resetAudio(snd.sample_rate_in, snd.frame_rate); + } + } +} + +void SND_setBufferMultiplier(int multiplier) { + if (multiplier != audio_buffer_multiplier) { + audio_buffer_multiplier = multiplier; + if (snd.initialized && snd.sample_rate_out > 0) { + snd.frame_count = ((float)snd.sample_rate_out / SCREEN_FPS) * audio_buffer_multiplier; + perf.buffer_size = snd.frame_count; + SND_resizeBuffer(); + SND_pauseAudio(true); + LOG_info("Audio buffer multiplier set to %d, new frame_count: %d\n", multiplier, snd.frame_count); + } + } +} ResampledFrames resample_audio(const SND_Frame *input_frames, int input_frame_count, int input_sample_rate, int output_sample_rate, double ratio) @@ -2796,7 +2825,7 @@ void SND_init(double sample_rate, double frame_rate) spec_in.freq = PLAT_pickSampleRate(sample_rate, MAX_SAMPLE_RATE); spec_in.format = AUDIO_S16; spec_in.channels = 2; - spec_in.samples = SAMPLES; + spec_in.samples = audio_buffer_samples; spec_in.callback = SND_audioCallback; #if defined(USE_SDL2) @@ -2821,7 +2850,7 @@ void SND_init(double sample_rate, double frame_rate) LOG_info("We now have audio device #%d\n", snd.device_id); - snd.frame_count = ((float)spec_out.freq / SCREEN_FPS) * 8; // buffer size based on sample rate out (times 12 samples headroom) + snd.frame_count = ((float)spec_out.freq / SCREEN_FPS) * audio_buffer_multiplier; perf.buffer_size = snd.frame_count; snd.sample_rate_in = sample_rate; snd.sample_rate_out = spec_out.freq; @@ -2832,7 +2861,7 @@ void SND_init(double sample_rate, double frame_rate) // start with audiodevice paused so buffer can fill a little, snd_batchsamples will unpause it SND_pauseAudio(true); - LOG_info("sample rate: %i (req) %i (rec) [samples %i]\n", snd.sample_rate_in, snd.sample_rate_out, SAMPLES); + LOG_info("sample rate: %i (req) %i (rec) [samples %i]\n", snd.sample_rate_in, snd.sample_rate_out, audio_buffer_samples); snd.initialized = 1; } @@ -4388,4 +4417,4 @@ FALLBACK_IMPLEMENTATION void PLAT_bluetoothStreamBegin(int buffersize) {} FALLBACK_IMPLEMENTATION void PLAT_bluetoothStreamEnd() {} FALLBACK_IMPLEMENTATION void PLAT_bluetoothStreamQuit() {} FALLBACK_IMPLEMENTATION int PLAT_bluetoothVolume() { return 100; } -FALLBACK_IMPLEMENTATION void PLAT_bluetoothSetVolume(int vol) {} \ No newline at end of file +FALLBACK_IMPLEMENTATION void PLAT_bluetoothSetVolume(int vol) {} From eec8bfb2f83d0b1d55430c3b19cb89cf41284369 Mon Sep 17 00:00:00 2001 From: Jordy Nelson Samuel <35645454+jordysamuel@users.noreply.github.com> Date: Tue, 3 Mar 2026 05:22:51 +0000 Subject: [PATCH 2/4] add settings --- workspace/all/common/api.h | 2 ++ workspace/all/minarch/minarch.c | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/workspace/all/common/api.h b/workspace/all/common/api.h index 3d5bdf097..e1ac90cda 100644 --- a/workspace/all/common/api.h +++ b/workspace/all/common/api.h @@ -413,6 +413,8 @@ void SND_quit(void); void SND_resetAudio(double sample_rate, double frame_rate); void SND_pauseAudio(bool paused); void SND_setQuality(int quality); +void SND_setBufferSize(int samples); +void SND_setBufferMultiplier(int multiplier); // watch audio device changes typedef enum { diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index 81fc45db0..c9801c1b4 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -2027,6 +2027,14 @@ static char* resample_labels[] = { "Max", NULL }; +static char* buffer_size_labels[] = { + "128", "256", "512", "1024", + NULL +}; +static char* buffer_multiplier_labels[] = { + "4", "6", "8", "10", + NULL +}; static char* rewind_enable_labels[] = { "Off", "On", @@ -2319,6 +2327,8 @@ enum { FE_OPT_REWIND_COMPRESSION, FE_OPT_REWIND_COMPRESSION_ACCEL, FE_OPT_REWIND_AUDIO, + FE_OPT_AUDIO_BUFFER, + FE_OPT_AUDIO_LATENCY, FE_OPT_COUNT, }; @@ -2737,6 +2747,26 @@ static struct Config { .values = onoff_labels, .labels = onoff_labels, }, + [FE_OPT_AUDIO_BUFFER] = { + .key = "minarch__audio_buffer", + .name = "Audio Buffer Size", + .desc = "SDL audio callback size in samples.\nSmaller = lower latency, higher CPU.\n256 recommended for most use.", + .default_value = 1, + .value = 1, + .count = 4, + .values = buffer_size_labels, + .labels = buffer_size_labels, + }, + [FE_OPT_AUDIO_LATENCY] = { + .key = "minarch__audio_latency", + .name = "Audio Buffer Headroom", + .desc = "Multiplier for internal audio buffer.\nSmaller = lower latency but more risk of crackle.\n6 recommended for most use.", + .default_value = 1, + .value = 1, + .count = 4, + .values = buffer_multiplier_labels, + .labels = buffer_multiplier_labels, + }, [FE_OPT_COUNT] = {NULL} } }, @@ -3109,6 +3139,16 @@ static void Config_syncFrontend(char* key, int value) { else if (exactMatch(key,config.frontend.options[FE_OPT_REWIND_COMPRESSION_ACCEL].key)) { i = FE_OPT_REWIND_COMPRESSION_ACCEL; } + else if (exactMatch(key, config.frontend.options[FE_OPT_AUDIO_BUFFER].key)) { + int buf_size = atoi(config.frontend.options[FE_OPT_AUDIO_BUFFER].values[value]); + SND_setBufferSize(buf_size); + i = FE_OPT_AUDIO_BUFFER; + } + else if (exactMatch(key, config.frontend.options[FE_OPT_AUDIO_LATENCY].key)) { + int multiplier = atoi(config.frontend.options[FE_OPT_AUDIO_LATENCY].values[value]); + SND_setBufferMultiplier(multiplier); + i = FE_OPT_AUDIO_LATENCY; + } if (i==-1) return; Option* option = &config.frontend.options[i]; option->value = value; From c72049fa083bcda968066276fb1bba35618a666a Mon Sep 17 00:00:00 2001 From: Jordy Nelson Samuel <35645454+jordysamuel@users.noreply.github.com> Date: Tue, 3 Mar 2026 05:28:15 +0000 Subject: [PATCH 3/4] update wording and defaults --- workspace/all/minarch/minarch.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index c9801c1b4..f0e6192f7 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -2750,9 +2750,9 @@ static struct Config { [FE_OPT_AUDIO_BUFFER] = { .key = "minarch__audio_buffer", .name = "Audio Buffer Size", - .desc = "SDL audio callback size in samples.\nSmaller = lower latency, higher CPU.\n256 recommended for most use.", - .default_value = 1, - .value = 1, + .desc = "Size of audio chunks sent to the device.\nSmaller values lower latency but use more CPU.", + .default_value = 2, + .value = 2, .count = 4, .values = buffer_size_labels, .labels = buffer_size_labels, @@ -2760,9 +2760,9 @@ static struct Config { [FE_OPT_AUDIO_LATENCY] = { .key = "minarch__audio_latency", .name = "Audio Buffer Headroom", - .desc = "Multiplier for internal audio buffer.\nSmaller = lower latency but more risk of crackle.\n6 recommended for most use.", - .default_value = 1, - .value = 1, + .desc = "How much audio is buffered ahead of time.\nSmaller values lower latency but may crackle.", + .default_value = 2, + .value = 2, .count = 4, .values = buffer_multiplier_labels, .labels = buffer_multiplier_labels, From 177e009ffc32facacb5af5944854f2f614a01c28 Mon Sep 17 00:00:00 2001 From: Jordy Nelson Samuel <35645454+jordysamuel@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:50:22 +0800 Subject: [PATCH 4/4] Newline --- workspace/all/common/api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index ad4b5038f..003572f3d 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -2372,6 +2372,7 @@ void SND_setBufferMultiplier(int multiplier) { } } } + ResampledFrames resample_audio(const SND_Frame *input_frames, int input_frame_count, int input_sample_rate, int output_sample_rate, double ratio)