nx_polypitch_gate.nx source
↩ module page · 134 lines · 4634 B
1// nx_polypitch_gate.nx -- REFEREE for LG-3 polyphony (nx_polypitch).
2//
3// Synthesizes chords as sums of pure sine tones and checks the detected NOTE SET:
4// single A3 (220) -> {57} (neg-control: 1 note, not a chord)
5// A major (220,277,330) -> {57,61,64} (A3, C#4, E4)
6// power chord (220,330) -> {57,64} (A3, E4)
7// C major (261,330,392) -> {60,64,67} (C4, E4, G4) -- different chord, different set
8//
9// Evidence -> stdout + knowledge/status/polypitch_gate.log. Exit 0 GREEN / 1 RED.
10// Sovereign x86_64 throughout. license_tier: ORIGINAL
11import "nx_syscalls_x86_64.nx"
12import "nx_polypitch.nx"
13import "nx_note.nx"
14
15const N: i64 = 1024
16const FS: i64 = 8000
17const MLO: i64 = 50
18const MHI: i64 = 72
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(acc: *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 < N {
50 acc[n] = acc[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}
57func make_chord(acc: *i64, buf: *u8, f1: i64, f2: i64, f3: i64) -> i64 {
58 var n: i64 = 0
59 while n < N { acc[n] = 0; n = n + 1 }
60 add_sine(acc, f1, AMP)
61 add_sine(acc, f2, AMP)
62 add_sine(acc, f3, AMP)
63 var mx: i64 = 1
64 n = 0
65 while n < N { 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 < N {
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 pdet(logfd: i64, label: *u8, det: *i64, cnt: i64) -> i64 {
80 gp(logfd, label)
81 gp(logfd, " detected=\x00" as *u8); gn(logfd, cnt); gp(logfd, " [\x00" as *u8)
82 var i: i64 = 0
83 while i < cnt { gn(logfd, det[i]); gp(logfd, " \x00" as *u8); i = i + 1 }
84 gp(logfd, "]\n\x00" as *u8)
85 return 0
86}
87
88func main() -> i64 {
89 let logfd: i64 = sys_openat_append("knowledge/status/polypitch_gate.log\x00" as *u8, 0x1a4)
90 gp(logfd, "POLYPITCH-GATE LG-3 (chords)\n\x00" as *u8)
91
92 let tbl: *i64 = sys_mmap(128 * 8) as *i64
93 nx_note_table(tbl)
94 let acc: *i64 = sys_mmap(N * 8) as *i64
95 let buf: *u8 = sys_mmap(N * 2)
96 let det: *i64 = sys_mmap(8 * 8) as *i64
97
98 var ok: i64 = 1
99
100 make_chord(acc, buf, 220, 0, 0)
101 let c1: i64 = nx_polypitch(buf, 0, N, FS, tbl, MLO, MHI, det, 8)
102 pdet(logfd, " single A3 \x00" as *u8, det, c1)
103 if c1 != 1 { ok = 0 }
104 if c1 >= 1 { if det[0] != 57 { ok = 0 } }
105
106 make_chord(acc, buf, 220, 277, 330)
107 let c2: i64 = nx_polypitch(buf, 0, N, FS, tbl, MLO, MHI, det, 8)
108 pdet(logfd, " A maj triad \x00" as *u8, det, c2)
109 if c2 != 3 { ok = 0 }
110 if c2 == 3 { if det[0] != 57 { ok = 0 } if det[1] != 61 { ok = 0 } if det[2] != 64 { ok = 0 } }
111
112 make_chord(acc, buf, 220, 330, 0)
113 let c3: i64 = nx_polypitch(buf, 0, N, FS, tbl, MLO, MHI, det, 8)
114 pdet(logfd, " power 5th \x00" as *u8, det, c3)
115 if c3 != 2 { ok = 0 }
116 if c3 == 2 { if det[0] != 57 { ok = 0 } if det[1] != 64 { ok = 0 } }
117
118 make_chord(acc, buf, 261, 330, 392)
119 let c4: i64 = nx_polypitch(buf, 0, N, FS, tbl, MLO, MHI, det, 8)
120 pdet(logfd, " C maj triad \x00" as *u8, det, c4)
121 if c4 != 3 { ok = 0 }
122 if c4 == 3 { if det[0] != 60 { ok = 0 } if det[1] != 64 { ok = 0 } if det[2] != 67 { ok = 0 } }
123
124 if ok == 1 {
125 gp(logfd, "POLYPITCH-GATE result=ALL-PASS verdict=GREEN\n\x00" as *u8)
126 if logfd > 0 { sys_close(logfd) }
127 sys_exit(0)
128 return 0
129 }
130 gp(logfd, "POLYPITCH-GATE result=FAIL verdict=RED\n\x00" as *u8)
131 if logfd > 0 { sys_close(logfd) }
132 sys_exit(1)
133 return 1
134}