From 09985655a21450d1798eef5d5b52a4aa6be0913d Mon Sep 17 00:00:00 2001 From: Toby Jaffey Date: Mon, 15 Dec 2025 10:48:10 +0000 Subject: [PATCH] Fix host-sdl/doom audio. Have app ask via syscall if audio can be rendered before sending, else any mismatch in rates will cause queue over/underflow in host-sdl. --- apps/zigdoom/src/main.zig | 6 ++++-- apps/zigdoom/src/uvm.zig | 4 ++++ common/uvm32_common_custom.h | 1 + hosts/host-sdl/host-sdl.c | 13 +++++++------ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/zigdoom/src/main.zig b/apps/zigdoom/src/main.zig index 5d59e3f..3cabdda 100644 --- a/apps/zigdoom/src/main.zig +++ b/apps/zigdoom/src/main.zig @@ -198,8 +198,10 @@ fn submain() !void { while(true) { pd.doom_update(); - const doomSndBuf: [*]i16 = pd.doom_get_sound_buffer(); - uvm.renderAudio(doomSndBuf, 2048); + if (uvm.canRenderAudio()) { + const doomSndBuf: [*]i16 = pd.doom_get_sound_buffer(); + uvm.renderAudio(doomSndBuf, 2048); + } const fb: [*]const u8 = pd.doom_get_framebuffer(4); uvm.render(fb, WIDTH * HEIGHT * 4); diff --git a/apps/zigdoom/src/uvm.zig b/apps/zigdoom/src/uvm.zig index 250f8f7..5eedcda 100644 --- a/apps/zigdoom/src/uvm.zig +++ b/apps/zigdoom/src/uvm.zig @@ -24,6 +24,10 @@ pub inline fn syscall(id: u32, param1: u32, param2: u32) u32 { return val; } +pub inline fn canRenderAudio() bool { + return syscall(uvm32.UVM32_SYSCALL_CANRENDERAUDIO, 0, 0) != 0; +} + pub inline fn renderAudio(audbuf: [*]const i16, len:u32) void { _ = syscall(uvm32.UVM32_SYSCALL_RENDERAUDIO, @intFromPtr(audbuf), len); } diff --git a/common/uvm32_common_custom.h b/common/uvm32_common_custom.h index 0d74097..6d06b52 100644 --- a/common/uvm32_common_custom.h +++ b/common/uvm32_common_custom.h @@ -13,4 +13,5 @@ #define UVM32_SYSCALL_RENDER 0x00000008 #define UVM32_SYSCALL_GETKEY 0x00000009 #define UVM32_SYSCALL_RENDERAUDIO 0x0000000A +#define UVM32_SYSCALL_CANRENDERAUDIO 0x0000000B diff --git a/hosts/host-sdl/host-sdl.c b/hosts/host-sdl/host-sdl.c index f640521..a305863 100644 --- a/hosts/host-sdl/host-sdl.c +++ b/hosts/host-sdl/host-sdl.c @@ -34,7 +34,7 @@ static int keyBufferWr = 0; static int keyBufferRd = 0; // circular buffer of audio samples, so vm code can read them as it's ready -#define AUDIOBUFFER_LEN 4096 +#define AUDIOBUFFER_LEN (2048*10) static int16_t audioBuffer[AUDIOBUFFER_LEN]; static int audioBufferWr = 0; static int audioBufferRd = 0; @@ -134,7 +134,7 @@ void audiocb(void *userdata, SDL_AudioStream *stream, int additional_amount, int return; } - while(total_amount > 0) { + while(additional_amount > 0) { int16_t sample[2]; // always expect audio in pairs @@ -147,7 +147,7 @@ void audiocb(void *userdata, SDL_AudioStream *stream, int additional_amount, int } else { return; } - total_amount -= 4; + additional_amount -= 4; } } @@ -251,7 +251,7 @@ int main(int argc, char *argv[]) { SDL_AudioSpec srcspec = { .format = SDL_AUDIO_S16, .channels = 2, - .freq = 44100, + .freq = 11025, }; SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &srcspec, audiocb, NULL); @@ -339,14 +339,15 @@ int main(int argc, char *argv[]) { case UVM32_SYSCALL_GETC: { uvm32_arg_setval(vmst, &evt, RET, 0xFFFFFFFF); } break; + case UVM32_SYSCALL_CANRENDERAUDIO: + uvm32_arg_setval(vmst, &evt, RET, audioBufferWr == audioBufferRd); // queue is empty + break; case UVM32_SYSCALL_RENDERAUDIO: { uvm32_slice_t buf = uvm32_arg_getslice(vmst, &evt, ARG0, ARG1); - printf("Got audio buf len=%d\n", buf.len); int16_t *samples = (int16_t *)buf.ptr; for (int i=0;i