diff --git a/apps/zigdoom/src/main.zig b/apps/zigdoom/src/main.zig index be57d82..5d59e3f 100644 --- a/apps/zigdoom/src/main.zig +++ b/apps/zigdoom/src/main.zig @@ -198,6 +198,9 @@ fn submain() !void { while(true) { pd.doom_update(); + 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 1a1d4e2..250f8f7 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 renderAudio(audbuf: [*]const i16, len:u32) void { + _ = syscall(uvm32.UVM32_SYSCALL_RENDERAUDIO, @intFromPtr(audbuf), len); +} + pub inline fn render(fb: [*]const u8, len:u32) void { _ = syscall(uvm32.UVM32_SYSCALL_RENDER, @intFromPtr(fb), len); } diff --git a/common/uvm32_common_custom.h b/common/uvm32_common_custom.h index 6739938..0d74097 100644 --- a/common/uvm32_common_custom.h +++ b/common/uvm32_common_custom.h @@ -2,14 +2,15 @@ // These are not required when building a custom host target code with uvm32 // syscalls for exposed host functions, start at 0 -#define UVM32_SYSCALL_PUTC 0x00000000 -#define UVM32_SYSCALL_GETC 0x00000001 -#define UVM32_SYSCALL_PRINT 0x00000002 -#define UVM32_SYSCALL_PRINTLN 0x00000003 -#define UVM32_SYSCALL_PRINTDEC 0x00000004 -#define UVM32_SYSCALL_PRINTHEX 0x00000005 -#define UVM32_SYSCALL_MILLIS 0x00000006 -#define UVM32_SYSCALL_PRINTBUF 0x00000007 -#define UVM32_SYSCALL_RENDER 0x00000008 -#define UVM32_SYSCALL_GETKEY 0x00000009 +#define UVM32_SYSCALL_PUTC 0x00000000 +#define UVM32_SYSCALL_GETC 0x00000001 +#define UVM32_SYSCALL_PRINT 0x00000002 +#define UVM32_SYSCALL_PRINTLN 0x00000003 +#define UVM32_SYSCALL_PRINTDEC 0x00000004 +#define UVM32_SYSCALL_PRINTHEX 0x00000005 +#define UVM32_SYSCALL_MILLIS 0x00000006 +#define UVM32_SYSCALL_PRINTBUF 0x00000007 +#define UVM32_SYSCALL_RENDER 0x00000008 +#define UVM32_SYSCALL_GETKEY 0x00000009 +#define UVM32_SYSCALL_RENDERAUDIO 0x0000000A diff --git a/hosts/host-sdl/host-sdl.c b/hosts/host-sdl/host-sdl.c index 1fe7e09..0b1f08d 100644 --- a/hosts/host-sdl/host-sdl.c +++ b/hosts/host-sdl/host-sdl.c @@ -33,6 +33,12 @@ static keyevent_t keyBuffer[KEYBUFFER_LEN]; 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 +static int16_t audioBuffer[AUDIOBUFFER_LEN]; +static int audioBufferWr = 0; +static int audioBufferRd = 0; + void key_enq(uint16_t scancode, bool down) { keyBuffer[keyBufferWr].scancode = scancode; keyBuffer[keyBufferWr].down = down; @@ -50,6 +56,22 @@ bool key_deq(keyevent_t *ke) { } } +void audio_enq(int16_t sample) { + audioBuffer[audioBufferWr] = sample; + audioBufferWr = (audioBufferWr + 1) % AUDIOBUFFER_LEN; +} + +bool audio_deq(int16_t *sample) { + if (audioBufferWr != audioBufferRd) { + *sample = audioBuffer[audioBufferRd]; + audioBufferRd = (audioBufferRd + 1) % AUDIOBUFFER_LEN; + return true; + } else { + return false; + } +} + + static uint8_t *read_file(const char* filename, int *len) { FILE* f = fopen(filename, "rb"); uint8_t *buf = NULL; @@ -107,6 +129,27 @@ void usage(const char *name) { exit(1); } +void audiocb(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) { + if (audioBufferWr == audioBufferRd) { // empty + return; + } + + while(total_amount > 0) { + int16_t sample[2]; + + // always expect audio in pairs + if (audio_deq(&sample[0])) { + if (audio_deq(&sample[1])) { + if (!SDL_PutAudioStreamData(stream, sample, 4)) { + printf("audio write failed\r\n"); + } + } + } else { + return; + } + total_amount -= 4; + } +} int main(int argc, char *argv[]) { @@ -199,6 +242,19 @@ int main(int argc, char *argv[]) { render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT); SDL_SetTextureScaleMode(render_target, SDL_SCALEMODE_NEAREST); + SDL_AudioSpec srcspec = { + .format = SDL_AUDIO_S16, + .channels = 2, + .freq = 44100, + }; + + SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &srcspec, audiocb, NULL); + if (NULL == stream) { + printf("Could not setup audio!\n"); + return 1; + } + SDL_ResumeAudioStreamDevice(stream); + while (isrunning) { SDL_PollEvent(&event); @@ -277,6 +333,15 @@ int main(int argc, char *argv[]) { case UVM32_SYSCALL_GETC: { uvm32_arg_setval(vmst, &evt, RET, 0xFFFFFFFF); } 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