code wiki / _hdl_build / nx_denoise_spectral_gate.nx
nx_denoise_spectral_gate.nx source
↩ module page · 45 lines · 2797 B
1// nx_denoise_spectral_gate.nx -- proves + MEASURES sovereign spectral denoise (nx_denoise_spectral): estimate the
2// noise floor from a silence frame, then remove broadband noise from a speech+noise frame while keeping the speech.
3import "nx_syscalls.nx"
4import "nx_gate_emit_lib.nx"
5import "nx_denoise_spectral.nx"
6
7func tri8(i: i64) -> i64 { let p: i64 = i % 8; if p <= 4 { return p } return 8 - p }
8// power of bin `b` of a signal (copies it, doesn't modify)
9func bin_power(sig: *i64, n: i64, b: i64) -> i64 {
10 let re: *i64 = sys_mmap(n*8) as *i64; let im: *i64 = sys_mmap(n*8) as *i64
11 var i: i64=0; while i<n { re[i]=sig[i]; im[i]=0; i=i+1 }
12 nx_fft_forward(re, im, n)
13 return re[b]*re[b] + im[b]*im[b]
14}
15
16func main() -> i64 {
17 g_puts("nx_denoise_spectral gate (FFT noise-floor + spectral gate, MEASURED)\n" as *u8)
18 var pass: i64 = 0; var total: i64 = 0
19 let n: i64 = 16
20
21 // noise-only frame (silence): just the ±5 high-frequency hiss (Nyquist, bin 8)
22 let noise: *i64 = sys_mmap(n*8) as *i64; let nim: *i64 = sys_mmap(n*8) as *i64
23 var i: i64=0; while i<n { var v: i64 = 5; if (i & 1) == 1 { v = 0 - 5 } noise[i] = v; nim[i] = 0; i=i+1 }
24 let floor: i64 = ds_noise_floor(noise, nim, n, 512) // 2x the loudest noise bin
25 g_puts(" [measure] estimated noise floor (power) = " as *u8); g_pn(floor); g_puts("\n" as *u8)
26
27 // speech+noise frame: triangle speech (bin 2) + the ±5 hiss (bin 8)
28 let sig: *i64 = sys_mmap(n*8) as *i64; let sim: *i64 = sys_mmap(n*8) as *i64
29 i=0; while i<n { var v: i64 = 50 + 30*tri8(i); if (i & 1) == 0 { v = v + 5 } else { v = v - 5 } sig[i] = v; sim[i] = 0; i=i+1 }
30 let speech_before: i64 = bin_power(sig, n, 2) // the speech carrier
31 let hiss_before: i64 = bin_power(sig, n, 8) // the Nyquist hiss (noise)
32
33 ds_spectral_gate(sig, sim, n, floor, 20) // denoise (attenuate sub-floor bins to ~8%)
34
35 let speech_after: i64 = bin_power(sig, n, 2)
36 let hiss_after: i64 = bin_power(sig, n, 8)
37 g_puts(" [measure] speech bin: " as *u8); g_pn(speech_before); g_puts("->" as *u8); g_pn(speech_after); g_puts(" hiss bin: " as *u8); g_pn(hiss_before); g_puts("->" as *u8); g_pn(hiss_after); g_puts("\n" as *u8)
38
39 pass = pass + g_check("noise hiss bin attenuated >= 4x (removed during speech)" as *u8, hiss_after * 4 < hiss_before); total=total+1
40 pass = pass + g_check("speech carrier preserved (>= half its energy)" as *u8, speech_after * 2 > speech_before); total=total+1
41
42 g_puts("---- denoise-spectral gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
43 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
44 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
45}