code wiki / _hdl_build / nx_lipsync_gate.nx
nx_lipsync_gate.nx source
↩ module page · 58 lines · 3694 B
1// nx_lipsync_gate.nx -- TALKING AVATAR v0 (R6): text -> visemes -> an animated mouth on a face. Proves (T1) the
2// viseme rules are right (vowels open the mouth, plosive m/p shut the lips), (T2) a sentence ANIMATES (the mouth
3// opens/closes = talking), (T3) valid APNG. Emits knowledge/synth_talk.png (the talking head). expect_exit:0
4// license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_lipsync.nx"
7import "nx_apng.nx"
8
9func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
11func cks(fb: *i64, n: i64) -> i64 { var s: i64=1469598103; var i: i64=0; while i<n{s=(s*31+(fb[i]&0xffffff))&0x0fffffffffffffff;i=i+1} return s }
12func find4(buf: *u8, n: i64, a: i64, b: i64, c: i64, d: i64) -> i64 { var i: i64=0; while i+4<=n{ if (buf[i]&0xff)==a{ if (buf[i+1]&0xff)==b{ if (buf[i+2]&0xff)==c{ if (buf[i+3]&0xff)==d{return i}}}} i=i+1} return 0-1 }
13
14const LW: i64 = 96
15const LH: i64 = 96
16
17func main() -> i64 {
18 hw("=== nx_lipsync_gate -- talking avatar v0: text -> viseme mouth (R6) ===\n" as *u8)
19 var fails: i64 = 0
20 let vh: *i64 = sys_mmap(64 * 8) as *i64
21 let vw: *i64 = sys_mmap(64 * 8) as *i64
22
23 // T1: viseme correctness on "mama" -- a(open) >> m(shut), alternating
24 let nm: i64 = ls_text_visemes("mama" as *u8, vh, vw, 64)
25 hw(" 'mama' viseme heights: m="); pn(vh[0]); hw(" a="); pn(vh[1]); hw(" m="); pn(vh[2]); hw(" a="); pn(vh[3]); hw("\n" as *u8)
26 if vh[1] > vh[0] + 8 { if vh[0] <= 2 { if vh[2] <= 2 { hw("T1 PASS visemes right (vowel a opens, plosive m shuts the lips)\n" as *u8) } else { fails=fails+1; hw("T1 FAIL m2 not shut\n" as *u8) } } else { fails=fails+1; hw("T1 FAIL m not shut\n" as *u8) } }
27 else { fails = fails + 1; hw("T1 FAIL a not open enough\n" as *u8) }
28
29 // T2+T3: render a sentence, one viseme per char -> APNG that ANIMATES
30 let txt: *u8 = "hello i am a talking synthetic human" as *u8
31 let n: i64 = ls_text_visemes(txt, vh, vw, 64)
32 let fb: *i64 = sys_mmap(LW * LH * 8) as *i64
33 let apbuf: *u8 = sys_mmap(12 * 1024 * 1024)
34 let seq: *i64 = sys_mmap(8) as *i64; seq[0] = 0
35 var o: i64 = apng_open(apbuf, LW, LH, n)
36 var minh: i64 = 999; var maxh: i64 = 0
37 var f: i64 = 0
38 while f < n {
39 ls_face_frame(fb, LW, LH, vh[f], vw[f])
40 if vh[f] < minh { minh = vh[f] }
41 if vh[f] > maxh { maxh = vh[f] }
42 var first: i64 = 0; if f == 0 { first = 1 }
43 o = apng_frame(apbuf, o, seq, fb, LW, LH, 9, first)
44 f = f + 1
45 }
46 o = apng_close(apbuf, o)
47 let fd: i64 = sys_openat_wr("knowledge/synth_talk.png" as *u8, 0x1a4)
48 if fd >= 0 { sys_write(fd, apbuf, o); sys_close(fd) }
49 hw(" spoke '"); hw(txt); hw("' -> "); pn(n); hw(" visemes, mouth "); pn(minh); hw(".."); pn(maxh); hw(", "); pn(o); hw("B APNG\n" as *u8)
50 if maxh > minh + 8 { hw("T2 PASS the mouth ANIMATES across the sentence (opens + shuts = talking)\n" as *u8) }
51 else { fails = fails + 1; hw("T2 FAIL mouth static\n" as *u8) }
52 if find4(apbuf, o, 97, 99, 84, 76) >= 0 { hw("T3 PASS valid APNG (knowledge/synth_talk.png)\n" as *u8) }
53 else { fails = fails + 1; hw("T3 FAIL APNG invalid\n" as *u8) }
54
55 if fails == 0 { hw("LIPSYNC-GATE 3/3 GREEN -- talking avatar v0: a synthetic human LIP-SYNCS typed text (R6; rule-based, sovereign)\n" as *u8); sys_exit(0); return 0 }
56 hw("LIPSYNC-GATE RED fails="); pn(fails); hw("\n" as *u8)
57 sys_exit(1); return 1
58}