code wiki / _hdl_build / nx_bioacoustic_bench.nx
nx_bioacoustic_bench.nx
buildroot/runtime/_hdl_build/nx_bioacoustic_bench.nx
about
nx_bioacoustic_bench.nx -- THE RULER for ANIMAL-VOCALISATION REALISM.
Operator 2026-07-25: "get nishi audio state of the art so we can generate animal sounds and a dog toy
ball that makes the noise when compressed by a dog's mouth". Rung R0. BEFORE any synthesis claim we
need a MEASURED NUMBER, because the only animal-sound organ that exists today (nx_audio_bark.nx) says
in its own header "First-iteration timbre -- tune by ear". Tuned by ear is not a measurement, and a
lane with no ruler cannot honestly say SOTA. This organ is that ruler.
WHY THESE AXES. A dog ignores TV animal sound because the signal fails on several acoustic axes at
once. Each axis below is one of those failure modes turned into a number that a real recording passes
and a synthetic/looped/broadcast one fails:
AX_BAND container bandwidth vs the DOG hearing band (dogs hear to ~60 kHz; 48 kHz media carries
24 kHz -- so a 48k file is PHYSICALLY INCAPABLE of >24 kHz no matter how good the synth).
AX_ULTRA fraction of energy above 20 kHz -- content a human cannot hear and a dog can.
AX_F0DYN pitch-contour movement (stddev of F0). Real calls sweep; a beep does not.
AX_HNR harmonic-to-noise proxy (normalised autocorrelation peak).
AX_NONLIN NONLINEAR PHENOMENA -- subharmonics, biphonation, deterministic chaos. This is the
hallmark of real mammalian/avian vocal production (the source self-oscillates and jumps
between regimes) and it is exactly what sample playback and hand-tuned oscillator banks
do not reproduce. Highest weight.
AX_NONREP non-repetition across successive segments. A looped sample cross-correlates ~1.0 with
itself; a real animal never repeats exactly. This is the HABITUATION axis.
AX_ATTACK envelope attack sharpness (transient realism).
AX_CREST crest factor = peak/RMS. Broadcast compression crushes this.
AX_RESON count of resonances (vocal-tract poles) in the long-term average spectrum.
AX_FLUX spectral micro-dynamics frame to frame. A static tone has none.
HONESTY DISCIPLINE. Every axis is reference-free and INTRINSIC -- it is a property of the signal
itself, so no reference corpus is needed to run it and no axis can be satisfied by simply copying a
reference. The ruler is only trustworthy if it REFUSES bad input, so nx_bioacoustic_bench_gate feeds
it negative controls (pure sine, white noise, an exactly-looped sample, a band-limited 48k signal) and
asserts each one scores LOW on the axes it should fail. A ruler that passes everything is a rubber
stamp, not an instrument. See [[feedback-cynical-instruments-author-optimism-is-a-bug]].
ANTI-GAMING NOTE ON AX_NONLIN. "Loud but aperiodic" alone is NOT evidence of nonlinear vocal
production -- white noise is loud and aperiodic. Real nonlinear phenomena are REGIME TRANSITIONS, so
a chaotic frame only counts when the same utterance also contains periodic frames. White noise has no
periodic frames, so it scores 0 here. That is the biology, and it is what makes the axis honest.
dependencies 3 imports · 1 importers
imports: nx_syscalls.nxnx_audio_osc.nxnx_isqrt.nx
imported by: nx_squeaker_design.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 55 | const BB_MAGIC_8000: i64 = 8000 |
| 56 | const BB_MAGIC_20000: i64 = 20000 |
| 57 | const BB_MAGIC_60000: i64 = 60000 |
| 58 | const BB_MAGIC_65536: i64 = 65536 |
| 59 | const BB_MAGIC_16777216: i64 = 16777216 |
| 60 | const BB_MAGIC_32768: i64 = 32768 |
| 61 | const BB_MAGIC_8388608: i64 = 8388608 |
| 62 | const BB_MAGIC_1024: i64 = 1024 |
| 63 | const BB_MAGIC_4096: i64 = 4096 |
| 64 | const BB_MAGIC_8192: i64 = 8192 |
| 65 | const BB_MAGIC_2000: i64 = 2000 |
| 66 | const BB_MAGIC_3000: i64 = 3000 |
| 69 | const BB_R_RATE: i64 = 0 |
| 70 | const BB_R_NSAMP: i64 = 1 |
| 71 | const BB_R_NCH: i64 = 2 |
| 72 | const BB_R_BITS: i64 = 3 |
| 73 | const BB_R_AX_BAND: i64 = 4 |
| 74 | const BB_R_AX_ULTRA: i64 = 5 |
| 75 | const BB_R_AX_F0DYN: i64 = 6 |
| 76 | const BB_R_AX_HNR: i64 = 7 |
| 77 | const BB_R_AX_NONLIN: i64 = 8 |
| 78 | const BB_R_AX_NONREP: i64 = 9 |
| 79 | const BB_R_AX_ATTACK: i64 = 10 |
| 80 | const BB_R_AX_CREST: i64 = 11 |
| 81 | const BB_R_AX_RESON: i64 = 12 |
| 82 | const BB_R_AX_FLUX: i64 = 13 |
| 83 | const BB_R_AX_VOCAL: i64 = 14 |
| 84 | const BB_R_SCORE: i64 = 15 |
| 85 | const BB_R_F0_MEAN: i64 = 16 |
| 86 | const BB_R_F0_SD: i64 = 17 |
| 87 | const BB_R_VOICED: i64 = 18 |
| 88 | const BB_R_FRAMES: i64 = 19 |
| 89 | const BB_R_ULTRAFRAC: i64 = 20 |
| 90 | const BB_R_CRESTX100: i64 = 21 |
| 91 | const BB_R_NRESON: i64 = 22 |
| 92 | const BB_R_XCORR: i64 = 23 |
| 93 | const BB_R_NL_SUBH: i64 = 24 |
| 94 | const BB_R_NL_BIPH: i64 = 25 |
| 95 | const BB_R_NL_CHAOS: i64 = 26 |
| 96 | const BB_R_NL_PERIOD: i64 = 27 |
| 97 | const BB_R_N: i64 = 28 |
| 100 | const BB_C_F0_MIN: i64 = 0 // Hz lowest tracked fundamental |
| 101 | const BB_C_F0_MAX: i64 = 1 // Hz highest tracked fundamental (mouse squeak fundamentals reach 8k) |
| 102 | const BB_C_VOICE_FLOOR: i64 = 2 // per-mille of peak frame energy above which a frame is "sounding" |
| 103 | const BB_C_F0SD_REF: i64 = 3 // Hz F0 stddev that scores 1000 |
| 104 | const BB_C_SUBH_LO: i64 = 4 // per-mille min correlation at P/2 to call it a subharmonic |
| 105 | const BB_C_SUBH_HI: i64 = 5 // per-mille max correlation at P/2 before it is just the true period |
| 106 | const BB_C_CHAOS_R: i64 = 6 // per-mille peak correlation below this = aperiodic regime |
| 107 | const BB_C_BIPH_R: i64 = 7 // per-mille min correlation for a second incommensurate peak |
| 108 | const BB_C_ULTRA_HZ: i64 = 8 // Hz boundary of the "human cannot hear, dog can" band |
| 109 | const BB_C_DOG_HZ: i64 = 9 // Hz upper edge of canine hearing -- the bandwidth target |
| 110 | const BB_C_ULTRA_REF: i64 = 10 // per-mille energy above ULTRA_HZ that scores 1000 |
| 111 | const BB_C_ATTACK_REF: i64 = 11 // per-mille envelope rise per frame that scores 1000 |
| 112 | const BB_C_CREST_FLOOR: i64 = 12 // crest x100 at which the axis starts scoring |
| 113 | const BB_C_CREST_REF: i64 = 13 // crest x100 that scores 1000 |
| 114 | const BB_C_RESON_REF: i64 = 14 // resonance count that scores 1000 |
| 115 | const BB_C_FLUX_REF: i64 = 15 // per-mille spectral flux that scores 1000 |
| 116 | const BB_C_PROM: i64 = 16 // per-mille of spectral max a peak must clear to count as a resonance |
| 117 | const BB_C_NSEG: i64 = 17 // segments compared for the non-repetition axis |
| 118 | const BB_C_W_BAND: i64 = 18 |
| 119 | const BB_C_W_ULTRA: i64 = 19 |
| 120 | const BB_C_W_F0DYN: i64 = 20 |
| 121 | const BB_C_W_HNR: i64 = 21 |
| 122 | const BB_C_W_NONLIN: i64 = 22 |
| 123 | const BB_C_W_NONREP: i64 = 23 |
| 124 | const BB_C_W_ATTACK: i64 = 24 |
| 125 | const BB_C_W_CREST: i64 = 25 |
| 126 | const BB_C_W_RESON: i64 = 26 |
| 127 | const BB_C_W_FLUX: i64 = 27 |
| 128 | const BB_C_W_VOCAL: i64 = 28 |
| 129 | const BB_C_N: i64 = 29 |
| 131 | const BB_MAXBAND: i64 = 64 |
| 132 | const BB_BANDRATIO: i64 = 77936 // 2^(1/4) in Q16 -- quarter-octave band bank |
| 133 | const BB_BAND_LO: i64 = 50 // Hz, lowest band centre (dog hearing floor is ~40 Hz) |
| 134 | const BB_Q: i64 = 65536 |
| 454 | const BB_MAXFRAME: i64 = 512 |
| 455 | const BB_ADJ: i64 = 2 // frames either side that count as "the same utterance" for regime switching |
| 459 | const BB_REG_SILENT: i64 = 0 |
| 460 | const BB_REG_PERIOD: i64 = 1 |
| 461 | const BB_REG_SUBH: i64 = 2 |
| 462 | const BB_REG_BIPH: i64 = 3 |
| 463 | const BB_REG_CHAOS: i64 = 4 |
functions
| 137 | func bb_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 138 | func bb_n(v: i64) -> i64 |
| 152 | func bb_kvpair(k: *u8, v: i64) -> i64 { bb_w(k); bb_n(v); bb_w(" " as *u8); return 0 } |
| 153 | func bb_iabs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } |
| 154 | func bb_min(a: i64, b: i64) -> i64 { if a < b { return a } return b } |
| 155 | func bb_max(a: i64, b: i64) -> i64 { if a > b { return a } return b } |
| 157 | func bb_axis(num: i64, ref: i64) -> i64 called by 1: bb_analyze |
| 168 | func bb_cfg_defaults(c: *i64) -> i64 called by 1: bb_cfg_load |
| 208 | func bb_load_ints(dst: *i64, cap: i64, path: *u8) -> i64 |
| 236 | func bb_cfg_load(c: *i64, path: *u8) -> i64 |
| 246 | func bb_rd_u16(b: *u8, o: i64) -> i64 { return (b[o] & 0xff) + ((b[o+1] & 0xff) * 256) } |
| 247 | func bb_rd_u32(b: *u8, o: i64) -> i64 called by 1: bb_wav_parse |
| 254 | func bb_tag4(b: *u8, o: i64, a: i64, c2: i64, c3: i64, c4: i64) -> i64 called by 1: bb_wav_parse |
| 261 | func bb_wav_parse(buf: *u8, flen: i64, meta: *i64) -> i64 |
| 299 | func bb_wav_decode(buf: *u8, meta: *i64, out: *i64, cap: i64) -> i64 |
| 329 | func bb_bands(rate: i64, centres: *i64) -> i64 called by 1: bb_analyze |
| 343 | func bb_goertzel(x: *i64, s: i64, m: i64, f: i64, rate: i64) -> i64 |
| 374 | func bb_acorr(x: *i64, s: i64, fn: i64, lag: i64, mean: i64) -> i64 |
| 417 | func bb_biph_frame(fpow: *i64, base: i64, centres: *i64, nb: i64, biph_r: i64) -> i64 |
| 467 | func bb_analyze(x: *i64, n: i64, rate: i64, nch: i64, bits: i64, c: *i64, res: *i64) -> i64 |
| 864 | func bb_measure_file(path: *u8, c: *i64, res: *i64) -> i64 |
| 881 | func bb_report(label: *u8, res: *i64) -> i64 |
| 914 | func main(argc: i64, argv: *i64) -> i64 |