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.

This commit is contained in:
Toby Jaffey 2025-12-15 10:48:10 +00:00
parent 4e61e3bd4a
commit 09985655a2
4 changed files with 16 additions and 8 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -13,4 +13,5 @@
#define UVM32_SYSCALL_RENDER 0x00000008
#define UVM32_SYSCALL_GETKEY 0x00000009
#define UVM32_SYSCALL_RENDERAUDIO 0x0000000A
#define UVM32_SYSCALL_CANRENDERAUDIO 0x0000000B

View file

@ -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<buf.len/2;i++) {
audio_enq(samples[i]);
}
} break;
case UVM32_SYSCALL_RENDER: {
uvm32_slice_t buf = uvm32_arg_getslice(vmst, &evt, ARG0, ARG1);