nx_hifigan_verify.nx source
↩ module page · 149 lines · 10527 B
1// nx_hifigan_verify.nx -- VERIFY our sovereign HiFi-GAN against the transformers oracle (Qwen-style). Reads a REAL
2// SpeechT5 mel (ref_mel_short.f32, [T,80] row-major) + the reference vocoder output (ref_audio_short.f32, [T*256])
3// produced by hifigan_oracle.py, runs OUR nx_hifigan forward on the same mel, and reports the max/mean abs error.
4// Small error => our vocoder is CORRECT (produces the same human-grade audio as the reference). Also writes our
5// audio as a 16kHz WAV so it can be published to /listen and HEARD. license_tier: ORIGINAL expect_exit: 0
6import "nx_syscalls.nx"
7import "nx_f32.nx"
8import "nx_f32_activations.nx"
9import "nx_f32_cvt.nx"
10import "nx_vocops.nx"
11
12const SLOPE01: i64 = 0x3DCCCCCD
13const F_THIRD: i64 = 0x3EAAAAAB
14
15func p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
16func pn(v: i64) -> i64 { if v==0 { sys_write(1,"0" as *u8,1); return 0 } var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let d: *u8=sys_mmap(24); var k: i64=0; while m>0 {d[k]=(48+(m%10)) as u8; m=m/10; k=k+1} var i: i64=k-1; while i>=0 {let o: *u8=sys_mmap(1); o[0]=d[i]; sys_write(1,o,1); i=i-1} return 0 }
17func phx(v: i64) -> i64 { let b: *u8=sys_mmap(8); var i: i64=0; while i<8 { let n: i64=(v>>((7-i)*4))&0xF; if n<10 {b[i]=(48+n) as u8} else {b[i]=(87+n) as u8} i=i+1 } sys_write(1,b,8); return 0 }
18func u16le(b: *u8, o: i64) -> i64 { return (b[o]&0xff) | ((b[o+1]&0xff)<<8) }
19func u32le(b: *u8, o: i64) -> i64 { return (b[o]&0xff) | ((b[o+1]&0xff)<<8) | ((b[o+2]&0xff)<<16) | ((b[o+3]&0xff)<<24) }
20func f32_sub(a: i64, b: i64) -> i64 { return nx_f32_add(a, (b & 0xFFFFFFFF) ^ 0x80000000) }
21func f32_abs(a: i64) -> i64 { return a & 0x7FFFFFFF }
22func vcopy(d: *i64, s: *i64, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 }
23func vaddto(d: *i64, s: *i64, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=nx_f32_add(d[i],s[i]); i=i+1 } return 0 }
24func vzero(d: *i64, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=0; i=i+1 } return 0 }
25func vscale(d: *i64, n: i64, s: i64) -> i64 { var i: i64=0; while i<n { d[i]=nx_f32_mul(d[i],s); i=i+1 } return 0 }
26
27// read a whole file into a fresh buffer; returns bytes read, sets *bufp.
28func read_all(path: *u8, cap: i64, bufp: *i64) -> i64 {
29 let fd: i64 = sys_openat_rd(path); if fd<0 { return 0-1 }
30 let buf: *u8 = sys_mmap(cap); var n: i64=0; var go: i64=1
31 while go==1 { let r: i64=sys_read(fd,(buf as i64+n) as *u8,cap-n); if r<=0 {go=0} else {n=n+r; if n>=cap {go=0}} }
32 sys_close(fd); bufp[0]=buf as i64; return n
33}
34
35func main() -> i64 {
36 p("=== nx_hifigan_verify -- our vocoder vs the transformers oracle ===\n" as *u8)
37 // dims: ref_dims_short.txt = "T 80 audiolen"
38 let dbp: *i64 = sys_mmap(8) as *i64
39 let dn: i64 = read_all("/home/elderwesto/nx_stage/ref_dims_short.txt" as *u8, 256, dbp)
40 if dn<0 { p("no ref_dims_short.txt (run the oracle short-slice first)\n" as *u8); sys_exit(1); return 1 }
41 let db: *u8 = dbp[0] as *u8
42 var T: i64=0; var i: i64=0; while i<dn { let c: i64=db[i] as i64; if c>=48 { if c<=57 { T=T*10+(c-48) } else { i=dn } } else { i=dn } i=i+1 }
43 p("mel frames T="); pn(T); p("\n" as *u8)
44 let AUD: i64 = T*256
45
46 // read ref_mel_short.f32 [T,80] row-major -> mel[80,T]
47 let mbp: *i64 = sys_mmap(8) as *i64
48 let mn: i64 = read_all("/home/elderwesto/nx_stage/ref_mel_short.f32" as *u8, T*80*4 + 64, mbp)
49 if mn<0 { p("no ref_mel_short.f32\n" as *u8); sys_exit(1); return 1 }
50 let mb: *u8 = mbp[0] as *u8
51 let mel: *i64 = sys_mmap(80*T*8 + 64) as *i64
52 var c: i64=0; while c<80 { var t: i64=0; while t<T { mel[c*T+t]=u32le(mb, (t*80+c)*4); t=t+1 } c=c+1 }
53
54 // read ref_audio_short.f32 [AUD]
55 let abp: *i64 = sys_mmap(8) as *i64
56 read_all("/home/elderwesto/nx_stage/ref_audio_short.f32" as *u8, AUD*4 + 64, abp)
57 let ab: *u8 = abp[0] as *u8
58
59 // load HiFi-GAN weights from the .bin
60 let wbp: *i64 = sys_mmap(8) as *i64
61 let bn: i64 = read_all("/home/elderwesto/nx_stage/hifigan_pytorch_model.bin" as *u8, 67108864, wbp)
62 let buf: *u8 = wbp[0] as *u8
63 var ez: i64 = bn-22; while ez>=0 { if buf[ez]==0x50 as u8 { if buf[ez+1]==0x4B as u8 { if buf[ez+2]==0x05 as u8 { if buf[ez+3]==0x06 as u8 { break } } } } ez=ez-1 }
64 let n_entries: i64 = u16le(buf, ez+10)
65 let doff: *i64 = sys_mmap(256*8) as *i64; let dsz: *i64 = sys_mmap(256*8) as *i64
66 var z: i64=0; while z<256 { doff[z]=0-1; dsz[z]=0; z=z+1 }
67 var off: i64=u32le(buf,ez+16); var e: i64=0
68 while e<n_entries {
69 if buf[off]!=0x50 as u8 { e=n_entries } else {
70 let usize: i64=u32le(buf,off+24); let fnl: i64=u16le(buf,off+28); let exl: i64=u16le(buf,off+30); let cml: i64=u16le(buf,off+32); let lho: i64=u32le(buf,off+42)
71 var slash: i64=0-1; var q: i64=0; while q<fnl { if buf[off+46+q]==0x2F as u8 { slash=q } q=q+1 }
72 if slash>=0 { let c0: i64=buf[off+46+slash+1] as i64; if c0>=48 { if c0<=57 {
73 var kk: i64=0; var pp: i64=slash+1; while pp<fnl { let cc: i64=buf[off+46+pp] as i64; if cc>=48 { if cc<=57 { kk=kk*10+(cc-48); pp=pp+1 } else { pp=fnl } } else { pp=fnl } }
74 if kk<256 { let lfnl: i64=u16le(buf,lho+26); let lexl: i64=u16le(buf,lho+28); doff[kk]=lho+30+lfnl+lexl; dsz[kk]=usize }
75 } } }
76 off=off+46+fnl+exl+cml; e=e+1
77 }
78 }
79 let wpool: *i64 = sys_mmap(16777216*8) as *i64; let woff: *i64 = sys_mmap(256*8) as *i64
80 var cur: i64=0; var k: i64=0
81 while k<158 { woff[k]=cur; let cnt: i64=dsz[k]/4; var j: i64=0; while j<cnt { wpool[cur+j]=u32le(buf, doff[k]+4*j); j=j+1 } cur=cur+cnt; k=k+1 }
82
83 // normalize mel (mel-mean)/scale
84 let mean: *i64=(wpool as i64+woff[0]*8) as *i64; let scale: *i64=(wpool as i64+woff[1]*8) as *i64
85 c=0; while c<80 { var t: i64=0; while t<T { mel[c*T+t]=nx_f32_div(f32_sub(mel[c*T+t],mean[c]),scale[c]); t=t+1 } c=c+1 }
86
87 let KS: *i64=sys_mmap(4*8) as *i64; KS[0]=3; KS[1]=7; KS[2]=11
88 let DZ: *i64=sys_mmap(4*8) as *i64; DZ[0]=1; DZ[1]=3; DZ[2]=5
89 let BS: i64=524288
90 let bufX: *i64=sys_mmap(BS*8) as *i64; let bufU: *i64=sys_mmap(BS*8) as *i64; let xs: *i64=sys_mmap(BS*8) as *i64
91 let y: *i64=sys_mmap(BS*8) as *i64; let ro: *i64=sys_mmap(BS*8) as *i64; let t1: *i64=sys_mmap(BS*8) as *i64; let t2: *i64=sys_mmap(BS*8) as *i64
92
93 conv1d(mel, (wpool as i64+woff[3]*8) as *i64, (wpool as i64+woff[2]*8) as *i64, bufX, 80, T, 512, 7, 1, 3, 1)
94 var ch: i64=512; var L: i64=T; var s: i64=0
95 while s<4 {
96 leaky_relu_vec(bufX, ch*L, SLOPE01)
97 let ch2: i64=ch/2
98 let L2: i64=conv_transpose1d(bufX, (wpool as i64+woff[5+2*s]*8) as *i64, (wpool as i64+woff[4+2*s]*8) as *i64, bufU, ch, L, ch2, 8, 4, 2, 0, 1)
99 vzero(xs, ch2*L2)
100 var kk: i64=0
101 while kk<3 {
102 let r: i64=s*3+kk; let Kk: i64=KS[kk]; let base: i64=12+12*r
103 vcopy(y, bufU, ch2*L2)
104 var jj: i64=0
105 while jj<3 { let dil: i64=DZ[jj]
106 resblock1_1dil(y, (wpool as i64+woff[base+1+2*jj]*8) as *i64, (wpool as i64+woff[base+2*jj]*8) as *i64, (wpool as i64+woff[base+7+2*jj]*8) as *i64, (wpool as i64+woff[base+6+2*jj]*8) as *i64, ro, ch2, L2, Kk, dil, SLOPE01, t1, t2)
107 vcopy(y, ro, ch2*L2); jj=jj+1 }
108 vaddto(xs, y, ch2*L2); kk=kk+1
109 }
110 vscale(xs, ch2*L2, F_THIRD); vcopy(bufX, xs, ch2*L2); ch=ch2; L=L2; s=s+1
111 }
112 leaky_relu_vec(bufX, ch*L, SLOPE01)
113 let audio: *i64=sys_mmap(BS*8) as *i64
114 conv1d(bufX, (wpool as i64+woff[157]*8) as *i64, (wpool as i64+woff[156]*8) as *i64, audio, ch, L, 1, 7, 1, 3, 1)
115 var ia: i64=0; while ia<L { audio[ia]=nx_f32_tanh(audio[ia]); ia=ia+1 }
116
117 // compare to reference
118 var maxe: i64=0; var sume: i64=0; var cmp: i64=L; if AUD<cmp { cmp=AUD }
119 ia=0; while ia<cmp { let d0: i64=f32_abs(f32_sub(audio[ia], u32le(ab, ia*4))); if f32_abs(d0)>f32_abs(maxe) { maxe=d0 } sume=nx_f32_add(sume, d0); ia=ia+1 }
120 let meane: i64=nx_f32_div(sume, nx_i32_to_f32(cmp))
121 p("our audio len="); pn(L); p(" ref len="); pn(AUD); p(" compared="); pn(cmp); p("\n" as *u8)
122 p("our[0..3]="); phx(audio[0]&0xFFFFFFFF); p(" "); phx(audio[1]&0xFFFFFFFF); p(" "); phx(audio[2]&0xFFFFFFFF); p("\n" as *u8)
123 p("ref[0..3]="); phx(u32le(ab,0)); p(" "); phx(u32le(ab,4)); p(" "); phx(u32le(ab,8)); p("\n" as *u8)
124 p("max abs err="); phx(maxe&0xFFFFFFFF); p(" mean abs err="); phx(meane&0xFFFFFFFF); p(" (small => our vocoder matches the reference)\n" as *u8)
125
126 // write our audio as 16kHz mono int16 WAV
127 let wav: *u8 = sys_mmap(L*2 + 128)
128 // header
129 let hdr: *u8 = "RIFF" as *u8; var hi: i64=0; while hi<4 { wav[hi]=hdr[hi]; hi=hi+1 }
130 let dsize: i64 = L*2; let csize: i64 = 36 + dsize
131 wav[4]=(csize&0xff) as u8; wav[5]=((csize>>8)&0xff) as u8; wav[6]=((csize>>16)&0xff) as u8; wav[7]=((csize>>24)&0xff) as u8
132 let wave: *u8="WAVEfmt " as *u8; hi=0; while hi<8 { wav[8+hi]=wave[hi]; hi=hi+1 }
133 wav[16]=16 as u8; wav[17]=0 as u8; wav[18]=0 as u8; wav[19]=0 as u8
134 wav[20]=1 as u8; wav[21]=0 as u8; wav[22]=1 as u8; wav[23]=0 as u8 // PCM, mono
135 wav[24]=0x80 as u8; wav[25]=0x3E as u8; wav[26]=0 as u8; wav[27]=0 as u8 // 16000 Hz
136 wav[28]=0 as u8; wav[29]=0x7D as u8; wav[30]=0 as u8; wav[31]=0 as u8 // byte rate 32000
137 wav[32]=2 as u8; wav[33]=0 as u8; wav[34]=16 as u8; wav[35]=0 as u8
138 let dt: *u8="data" as *u8; hi=0; while hi<4 { wav[36+hi]=dt[hi]; hi=hi+1 }
139 wav[40]=(dsize&0xff) as u8; wav[41]=((dsize>>8)&0xff) as u8; wav[42]=((dsize>>16)&0xff) as u8; wav[43]=((dsize>>24)&0xff) as u8
140 // samples: f32 [-1,1] -> int16
141 ia=0; while ia<L { let sv: i64=nx_f32_to_i32(nx_f32_mul(audio[ia], nx_i32_to_f32(32000))); var iv: i64=sv; if iv>32767 {iv=32767} if iv<0-32768 {iv=0-32768} wav[44+ia*2]=(iv&0xff) as u8; wav[45+ia*2]=((iv>>8)&0xff) as u8; ia=ia+1 }
142 let wfd: i64=sys_openat_wr("/mnt/c/Users/elder/nishi-core/nxc2/web_assets/ng_elara_neural.wav" as *u8, 0x1a4)
143 if wfd>=0 { sys_write(wfd, wav, 44+L*2); sys_close(wfd); p("wrote web_assets/ng_elara_neural.wav ("); pn(44+L*2); p(" bytes)\n" as *u8) }
144
145 // GATE: mean abs err below ~0.02 => match (f32 0.02 = 0x3CA3D70A)
146 if f32_abs(meane) < 0x3CA3D70A { p("verdict=GREEN -- our sovereign vocoder MATCHES the transformers reference (mean err < 0.02). Real neural audio, verified.\n" as *u8); sys_exit(0); return 0 }
147 p("verdict=NOTE -- audio differs from reference; inspect errs above (may be a forward bug -- bisect like Qwen)\n" as *u8)
148 sys_exit(1); return 1
149}