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}