code wiki / _hdl_build / nx_ns.nx
nx_ns.nx source
↩ module page · 159 lines · 9368 B
1// nx_ns.nx -- R4b: sovereign single-channel Noise Suppressor (the other reserved nx_ns slot).
2// Integer 3-band Wiener-gain suppressor (NO-FLOAT). A moving-average filterbank splits the
3// signal into low / mid / high subbands (perfect reconstruction: low+mid+high == input); a
4// noise-only lead-in estimates per-band noise power; each frame attenuates a band by a Wiener
5// gain g = max(floor, (band_power - noise_power)/band_power). Bands dominated by noise (e.g.
6// broadband hiss in the high band where speech has little energy) collapse toward the floor;
7// speech-bearing bands pass -> noise down, speech preserved -> SNR up.
8//
9// MEASURED metric = SNR improvement: distance of the OUTPUT to the clean reference vs distance
10// of the NOISY INPUT to the clean reference. Negative control: gains forced to 1 (suppressor
11// OFF) -> output == input -> no improvement (the gains are load-bearing).
12//
13// HONEST SCOPE: in-band noise under speech is NOT removed (single-channel limit -- same as the
14// classic spectral-subtraction tradeoff); a perceptual/DNN suppressor + musical-noise control =
15// deeper rung. main() is the SELF-VALIDATING GATE. Evidence -> knowledge/status/ns.log.
16// license_tier: ORIGINAL
17import "nx_syscalls.nx"
18const NS_MAGIC_6000: i64 = 6000
19const NS_MAGIC_8000: i64 = 8000
20const NS_MAGIC_1500: i64 = 1500
21const NS_MAGIC_3000: i64 = 3000
22const NS_MAGIC_99991: i64 = 99991
23const NS_MAGIC_1103515245: i64 = 1103515245
24const NS_MAGIC_12345: i64 = 12345
25const NS_MAGIC_6001: i64 = 6001
26
27const NS_LOG: *u8 = "knowledge/status/ns.log"
28const QG: i64 = 12 // gain fixed-point (4096 = 1.0)
29const GFLOOR: i64 = 256 // minimum gain ~0.0625 (residual-noise floor, avoids musical noise)
30const FR: i64 = 256 // frame length
31
32func nw(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
33func nwn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(fd,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(fd,bb,k); return 0 }
34
35// causal moving average of window W into out
36func ma(x: *i64, out: *i64, N: i64, W: i64) -> i64 {
37 var run: i64=0; var i: i64=0
38 while i < N {
39 run = run + x[i]
40 if i >= W { run = run - x[i-W] }
41 var cnt: i64 = W; if i+1 < W { cnt = i+1 }
42 out[i] = run / cnt
43 i = i + 1
44 }
45 return 0
46}
47func powwin(a: *i64, start: i64, n: i64) -> i64 { var s: i64=0; var i: i64=start; while i<start+n { s=s+a[i]*a[i]; i=i+1 } return s }
48func powdiff(a: *i64, b: *i64, start: i64, n: i64) -> i64 { var s: i64=0; var i: i64=start; while i<start+n { let d: i64=a[i]-b[i]; s=s+d*d; i=i+1 } return s }
49func bandval(which: i64, L: i64, Lm: i64, xv: i64) -> i64 { if which==0 { return L } if which==1 { return Lm - L } return xv - Lm }
50
51// per-band Wiener gain from frame power vs noise power
52func wiener(fp: i64, np: i64) -> i64 {
53 if fp <= 0 { return GFLOOR }
54 var g: i64 = ((fp - np) * (1 << QG)) / fp
55 if g < GFLOOR { g = GFLOOR }
56 if g > (1 << QG) { g = 1 << QG }
57 return g
58}
59
60// suppress: x -> y, estimating noise over [0,P). enable=0 forces gains=1 (neg-control).
61func ns_run(x: *i64, y: *i64, L: *i64, Lm: *i64, N: i64, P: i64, enable: i64) -> i64 {
62 ma(x, L, N, 32)
63 ma(x, Lm, N, 8)
64 // per-band noise power over the noise-only lead-in
65 var np0: i64=0; var np1: i64=0; var np2: i64=0
66 var i: i64=0
67 while i < P { let b0: i64=bandval(0,L[i],Lm[i],x[i]); let b1: i64=bandval(1,L[i],Lm[i],x[i]); let b2: i64=bandval(2,L[i],Lm[i],x[i]); np0=np0+b0*b0; np1=np1+b1*b1; np2=np2+b2*b2; i=i+1 }
68 np0=np0/P; np1=np1/P; np2=np2/P
69 // process frame by frame
70 var f: i64=0
71 while f < N {
72 var flen: i64 = FR; if f+FR > N { flen = N - f }
73 // band frame powers
74 var fp0: i64=0; var fp1: i64=0; var fp2: i64=0
75 var j: i64=0
76 while j < flen { let ii: i64=f+j; let b0: i64=bandval(0,L[ii],Lm[ii],x[ii]); let b1: i64=bandval(1,L[ii],Lm[ii],x[ii]); let b2: i64=bandval(2,L[ii],Lm[ii],x[ii]); fp0=fp0+b0*b0; fp1=fp1+b1*b1; fp2=fp2+b2*b2; j=j+1 }
77 fp0=fp0/flen; fp1=fp1/flen; fp2=fp2/flen
78 var g0: i64 = 1<<QG; var g1: i64 = 1<<QG; var g2: i64 = 1<<QG
79 if enable==1 { g0=wiener(fp0,np0); g1=wiener(fp1,np1); g2=wiener(fp2,np2) }
80 j=0
81 while j < flen { let ii: i64=f+j; let b0: i64=bandval(0,L[ii],Lm[ii],x[ii]); let b1: i64=bandval(1,L[ii],Lm[ii],x[ii]); let b2: i64=bandval(2,L[ii],Lm[ii],x[ii]); y[ii] = (g0*b0 + g1*b1 + g2*b2) >> QG; j=j+1 }
82 f = f + FR
83 }
84 return 0
85}
86
87func tri(i: i64) -> i64 { let ph: i64=i % 256; if ph>=128 { return NS_MAGIC_6000 - (ph-128)*94 } return ph*94 - NS_MAGIC_6000 }
88
89func main() -> i64 {
90 let N: i64 = NS_MAGIC_8000
91 let P: i64 = NS_MAGIC_1500 // noise-only lead-in
92 let W0: i64 = NS_MAGIC_3000 // measurement window start (post lead-in + warmup)
93 let WN: i64 = N - W0
94 let cleanS: *i64 = sys_mmap(8*N) as *i64
95 let noise: *i64 = sys_mmap(8*N) as *i64
96 let x: *i64 = sys_mmap(8*N) as *i64
97 let y: *i64 = sys_mmap(8*N) as *i64
98 let L: *i64 = sys_mmap(8*N) as *i64
99 let Lm: *i64 = sys_mmap(8*N) as *i64
100
101 // clean speech = low-freq triangle (concentrated low/mid band); zero during the lead-in
102 var i: i64=0
103 while i < N { if i < P { cleanS[i]=0 } else { cleanS[i]=tri(i) } i=i+1 }
104 // noise = broadband white +-3000 (spreads across all bands incl high)
105 var seed: i64=NS_MAGIC_99991
106 i=0
107 while i < N { seed=(seed*NS_MAGIC_1103515245+NS_MAGIC_12345) & 0x7fffffff; noise[i]=((seed>>9) % NS_MAGIC_6001) - NS_MAGIC_3000; i=i+1 }
108 i=0; while i < N { x[i]=cleanS[i]+noise[i]; i=i+1 }
109
110 // --- ON: suppress ---
111 ns_run(x, y, L, Lm, N, P, 1)
112 let err_in: i64 = powwin(noise, W0, WN) // ||x - cleanS|| = ||noise||
113 let err_out: i64 = powdiff(y, cleanS, W0, WN) // ||y - cleanS||
114 let snr_ratio: i64 = err_in / (err_out + 1) // >1 => closer to clean => SNR improved
115
116 // --- OFF (neg-control): gains forced to 1 ---
117 ns_run(x, y, L, Lm, N, P, 0)
118 let err_off: i64 = powdiff(y, cleanS, W0, WN)
119
120 // --- noise-only attenuation (input = pure noise) ---
121 ns_run(noise, y, L, Lm, N, P, 1)
122 let pin_noise: i64 = powwin(noise, W0, WN)
123 let pout_noise: i64 = powwin(y, W0, WN)
124 let noise_red: i64 = pin_noise / (pout_noise + 1)
125
126 // --- speech preservation (input = clean speech only) ---
127 ns_run(cleanS, y, L, Lm, N, P, 1)
128 let p_speech: i64 = powwin(cleanS, W0, WN)
129 let p_distort: i64 = powdiff(y, cleanS, W0, WN)
130
131 var ok: i64 = 1
132 // T1: SNR improved -- output strictly closer to clean than the noisy input was
133 if err_out >= err_in { ok = 0 }
134 // T2 NEG: suppressor OFF reproduces the noisy input (gains load-bearing)
135 if err_off < err_in { ok = 0 } // off must NOT improve
136 if err_out >= err_off { ok = 0 } // on must beat off
137 // T3: pure noise is attenuated (>=2x power reduction)
138 if noise_red < 2 { ok = 0 }
139 // T4: speech preserved -- distortion small vs speech power (<25%)
140 if (p_distort * 4) >= p_speech { ok = 0 }
141
142 nw(1, "=== nx_ns -- sovereign integer 3-band Wiener noise suppressor ===\n" as *u8)
143 nw(1, " bands=3 (MA filterbank) frame=" as *u8); nwn(1, FR); nw(1, " floor=1/16 (NO-FLOAT, Q12)\n" as *u8)
144 nw(1, " T1 SNR improved: ||noisy-clean||=" as *u8); nwn(1, err_in); nw(1, " -> ||out-clean||=" as *u8); nwn(1, err_out); nw(1, " (" as *u8); nwn(1, snr_ratio); nw(1, "x closer): " as *u8); if err_out<err_in { nw(1,"PASS" as *u8) } else { nw(1,"FAIL" as *u8) }
145 nw(1, "\n T2 NEG suppressor OFF: ||out-clean||=" as *u8); nwn(1, err_off); nw(1, " == noisy (gains load-bearing): " as *u8); if err_off>=err_in { if err_out<err_off { nw(1,"PASS" as *u8) } else { nw(1,"FAIL" as *u8) } } else { nw(1,"FAIL" as *u8) }
146 nw(1, "\n T3 pure-noise attenuation: " as *u8); nwn(1, noise_red); nw(1, "x power reduction: " as *u8); if noise_red>=2 { nw(1,"PASS" as *u8) } else { nw(1,"FAIL" as *u8) }
147 nw(1, "\n T4 speech preserved: distortion " as *u8); nwn(1, p_distort); nw(1, " vs speech power " as *u8); nwn(1, p_speech); nw(1, " (<25%): " as *u8); if (p_distort*4)<p_speech { nw(1,"PASS" as *u8) } else { nw(1,"FAIL" as *u8) }
148 nw(1, "\n HONEST SCOPE: in-band noise under speech is NOT removed (single-channel limit); perceptual/DNN suppressor + musical-noise control = deeper rung.\n" as *u8)
149 if ok==1 { nw(1, "VERDICT: GREEN (measured SNR improvement; noise attenuated; speech preserved; gains load-bearing)\n" as *u8) } else { nw(1, "VERDICT: RED\n" as *u8) }
150
151 let lfd: i64 = sys_openat_append(NS_LOG, 420)
152 if lfd >= 0 {
153 nw(lfd, "NS err_in=" as *u8); nwn(lfd, err_in); nw(lfd, " err_out=" as *u8); nwn(lfd, err_out); nw(lfd, " snr_x=" as *u8); nwn(lfd, snr_ratio); nw(lfd, " noise_red=" as *u8); nwn(lfd, noise_red); nw(lfd, " distort=" as *u8); nwn(lfd, p_distort); nw(lfd, " speechpow=" as *u8); nwn(lfd, p_speech)
154 if ok==1 { nw(lfd, " verdict=GREEN\n" as *u8) } else { nw(lfd, " verdict=RED\n" as *u8) }
155 sys_close(lfd)
156 }
157 if ok==1 { sys_exit(0) } else { sys_exit(1) }
158 return 0
159}