code wiki / (root) / nx_audio_wav.nx

nx_audio_wav.nx source

↩ module page · 76 lines · 2853 B

1// nx_audio_wav.nx -- SOVEREIGN AUDIO ENGINE rung R4: render to a real .wav file. 2// 3// Makes the engine produce a PLAYABLE artifact (the live-testable principle for 4// audio: the file is the proof). WAV/RIFF is a STANDARD format -> sovereign 5// implementation, proven byte-exact vs the spec in the gate (per the non-novel 6// verification doctrine). 16-bit PCM, little-endian, interleaved stereo. Only 7// % and / used (no reliance on bitwise). license_tier: ORIGINAL. 8 9import "nx_syscalls.nx" 10const K_MAGIC_65536: i64 = 65536 11const K_MAGIC_16777216: i64 = 16777216 12 13// little-endian writers (header values are non-negative) 14func wav_put_u32(buf: *u8, off: i64, v: i64) -> i64 { 15 buf[off] = (v % 256) as u8 16 buf[off + 1] = ((v / 256) % 256) as u8 17 buf[off + 2] = ((v / K_MAGIC_65536) % 256) as u8 18 buf[off + 3] = ((v / K_MAGIC_16777216) % 256) as u8 19 return 0 20} 21func wav_put_u16(buf: *u8, off: i64, v: i64) -> i64 { 22 buf[off] = (v % 256) as u8 23 buf[off + 1] = ((v / 256) % 256) as u8 24 return 0 25} 26// signed 16-bit sample (handles negatives by wrapping into 0..65535 first) 27func wav_put_i16(buf: *u8, off: i64, v: i64) -> i64 { 28 let u: i64 = ((v % K_MAGIC_65536) + K_MAGIC_65536) % K_MAGIC_65536 29 buf[off] = (u % 256) as u8 30 buf[off + 1] = ((u / 256) % 256) as u8 31 return 0 32} 33func wav_put_str(buf: *u8, off: i64, s: *u8) -> i64 { 34 var i: i64 = 0 35 while s[i] != (0 as u8) { buf[off + i] = s[i]; i = i + 1 } 36 return i 37} 38 39// render n frames of 16-bit interleaved stereo WAV into out; returns total bytes 40func wav_render_stereo(L: *i64, R: *i64, n: i64, rate: i64, out: *u8) -> i64 { 41 let channels: i64 = 2 42 let bits: i64 = 16 43 let block_align: i64 = channels * (bits / 8) // 4 44 let byte_rate: i64 = rate * block_align 45 let data_size: i64 = n * block_align 46 wav_put_str(out, 0, "RIFF" as *u8) 47 wav_put_u32(out, 4, 36 + data_size) 48 wav_put_str(out, 8, "WAVE" as *u8) 49 wav_put_str(out, 12, "fmt " as *u8) 50 wav_put_u32(out, 16, 16) // fmt chunk size 51 wav_put_u16(out, 20, 1) // PCM 52 wav_put_u16(out, 22, channels) 53 wav_put_u32(out, 24, rate) 54 wav_put_u32(out, 28, byte_rate) 55 wav_put_u16(out, 32, block_align) 56 wav_put_u16(out, 34, bits) 57 wav_put_str(out, 36, "data" as *u8) 58 wav_put_u32(out, 40, data_size) 59 var off: i64 = 44 60 var i: i64 = 0 61 while i < n { 62 wav_put_i16(out, off, L[i]); off = off + 2 63 wav_put_i16(out, off, R[i]); off = off + 2 64 i = i + 1 65 } 66 return off 67} 68 69func wav_save(path: *u8, buf: *u8, len: i64) -> i64 { 70 let fd: i64 = sys_openat_wr(path, 420) 71 if fd < 0 { return 0 - 1 } 72 var wr: i64 = 0 73 while wr < len { let c: i64 = sys_write(fd, buf + wr, len - wr); if c <= 0 { break } wr = wr + c } 74 sys_close(fd) 75 return wr 76}