From 83529593ed302ce54343229cc11f6f7c0525f122 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Tue, 10 Sep 2024 18:19:53 -0400 Subject: [PATCH] Implement audio_read_samples() --- api/syscalls.json | 20 ++++++++++++++++++++ doc/syscalls.md | 8 ++++++++ ncc/include/uvm/syscalls.h | 4 ++++ vm/src/audio.rs | 23 +++++++++++++++++++++++ vm/src/constants.rs | 3 ++- vm/src/host.rs | 2 ++ 6 files changed, 59 insertions(+), 1 deletion(-) diff --git a/api/syscalls.json b/api/syscalls.json index cb88b01..7e02222 100644 --- a/api/syscalls.json +++ b/api/syscalls.json @@ -766,6 +766,26 @@ "permission": "audio_input", "const_idx": 12, "description": "Open an audio input device, then spawn a new thread which will regularly call the specified callback function to process audio samples." + }, + { + "name": "audio_read_samples", + "args": [ + [ + "i16*", + "dst_buf" + ], + [ + "u32", + "num_samples" + ] + ], + "returns": [ + "void", + "" + ], + "permission": "audio_input", + "const_idx": 13, + "description": "Read available input samples. Must be called from the audio input thread." } ], "constants": [ diff --git a/doc/syscalls.md b/doc/syscalls.md index 9113bbe..cf5367d 100644 --- a/doc/syscalls.md +++ b/doc/syscalls.md @@ -312,6 +312,14 @@ u32 audio_open_input(u32 sample_rate, u16 num_channels, u16 format, void* callba Open an audio input device, then spawn a new thread which will regularly call the specified callback function to process audio samples. +## audio_read_samples + +``` +void audio_read_samples(i16* dst_buf, u32 num_samples) +``` + +Read available input samples. Must be called from the audio input thread. + ## Constants These are the constants associated with the audio subsystem: diff --git a/ncc/include/uvm/syscalls.h b/ncc/include/uvm/syscalls.h index 115355c..5b9c683 100644 --- a/ncc/include/uvm/syscalls.h +++ b/ncc/include/uvm/syscalls.h @@ -101,6 +101,10 @@ // Open an audio input device, then spawn a new thread which will regularly call the specified callback function to process audio samples. #define audio_open_input(__sample_rate, __num_channels, __format, __callback) asm (__sample_rate, __num_channels, __format, __callback) -> u32 { syscall audio_open_input; } +// void audio_read_samples(i16* dst_buf, u32 num_samples) +// Read available input samples. Must be called from the audio input thread. +#define audio_read_samples(__dst_buf, __num_samples) asm (__dst_buf, __num_samples) -> void { syscall audio_read_samples; } + // u64 net_listen(const char* listen_addr, void* on_new_conn) // Open a listening TCP socket to accept incoming connections. A callback function is called when a new connection request is received. #define net_listen(__listen_addr, __on_new_conn) asm (__listen_addr, __on_new_conn) -> u64 { syscall net_listen; } diff --git a/vm/src/audio.rs b/vm/src/audio.rs index 84e0372..e7c8b04 100644 --- a/vm/src/audio.rs +++ b/vm/src/audio.rs @@ -240,3 +240,26 @@ pub fn audio_open_input(thread: &mut Thread, sample_rate: Value, num_channels: V // FIXME: return the device_id (u32) Value::from(1) } + +/// Read audio samples from an audio input thread +pub fn audio_read_samples(thread: &mut Thread, dst_ptr: Value, num_samples: Value) +{ + let dst_ptr = dst_ptr.as_usize(); + let num_samples = num_samples.as_usize(); + + INPUT_STATE.with_borrow_mut(|s| { + if s.input_tid != thread.id { + panic!("can only read audio samples from audio input thread"); + } + + // For now, force reading all available samples + if num_samples != s.samples.len() { + panic!("must read all available samples"); + } + + let dst_buf: &mut [i16] = thread.get_heap_slice_mut(dst_ptr, num_samples); + dst_buf.copy_from_slice(&s.samples); + + s.samples.clear(); + }); +} diff --git a/vm/src/constants.rs b/vm/src/constants.rs index 9559e73..18cf369 100644 --- a/vm/src/constants.rs +++ b/vm/src/constants.rs @@ -19,6 +19,7 @@ pub const WINDOW_POLL_EVENT: u16 = 9; pub const WINDOW_DRAW_FRAME: u16 = 10; pub const EXIT: u16 = 11; pub const AUDIO_OPEN_INPUT: u16 = 12; +pub const AUDIO_READ_SAMPLES: u16 = 13; pub const VM_HEAP_SIZE: u16 = 14; pub const MEMSET32: u16 = 16; pub const VM_GROW_HEAP: u16 = 17; @@ -58,7 +59,7 @@ pub const SYSCALL_DESCS: [Option; SYSCALL_TBL_LEN] = [ Some(SysCallDesc { name: "window_draw_frame", const_idx: 10, argc: 2, has_ret: false }), Some(SysCallDesc { name: "exit", const_idx: 11, argc: 1, has_ret: false }), Some(SysCallDesc { name: "audio_open_input", const_idx: 12, argc: 4, has_ret: true }), - None, + Some(SysCallDesc { name: "audio_read_samples", const_idx: 13, argc: 2, has_ret: false }), Some(SysCallDesc { name: "vm_heap_size", const_idx: 14, argc: 0, has_ret: true }), None, Some(SysCallDesc { name: "memset32", const_idx: 16, argc: 3, has_ret: false }), diff --git a/vm/src/host.rs b/vm/src/host.rs index fb92314..1513e84 100644 --- a/vm/src/host.rs +++ b/vm/src/host.rs @@ -120,6 +120,8 @@ pub fn get_syscall(const_idx: u16) -> HostFn WINDOW_WAIT_EVENT => HostFn::Fn1_0(window_wait_event), AUDIO_OPEN_OUTPUT => HostFn::Fn4_1(audio_open_output), + AUDIO_OPEN_INPUT => HostFn::Fn4_1(audio_open_input), + AUDIO_READ_SAMPLES => HostFn::Fn2_0(audio_read_samples), _ => panic!("unknown syscall \"{}\"", const_idx), }