code wiki / _hdl_build / nx_birdsynth.nx
nx_birdsynth.nx
buildroot/runtime/_hdl_build/nx_birdsynth.nx
about
nx_birdsynth.nx -- SOVEREIGN BAND-LIMITED BIRD-CALL EMITTER (the SKU-2 signal source).
Operator: a remote-controlled toy that emits "exact replicas of bird noises based on bird calls".
The estate already owns the RULER for that claim -- nx_bioacoustic_bench scores animal-vocalisation
realism on ten axes to a per-mille. What it did not own was anything to MEASURE: the only wavs in
the corpus are nx_gamemusic.wav and sfx_demo.wav. ★A RULER WITH NOTHING TO MEASURE IS A COMMENT.
This organ closes that loop -- emit, measure, iterate -- and the same PCM it writes is what the
toy's DAC will eventually clock out.
WHY SYNTHESIS AND NOT A SAMPLE. A recording, looped, fails the bench on the axis that matters most:
`nonrep`. Real animals never repeat exactly (breath-driven micro-variation), and a dog's habituation
is driven precisely by detecting the repeat. So the emitter is GENERATIVE -- per-syllable phase
jitter from an LCG means no two utterances are sample-identical -- which is a property a sample
player structurally cannot have.
★★BAND-LIMITED ON PURPOSE, AND THAT IS THE WHOLE EXPERIMENT. A harmonic is synthesised ONLY while
k*f0 < rate/2. That is correct DSP (no aliasing), and it makes the frequency-cutoff thesis MEASURABLE
instead of asserted: render the SAME call at 96 kHz and at 22.05 kHz and the low-rate render cannot
carry the upper partials AT ALL -- not "quieter", ABSENT. The bench's ax_ultra / ax_band axes then
report that difference as a number. Consumer audio does not fail a dog by being low quality; it fails
by being structurally incapable of representing the signal.
INTEGER-ONLY (sovereign no-float law). Sine comes from a 65-entry quarter-wave table filled at
runtime and mirrored into four quadrants. The table is mmap'd and filled by assignment, NEVER a
module-level const array -- a const array here compiles clean and then reads garbage (banked gotcha),
and a BSS [N]i64 silently crashes a handler module on startup.
usage: nx_birdsynth <out.wav> <rate_hz> <ms> [seed]
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 1 imports · 0 importers
imports: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 31 | const BS_MAGIC_1224: i64 = 1224 |
| 32 | const BS_MAGIC_1467: i64 = 1467 |
| 33 | const BS_MAGIC_1710: i64 = 1710 |
| 34 | const BS_MAGIC_1951: i64 = 1951 |
| 35 | const BS_MAGIC_2191: i64 = 2191 |
| 36 | const BS_MAGIC_2430: i64 = 2430 |
| 37 | const BS_MAGIC_2667: i64 = 2667 |
| 38 | const BS_MAGIC_2903: i64 = 2903 |
| 39 | const BS_MAGIC_3137: i64 = 3137 |
| 40 | const BS_MAGIC_3369: i64 = 3369 |
| 41 | const BS_MAGIC_3599: i64 = 3599 |
| 42 | const BS_MAGIC_3827: i64 = 3827 |
| 43 | const BS_MAGIC_4052: i64 = 4052 |
| 44 | const BS_MAGIC_4276: i64 = 4276 |
| 45 | const BS_MAGIC_4496: i64 = 4496 |
| 46 | const BS_MAGIC_4714: i64 = 4714 |
| 47 | const BS_MAGIC_4929: i64 = 4929 |
| 48 | const BS_MAGIC_5141: i64 = 5141 |
| 49 | const BS_MAGIC_5350: i64 = 5350 |
| 50 | const BS_MAGIC_5556: i64 = 5556 |
| 51 | const BS_MAGIC_5758: i64 = 5758 |
| 52 | const BS_MAGIC_5957: i64 = 5957 |
| 53 | const BS_MAGIC_6152: i64 = 6152 |
| 54 | const BS_MAGIC_6344: i64 = 6344 |
| 55 | const BS_MAGIC_6532: i64 = 6532 |
| 56 | const BS_MAGIC_6716: i64 = 6716 |
| 57 | const BS_MAGIC_6895: i64 = 6895 |
| 58 | const BS_MAGIC_7071: i64 = 7071 |
| 59 | const BS_MAGIC_7242: i64 = 7242 |
| 60 | const BS_MAGIC_7410: i64 = 7410 |
| 61 | const BS_MAGIC_7572: i64 = 7572 |
| 62 | const BS_MAGIC_7730: i64 = 7730 |
| 63 | const BS_MAGIC_7883: i64 = 7883 |
| 64 | const BS_MAGIC_8032: i64 = 8032 |
| 65 | const BS_MAGIC_8176: i64 = 8176 |
| 66 | const BS_MAGIC_8315: i64 = 8315 |
| 67 | const BS_MAGIC_8449: i64 = 8449 |
| 68 | const BS_MAGIC_8577: i64 = 8577 |
| 69 | const BS_MAGIC_8701: i64 = 8701 |
| 70 | const BS_MAGIC_8819: i64 = 8819 |
| 71 | const BS_MAGIC_8932: i64 = 8932 |
| 72 | const BS_MAGIC_9040: i64 = 9040 |
| 73 | const BS_MAGIC_9142: i64 = 9142 |
| 74 | const BS_MAGIC_9239: i64 = 9239 |
| 75 | const BS_MAGIC_9330: i64 = 9330 |
| 76 | const BS_MAGIC_9415: i64 = 9415 |
| 77 | const BS_MAGIC_9495: i64 = 9495 |
| 78 | const BS_MAGIC_9569: i64 = 9569 |
| 79 | const BS_MAGIC_9638: i64 = 9638 |
| 80 | const BS_MAGIC_9700: i64 = 9700 |
| 81 | const BS_MAGIC_9757: i64 = 9757 |
| 82 | const BS_MAGIC_9808: i64 = 9808 |
| 83 | const BS_MAGIC_9853: i64 = 9853 |
| 84 | const BS_MAGIC_9892: i64 = 9892 |
| 85 | const BS_MAGIC_9925: i64 = 9925 |
| 86 | const BS_MAGIC_9952: i64 = 9952 |
| 87 | const BS_MAGIC_9973: i64 = 9973 |
| 88 | const BS_MAGIC_9988: i64 = 9988 |
| 89 | const BS_MAGIC_9997: i64 = 9997 |
| 90 | const BS_MAGIC_10000: i64 = 10000 |
| 91 | const BS_MAGIC_1103515245: i64 = 1103515245 |
| 92 | const BS_MAGIC_12345: i64 = 12345 |
| 93 | const BS_MAGIC_8000: i64 = 8000 |
| 94 | const BS_MAGIC_2600: i64 = 2600 |
| 95 | const BS_MAGIC_2000: i64 = 2000 |
| 96 | const BS_MAGIC_2400: i64 = 2400 |
| 97 | const BS_MAGIC_240000: i64 = 240000 |
| 98 | const BS_MAGIC_8500: i64 = 8500 |
| 99 | const BS_MAGIC_20000: i64 = 20000 |
| 100 | const BS_MAGIC_2001: i64 = 2001 |
| 101 | const BS_MAGIC_65536: i64 = 65536 |
| 102 | const BS_MAGIC_100000: i64 = 100000 |
| 103 | const BS_MAGIC_32000: i64 = 32000 |
| 104 | const BS_MAGIC_65535: i64 = 65535 |
| 106 | const BS_TABN: i64 = 65 // quarter wave, 0..64 inclusive = 0..90 degrees |
| 107 | const BS_AMP: i64 = 10000 // sine full-scale (integer) |
| 108 | const BS_PHONE: i64 = 16777216 // one full cycle in phase units (256 table steps << 16) |
| 109 | const BS_MAXH: i64 = 8 // harmonics considered |
| 110 | const BS_MAXMS: i64 = 4000 |
| 111 | const BS_MAXRATE: i64 = 192000 |
| 112 | const BS_HDR: i64 = 44 |
functions
| 114 | func bw(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } |
| 115 | func bs_atoi(s: *u8) -> i64 called by 1: main |
| 127 | func bs_num(out: *u8, o: i64, v: i64) -> i64 called by 1: main |
| 139 | func bs_lit(out: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { out[o + i] = s[i]; i = i + 1 } return o + i } called by 1: main |
| 142 | func bs_fill_table(t: *i64) -> i64 called by 1: main |
| 156 | func bs_sin(t: *i64, idx: i64) -> i64 called by 1: main |
| 166 | func bs_lcg(s: i64) -> i64 { return ((s * BS_MAGIC_1103515245) + BS_MAGIC_12345) & 0x7FFFFFFF } called by 1: main |
| 169 | func bs_u32(b: *u8, o: i64, v: i64) -> i64 called by 1: main |
| 176 | func bs_u16(b: *u8, o: i64, v: i64) -> i64 called by 1: main |
| 181 | func bs_tag(b: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while i < 4 { b[o+i] = s[i]; i = i + 1 } return o + 4 } called by 1: main |
| 183 | func main(argc: i64, argv: *i64) -> i64 |