code wiki / (root) / nx_audio_capture.nx

nx_audio_capture.nx source

↩ module page · 132 lines · 4555 B

1// nx_audio_capture.nx -- abstract audio-capture backend + null impl. 2// 3// Capture backends provide PCM samples to nx_audio_session. Same 4// OOP pattern as nx_codec: typed-fn-ptr vtable in struct, concrete 5// backends embed this struct and wire their own impls. 6// 7// Shipping backends (today): 8// nx_audio_capture_null -- always returns 0 bytes (CI / headless) 9// nx_audio_capture_synth -- sine wave (test fixture, FUTURE file) 10// 11// Queued backends: 12// nx_audio_capture_alsa -- Linux ALSA (Synology / RPi deployment) 13// nx_audio_capture_webaudio -- wasm bridge to browser AudioContext 14// nx_audio_capture_coreaudio -- macOS 15 16// nx_safety_envelope: 17// intended_use: reusable audio capture abstraction 18// sil_target: SIL2 19// evidence: composes nx_fn_ptr_typed (compiler-enforced arity) 20// verdict: NOT_YET_EVALUATED 21 22import "nx_syscalls_x86_64.nx" 23 24// ---- Sealed enum: backend kind ---- 25 26const NX_AUDIO_CAPTURE_KIND_UNKNOWN: i64 = 0 27const NX_AUDIO_CAPTURE_KIND_NULL: i64 = 1 28const NX_AUDIO_CAPTURE_KIND_SYNTH: i64 = 2 29const NX_AUDIO_CAPTURE_KIND_ALSA: i64 = 3 30const NX_AUDIO_CAPTURE_KIND_WEBAUDIO: i64 = 4 31const NX_AUDIO_CAPTURE_KIND_COREAUDIO: i64 = 5 32const NX_AUDIO_CAPTURE_KIND_N: i64 = 6 33 34// ---- Sealed error codes ---- 35 36const NX_AUDIO_CAPTURE_ERR_NOT_OPEN: i64 = -1 37const NX_AUDIO_CAPTURE_ERR_BAD_SIZE: i64 = -2 38const NX_AUDIO_CAPTURE_ERR_BACKEND: i64 = -3 39const NX_AUDIO_CAPTURE_ERR_CLOSED: i64 = -4 40 41// ---- The struct ---- 42 43struct nx_audio_capture { 44 kind: i64, // NX_AUDIO_CAPTURE_KIND_* 45 sample_rate: i64, 46 channels: i64, 47 state: i64, // 0 = closed, 1 = open 48 private: i64, // backend-specific pointer (cast in impl) 49 50 // -- vtable -- 51 open_fn: func(*nx_audio_capture) -> i64, 52 close_fn: func(*nx_audio_capture) -> i64, 53 pull_frame_fn: func(*nx_audio_capture, *u8, i64) -> i64, // (dst, dst_cap) -> bytes or err 54} 55 56const NX_AUDIO_CAPTURE_BYTES: i64 = 64 57 58// ---- Generic accessors ---- 59 60func nx_audio_capture_kind(c: *nx_audio_capture) -> i64 { return c.kind } 61func nx_audio_capture_sample_rate(c: *nx_audio_capture) -> i64 { return c.sample_rate } 62func nx_audio_capture_channels(c: *nx_audio_capture) -> i64 { return c.channels } 63func nx_audio_capture_is_open(c: *nx_audio_capture) -> i64 { return c.state } 64 65// ---- Virtual call sites ---- 66 67func nx_audio_capture_open(c: *nx_audio_capture) -> i64 { 68 return c.open_fn(c) 69} 70 71func nx_audio_capture_close(c: *nx_audio_capture) -> i64 { 72 return c.close_fn(c) 73} 74 75func nx_audio_capture_pull_frame(c: *nx_audio_capture, 76 dst: *u8, dst_cap: i64) -> i64 { 77 if c.state == 0 { return NX_AUDIO_CAPTURE_ERR_NOT_OPEN } 78 if dst_cap <= 0 { return NX_AUDIO_CAPTURE_ERR_BAD_SIZE } 79 return c.pull_frame_fn(c, dst, dst_cap) 80} 81 82// ---- Default vtable impls ---- 83 84func nx_audio_capture_default_open(c: *nx_audio_capture) -> i64 { 85 c.state = 1 86 return 0 87} 88 89func nx_audio_capture_default_close(c: *nx_audio_capture) -> i64 { 90 c.state = 0 91 return 0 92} 93 94func nx_audio_capture_default_pull_frame(c: *nx_audio_capture, 95 dst: *u8, dst_cap: i64) -> i64 { 96 return 0 97} 98 99// ---- Base initializer ---- 100 101func nx_audio_capture_init(c: *nx_audio_capture, 102 kind: i64, sample_rate: i64, channels: i64) -> i64 { 103 c.kind = kind 104 c.sample_rate = sample_rate 105 c.channels = channels 106 c.state = 0 107 c.private = 0 108 c.open_fn = nx_audio_capture_default_open 109 c.close_fn = nx_audio_capture_default_close 110 c.pull_frame_fn = nx_audio_capture_default_pull_frame 111 return 0 112} 113 114// =================================================================== 115// nx_audio_capture_null -- always-zero-bytes backend 116// =================================================================== 117// 118// Useful for CI runs (no real audio device), default-attached 119// playback in nx_cli_meet-from-sshd, and as a smoke fixture. 120 121func nx_audio_capture_null_pull_frame(c: *nx_audio_capture, 122 dst: *u8, dst_cap: i64) -> i64 { 123 return 0 124} 125 126func nx_audio_capture_null_new(c: *nx_audio_capture, 127 sample_rate: i64, channels: i64) -> i64 { 128 nx_audio_capture_init(c, NX_AUDIO_CAPTURE_KIND_NULL, sample_rate, channels) 129 // Defaults already null-shaped; explicit re-wire for clarity. 130 c.pull_frame_fn = nx_audio_capture_null_pull_frame 131 return 0 132}