code wiki / (root) / nx_chord_grade_gate.nx

nx_chord_grade_gate.nx source

↩ module page · 181 lines · 6498 B

1// nx_chord_grade_gate.nx -- REFEREE for LG-4 chord-aware grading (nx_chord_grade). 2// 3// SONG (4 slots): A3 | A-major(A3,C#4,E4) | power-5th(A3,E4) | C-major(C4,E4,G4). 4// Three performances are synthesized (sum-of-sine chords per slot) and graded: 5// GOOD : every slot played correctly -> 1000, all HIT 6// BAD : disjoint wrong notes every slot -> 0, all WRONG (neg-control) 7// PARTIAL : A3 | only 2 of 3 | SILENT | C-maj -> 666, [HIT,PARTIAL,MISS,HIT] 8// 9// Evidence -> stdout + knowledge/status/chord_grade_gate.log. Exit 0 GREEN / 1 RED. 10// Sovereign x86_64 throughout. license_tier: ORIGINAL 11import "nx_syscalls_x86_64.nx" 12import "nx_chord_grade.nx" 13import "nx_polypitch.nx" 14import "nx_note.nx" 15 16const SLOT: i64 = 1536 17const NS: i64 = 6144 18const FS: i64 = 8000 19const AMP: i64 = 10000 20const TWO_PI: i64 = 411775 21 22func gp(logfd: i64, s: *u8) -> i64 { 23 var n: i64 = 0 24 while s[n] != (0 as u8) { n = n + 1 } 25 sys_write(1, s, n) 26 if logfd > 0 { sys_write(logfd, s, n) } 27 return 0 28} 29func gn(logfd: i64, v: i64) -> i64 { 30 let bb: *u8 = sys_mmap(28) 31 var m: i64 = v 32 if m < 0 { sys_write(1, "-\x00" as *u8, 1); if logfd > 0 { sys_write(logfd, "-\x00" as *u8, 1) } m = 0 - m } 33 let t: *u8 = sys_mmap(28) 34 var k: i64 = 0 35 if m == 0 { t[0] = 48 as u8; k = 1 } 36 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 37 var i: i64 = 0 38 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 39 sys_write(1, bb, k) 40 if logfd > 0 { sys_write(logfd, bb, k) } 41 return 0 42} 43 44func add_sine_region(acc: *i64, start: i64, dur: i64, f: i64, amp: i64) -> i64 { 45 if f <= 0 { return 0 } 46 let dph: i64 = (TWO_PI * f) / FS 47 var ph: i64 = 0 48 var n: i64 = 0 49 while n < dur { 50 acc[start + n] = acc[start + n] + ((amp * nx_pp_sinfull(ph)) >> 16) 51 ph = ph + dph 52 if ph >= TWO_PI { ph = ph - TWO_PI } 53 n = n + 1 54 } 55 return 0 56} 57// add a note (by MIDI) into a slot region 58func add_note(acc: *i64, tbl: *i64, slotstart: i64, midi: i64) -> i64 { 59 add_sine_region(acc, slotstart, SLOT, tbl[midi] / 100, AMP) 60 return 0 61} 62func normalize(acc: *i64, buf: *u8, total: i64) -> i64 { 63 var mx: i64 = 1 64 var n: i64 = 0 65 while n < total { var v: i64 = acc[n]; if v < 0 { v = 0 - v } if v > mx { mx = v } n = n + 1 } 66 n = 0 67 while n < total { 68 var s: i64 = acc[n] * 16000 / mx 69 if s > 32000 { s = 32000 } 70 if s < -32000 { s = -32000 } 71 var x: i64 = s 72 if x < 0 { x = x + 0x10000 } 73 buf[n * 2] = (x & 0xff) as u8 74 buf[n * 2 + 1] = ((x >> 8) & 0xff) as u8 75 n = n + 1 76 } 77 return 0 78} 79func zero(acc: *i64, total: i64) -> i64 { 80 var n: i64 = 0 81 while n < total { acc[n] = 0; n = n + 1 } 82 return 0 83} 84func setslot(song: *i64, s: i64, start: i64, nt: i64, m0: i64, m1: i64, m2: i64) -> i64 { 85 song[s * 9 + 0] = start 86 song[s * 9 + 1] = SLOT 87 song[s * 9 + 2] = nt 88 song[s * 9 + 3] = m0 89 song[s * 9 + 4] = m1 90 song[s * 9 + 5] = m2 91 return 0 92} 93func report(logfd: i64, label: *u8, score: i64, v: *i64) -> i64 { 94 gp(logfd, label) 95 gp(logfd, " score=\x00" as *u8); gn(logfd, score) 96 gp(logfd, " verdicts=[\x00" as *u8) 97 var i: i64 = 0 98 while i < 4 { gn(logfd, v[i]); gp(logfd, " \x00" as *u8); i = i + 1 } 99 gp(logfd, "] (0=HIT 1=PARTIAL 2=WRONG 3=MISS)\n\x00" as *u8) 100 return 0 101} 102 103func main() -> i64 { 104 let logfd: i64 = sys_openat_append("knowledge/status/chord_grade_gate.log\x00" as *u8, 0x1a4) 105 gp(logfd, "CHORD-GRADE-GATE LG-4 (chord-aware learn-game)\n\x00" as *u8) 106 107 let tbl: *i64 = sys_mmap(128 * 8) as *i64 108 nx_note_table(tbl) 109 110 // SONG: A3 | A-maj(57,61,64) | power-5th(57,64) | C-maj(60,64,67) 111 let song: *i64 = sys_mmap(4 * 9 * 8) as *i64 112 setslot(song, 0, 0, 1, 57, 0, 0) 113 setslot(song, 1, SLOT, 3, 57, 61, 64) 114 setslot(song, 2, 2 * SLOT, 2, 57, 64, 0) 115 setslot(song, 3, 3 * SLOT, 3, 60, 64, 67) 116 117 let acc: *i64 = sys_mmap(NS * 8) as *i64 118 let vG: *i64 = sys_mmap(4 * 8) as *i64 119 let vB: *i64 = sys_mmap(4 * 8) as *i64 120 let vP: *i64 = sys_mmap(4 * 8) as *i64 121 122 // GOOD 123 let pG: *u8 = sys_mmap(NS * 2) 124 zero(acc, NS) 125 add_note(acc, tbl, 0, 57) 126 add_note(acc, tbl, SLOT, 57); add_note(acc, tbl, SLOT, 61); add_note(acc, tbl, SLOT, 64) 127 add_note(acc, tbl, 2 * SLOT, 57); add_note(acc, tbl, 2 * SLOT, 64) 128 add_note(acc, tbl, 3 * SLOT, 60); add_note(acc, tbl, 3 * SLOT, 64); add_note(acc, tbl, 3 * SLOT, 67) 129 normalize(acc, pG, NS) 130 let sG: i64 = nx_chord_grade(song, 4, pG, FS, tbl, vG) 131 report(logfd, " GOOD \x00" as *u8, sG, vG) 132 133 // BAD: disjoint wrong notes (avoid {57,60,61,64,67}) 134 let pB: *u8 = sys_mmap(NS * 2) 135 zero(acc, NS) 136 add_note(acc, tbl, 0, 56) 137 add_note(acc, tbl, SLOT, 55); add_note(acc, tbl, SLOT, 58); add_note(acc, tbl, SLOT, 62) 138 add_note(acc, tbl, 2 * SLOT, 55); add_note(acc, tbl, 2 * SLOT, 62) 139 add_note(acc, tbl, 3 * SLOT, 55); add_note(acc, tbl, 3 * SLOT, 59); add_note(acc, tbl, 3 * SLOT, 63) 140 normalize(acc, pB, NS) 141 let sB: i64 = nx_chord_grade(song, 4, pB, FS, tbl, vB) 142 report(logfd, " BAD \x00" as *u8, sB, vB) 143 144 // PARTIAL: A3 | only 57,61 (miss 64) | SILENT | C-maj correct 145 let pP: *u8 = sys_mmap(NS * 2) 146 zero(acc, NS) 147 add_note(acc, tbl, 0, 57) 148 add_note(acc, tbl, SLOT, 57); add_note(acc, tbl, SLOT, 61) 149 add_note(acc, tbl, 3 * SLOT, 60); add_note(acc, tbl, 3 * SLOT, 64); add_note(acc, tbl, 3 * SLOT, 67) 150 normalize(acc, pP, NS) 151 let sP: i64 = nx_chord_grade(song, 4, pP, FS, tbl, vP) 152 report(logfd, " PARTIAL\x00" as *u8, sP, vP) 153 154 var ok: i64 = 1 155 if sG != 1000 { ok = 0 } 156 if vG[0] != CG_HIT { ok = 0 } 157 if vG[1] != CG_HIT { ok = 0 } 158 if vG[2] != CG_HIT { ok = 0 } 159 if vG[3] != CG_HIT { ok = 0 } 160 if sB != 0 { ok = 0 } 161 if vB[0] != CG_WRONG { ok = 0 } 162 if vB[1] != CG_WRONG { ok = 0 } 163 if vB[2] != CG_WRONG { ok = 0 } 164 if vB[3] != CG_WRONG { ok = 0 } 165 if sP != 666 { ok = 0 } 166 if vP[0] != CG_HIT { ok = 0 } 167 if vP[1] != CG_PARTIAL { ok = 0 } 168 if vP[2] != CG_MISS { ok = 0 } 169 if vP[3] != CG_HIT { ok = 0 } 170 171 if ok == 1 { 172 gp(logfd, "CHORD-GRADE-GATE result=ALL-PASS verdict=GREEN\n\x00" as *u8) 173 if logfd > 0 { sys_close(logfd) } 174 sys_exit(0) 175 return 0 176 } 177 gp(logfd, "CHORD-GRADE-GATE result=FAIL verdict=RED\n\x00" as *u8) 178 if logfd > 0 { sys_close(logfd) } 179 sys_exit(1) 180 return 1 181}