code wiki / (root) / nx_audio_pan_test.nx

nx_audio_pan_test.nx source

↩ module page · 72 lines · 3207 B

1// nx_audio_pan_test.nx -- KAT gate for sovereign stereo/constant-power pan (R2). 2// Pan-law table edges + center; mono->stereo placement; two opposite-panned 3// sources separate L/R; constant-power center (~0.707 each). expect_exit: 0. 4 5import "nx_syscalls.nx" 6import "nx_audio_mix.nx" 7import "nx_audio_pan.nx" 8 9func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 10func wn(v: i64) -> i64 { 11 let b: *u8 = sys_mmap(28); var m: i64 = v 12 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 13 let t: *u8 = sys_mmap(28); var k: i64 = 0 14 if m == 0 { t[0] = 48 as u8; k = 1 } 15 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 16 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 17 sys_write(1, b, k); return 0 18} 19func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 { 20 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) } 21 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) } 22 return 0 23} 24 25func main() -> i64 { 26 let pass: *i64 = (sys_mmap(8)) as *i64 27 let fail: *i64 = (sys_mmap(8)) as *i64 28 pass[0] = 0 29 fail[0] = 0 30 w("=== nx_audio_pan KAT (sovereign stereo + constant-power pan, R2) ===\n" as *u8) 31 32 // ---- pan-law table ---- 33 chk(ap_gl(0) == 256, pass, fail, "hardL gL=256" as *u8) 34 chk(ap_gr(0) == 0, pass, fail, "hardL gR=0" as *u8) 35 chk(ap_gl(2) == 181, pass, fail, "center gL=181 (~0.707)" as *u8) 36 chk(ap_gr(2) == 181, pass, fail, "center gR=181 (~0.707)" as *u8) 37 chk(ap_gl(4) == 0, pass, fail, "hardR gL=0" as *u8) 38 chk(ap_gr(4) == 256, pass, fail, "hardR gR=256" as *u8) 39 // constant power at center: gL^2+gR^2 ~= 65536 (within rounding) 40 let cp: i64 = ap_gl(2) * ap_gl(2) + ap_gr(2) * ap_gr(2) 41 chk(cp > 65000, pass, fail, "center constant-power (>65000)" as *u8) 42 chk(cp < 66000, pass, fail, "center constant-power (<66000)" as *u8) 43 44 let mono: *i64 = (sys_mmap(16)) as *i64 45 let oL: *i64 = (sys_mmap(16)) as *i64 46 let oR: *i64 = (sys_mmap(16)) as *i64 47 48 // ---- center placement: equal L/R, ~707 for a 1000 sample ---- 49 mono[0] = 1000; oL[0] = 0; oR[0] = 0 50 ap_pan_into(mono, 1, 256, 2, oL, oR) 51 chk(oL[0] == 707, pass, fail, "center L=707" as *u8) 52 chk(oR[0] == 707, pass, fail, "center R=707" as *u8) 53 54 // ---- hard-left: all energy in L ---- 55 mono[0] = 1000; oL[0] = 0; oR[0] = 0 56 ap_pan_into(mono, 1, 256, 0, oL, oR) 57 chk(oL[0] == 1000, pass, fail, "hardL L=1000" as *u8) 58 chk(oR[0] == 0, pass, fail, "hardL R=0" as *u8) 59 60 // ---- two opposite-panned sources separate into L and R ---- 61 let a: *i64 = (sys_mmap(16)) as *i64 62 let b: *i64 = (sys_mmap(16)) as *i64 63 a[0] = 1000; b[0] = 1000; oL[0] = 0; oR[0] = 0 64 ap_pan_into(a, 1, 256, 0, oL, oR) // A hard-left 65 ap_pan_into(b, 1, 256, 4, oL, oR) // B hard-right 66 chk(oL[0] == 1000, pass, fail, "mix: L = A only (1000)" as *u8) 67 chk(oR[0] == 1000, pass, fail, "mix: R = B only (1000)" as *u8) 68 69 w("=== VERDICT pass=" as *u8); wn(pass[0]); w(" fail=" as *u8); wn(fail[0]); w(" ===\n" as *u8) 70 if fail[0] == 0 { return 0 } 71 return 1 72}