code wiki / _hdl_build / nx_audio_bark.nx
nx_audio_bark.nx source
↩ module page · 143 lines · 5980 B
1// nx_audio_bark.nx -- dog BARK + GROWL via SOURCE-FILTER synthesis, COMPOSED from the canonical engine (operator
2// 2026-06-24: dedup must ABSORB capabilities + keep the most s-class). The formant source-filter (pitched glottal
3// pulse train -> driven formant-resonator bandpasses) is the NEW capability this organ keeps. DEDUP: cosine now
4// comes from nx_audio_osc.osc_cos_s (one cosine), and the growl rasp uses nx_audio_sfx.sfx_noise (xorshift -- the
5// engine's good noise, replacing this organ's old inferior LCG). 48kHz, peak-normalized no-clip, lossless PCM.
6// First-iteration timbre -- tune by ear. license_tier: ORIGINAL expect_exit: 0
7import "nx_audio_osc.nx" // osc_cos_s (deduped cosine for the formant pole)
8import "nx_audio_sfx.nx" // sfx_noise (xorshift noise -- replaces the old LCG)
9import "nx_audio_wav.nx" // wav_render_stereo, wav_save
10const K_MAGIC_411774: i64 = 411774
11const K_MAGIC_62915: i64 = 62915
12const K_MAGIC_1700: i64 = 1700
13const K_MAGIC_2600: i64 = 2600
14const K_MAGIC_60000: i64 = 60000
15const K_MAGIC_7777: i64 = 7777
16const K_MAGIC_1100: i64 = 1100
17
18const SR: i64 = 48000
19const NS: i64 = 48000 // 1.0 s
20const AMP: i64 = 12000
21
22func bp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
23func bpn(v: i64) -> i64 {
24 let b: *u8 = sys_mmap(28); var x: i64=v
25 if x<0 { b[0]=45; sys_write(1,b,1); x=0-x }
26 if x==0 { b[0]=48; sys_write(1,b,1); return 0 }
27 var d: i64=0; var y: i64=x; while y>0 { d=d+1; y=y/10 }
28 var i: i64=d-1; y=x; while i>=0 { b[i]=(48+(y%10)) as u8; y=y/10; i=i-1 }
29 sys_write(1,b,d); return 0
30}
31func b_abs(v: i64) -> i64 { if v<0 { return 0-v } return v }
32
33// driven 2nd-order bandpass at F Hz (r = pole radius, Q16); ADD output into acc[]. Cosine via the canonical osc_cos_s.
34func add_formant(acc: *i64, src: *i64, n: i64, F: i64, r: i64) -> i64 {
35 let om: i64 = (K_MAGIC_411774 * F) / SR
36 let c: i64 = osc_cos_s(om)
37 let a1: i64 = (2 * r * c) >> 16
38 let a2: i64 = (r * r) >> 16
39 var y1: i64 = 0; var y2: i64 = 0
40 var i: i64 = 0
41 while i < n {
42 let yn: i64 = ((a1 * y1) >> 16) - ((a2 * y2) >> 16) + src[i]
43 acc[i] = acc[i] + yn
44 y2 = y1; y1 = yn
45 i = i + 1
46 }
47 return 0
48}
49func clr(a: *i64, n: i64) -> i64 { var i: i64=0; while i<n { a[i]=0; i=i+1 } return 0 }
50func peak(a: *i64, n: i64) -> i64 { var m: i64=0; var i: i64=0; while i<n { let v: i64=b_abs(a[i]); if v>m{m=v} i=i+1 } return m }
51func normalize(a: *i64, n: i64) -> i64 {
52 let pk: i64 = peak(a, n); if pk == 0 { return 0 }
53 var i: i64 = 0; while i < n { a[i] = a[i] * AMP / pk; i = i + 1 }
54 return pk
55}
56func env(a: *i64, n: i64) -> i64 {
57 let at: i64 = n/12; let dc: i64 = n/2
58 var i: i64 = 0
59 while i < n {
60 var e: i64 = 256
61 if i < at { if at>0 { e = 256*i/at } }
62 if i > n-dc { if dc>0 { e = 256*(n-i)/dc } }
63 a[i] = (a[i] * e) >> 8
64 i = i + 1
65 }
66 return 0
67}
68func build_woof(acc: *i64, src: *i64, wn: i64) -> i64 {
69 clr(acc, wn); clr(src, wn)
70 var i: i64 = 0; var nxt: i64 = 0
71 while i < wn {
72 let pitch: i64 = 340 - (80 * i) / wn
73 let period: i64 = SR / pitch
74 if i >= nxt { src[i] = 300; nxt = i + period }
75 i = i + 1
76 }
77 add_formant(acc, src, wn, 600, K_MAGIC_62915)
78 add_formant(acc, src, wn, K_MAGIC_1700, K_MAGIC_62915)
79 add_formant(acc, src, wn, K_MAGIC_2600, K_MAGIC_60000)
80 env(acc, wn)
81 return 0
82}
83func save_wav(L: *i64, R: *i64, path: *u8) -> i64 {
84 let wavbuf: *u8 = sys_mmap(44 + NS*4 + 64)
85 let wlen: i64 = wav_render_stereo(L, R, NS, SR, wavbuf)
86 return wav_save(path, wavbuf, wlen)
87}
88
89func main() -> i64 {
90 bp("nx_audio_bark: source-filter BARK + GROWL composed from osc_cos_s + sfx_noise (deduped), 48kHz\n" as *u8)
91 let acc: *i64 = sys_mmap(NS*8) as *i64
92 let src: *i64 = sys_mmap(NS*8) as *i64
93 let nz: *i64 = sys_mmap(NS*8) as *i64
94 let R: *i64 = sys_mmap(NS*8) as *i64
95 var ok: i64 = 0
96
97 // BARK: two woofs ("wuff-wuff")
98 clr(acc, NS)
99 let wn: i64 = SR*22/100
100 let woof: *i64 = sys_mmap(NS*8) as *i64
101 let wsrc: *i64 = sys_mmap(NS*8) as *i64
102 build_woof(woof, wsrc, wn)
103 var i: i64 = 0; let o1: i64 = SR/20
104 while i < wn { acc[o1+i] = woof[i]; i = i + 1 }
105 let o2: i64 = o1 + wn + SR*9/100
106 i = 0; while i < wn { if o2+i < NS { acc[o2+i] = woof[i] } i = i + 1 }
107 normalize(acc, NS)
108 i = 0; while i < NS { R[i] = acc[i]; i = i + 1 }
109 let sb: i64 = save_wav(acc, R, "web_assets/ng_dog_bark.wav\x00" as *u8)
110 bp(" bark peak=" as *u8); bpn(peak(acc,NS)); bp(" bytes=" as *u8); bpn(sb); bp("\n" as *u8); if sb>44 { if peak(acc,NS)>1000 { ok=ok+1 } }
111
112 // GROWL: low glottal buzz + xorshift noise (sfx_noise) through 2 formants + triangle roughness
113 clr(acc, NS); clr(src, NS)
114 sfx_noise(nz, NS, 60, K_MAGIC_7777)
115 i = 0; var gnxt: i64 = 0
116 while i < NS {
117 if i >= gnxt { src[i] = src[i] + 260; gnxt = i + SR/95 }
118 src[i] = src[i] + nz[i]
119 i = i + 1
120 }
121 add_formant(acc, src, NS, 380, K_MAGIC_62915)
122 add_formant(acc, src, NS, K_MAGIC_1100, K_MAGIC_60000)
123 let amp_per: i64 = SR / 28
124 i = 0
125 while i < NS {
126 let ph: i64 = i % amp_per
127 var tri: i64 = ph * 512 / amp_per
128 if tri > 256 { tri = 512 - tri }
129 let amf: i64 = 110 + (tri * 146) / 256
130 acc[i] = (acc[i] * amf) >> 8
131 i = i + 1
132 }
133 env(acc, NS)
134 normalize(acc, NS)
135 i = 0; while i < NS { R[i] = acc[i]; i = i + 1 }
136 let sg: i64 = save_wav(acc, R, "web_assets/ng_dog_growl.wav\x00" as *u8)
137 bp(" growl peak=" as *u8); bpn(peak(acc,NS)); bp(" bytes=" as *u8); bpn(sg); bp("\n" as *u8); if sg>44 { if peak(acc,NS)>1000 { ok=ok+1 } }
138
139 bp(" verdict=" as *u8)
140 if ok == 2 { bp("GREEN (bark+growl via formant + deduped osc_cos_s/sfx_noise, 48kHz, normalized lossless)\n" as *u8); sys_exit(0); return 0 }
141 bp("RED\n" as *u8)
142 sys_exit(1); return 1
143}