code wiki / _hdl_build / nx_squeaker_design.nx
nx_squeaker_design.nx
buildroot/runtime/_hdl_build/nx_squeaker_design.nx
about
nx_squeaker_design.nx -- INVERT the toy model: given the sound you want and the dog that will bite
it, return a geometry somebody can mould. Rung R5, and the deliverable of the whole lane.
The forward model (nx_squeaker) turns geometry into sound. A product needs the other direction.
The Helmholtz law is invertible in closed form, which is why the model was written in millimetres
and newtons rather than in convenient normalised units:
f = (c / 2pi) * sqrt(A / (V * L)) -> A = (2*pi*f/c)^2 * V * L
and the bite sets the shell compliance, because compressing the chamber is what moves the pitch:
f_rest^2 / f_bitten^2 = V_bitten / V_rest = (V0 - dVdF * F) / V0
-> dVdF = V0 * (1 - (f_rest/f_bitten)^2) / F
So: pick the chamber volume and neck length from what is mouldable, and the neck area and the shell
compliance FALL OUT of the target sound and the dog's jaw. Different dogs get different shells for
the same sound -- a terrier and a mastiff biting the same geometry do not produce the same pitch, and
this is the organ that accounts for that.
SOLVED IS NOT VERIFIED. A closed-form solution can be arithmetically perfect and still describe an
object that does not work: the neck can come out too small to mould, the shell too soft to survive a
chew, the compression beyond what an elastomer will take. So every design is (1) solved, (2) checked
against manufacturing limits, and (3) RENDERED through the forward model and measured, with the
realised frequency reported next to the requested one. A design that is never rendered is a hope.
HONESTY ABOUT THE PREY TARGETS. The target frequencies below are DESIGN TARGETS taken from published
ranges for each prey class. They are NOT fitted to measured recordings, because this lane has no
licensed reference corpus yet -- see the gap filed against it. Nothing here should be read as
"matches a real rabbit"; it means "lands in the band that published work puts rabbit distress in".
The distinction matters, and collapsing it is how a lane starts believing its own brochure.
license_tier: ORIGINAL expect_exit: 0
dependencies 2 imports · 0 importers
imports: nx_squeaker.nxnx_bioacoustic_bench.nx
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 37 | const SQD_C: i64 = 343000 // speed of sound, mm/s |
| 38 | const SQD_TWOPI6: i64 = 6283185 // 2*pi * 1e6 |
| 42 | const SQD_A_MIN_X100: i64 = 200 // 2.00 mm^2 -- below this the neck will not mould or will clog |
| 43 | const SQD_A_MAX_X100: i64 = 20000 // 200.00 mm^2 |
| 44 | const SQD_V_MIN: i64 = 500 // mm^3 |
| 45 | const SQD_V_MAX: i64 = 120000 // mm^3 -- fits inside a 65 mm ball with wall thickness |
| 46 | const SQD_COMP_MAX_PM: i64 = 700 // per-mille of chamber volume an elastomer shell may give up |
| 49 | const SQD_R_V0: i64 = 0 |
| 50 | const SQD_R_AN_X100: i64 = 1 |
| 51 | const SQD_R_LN_X100: i64 = 2 |
| 52 | const SQD_R_DVDF100: i64 = 3 |
| 53 | const SQD_R_F_REST: i64 = 4 // realised, from the geometry |
| 54 | const SQD_R_F_BITE: i64 = 5 |
| 55 | const SQD_R_OK: i64 = 6 // 1 = manufacturable |
| 56 | const SQD_R_WHY: i64 = 7 // rejection code when OK = 0 |
| 57 | const SQD_R_N: i64 = 8 |
| 59 | const SQD_WHY_OK: i64 = 0 |
| 60 | const SQD_WHY_A_SMALL: i64 = 1 |
| 61 | const SQD_WHY_A_BIG: i64 = 2 |
| 62 | const SQD_WHY_V: i64 = 3 |
| 63 | const SQD_WHY_COMP: i64 = 4 |
| 64 | const SQD_WHY_TARGET: i64 = 5 |
functions
| 67 | func sqd_area_for(f: i64, vol: i64, ln_x100: i64) -> i64 called by 1: sqd_solve |
| 81 | func sqd_solve(f_rest: i64, f_bitten: i64, bite_n: i64, vol: i64, ln_x100: i64, rec: *i64) -> i64 calls 1: sqd_area_for |
| 112 | func sqd_to_params(rec: *i64, bite_n: i64, p: *i64) -> i64 calls 1: sq_defaults |
| 123 | func sqd_card(name: *u8, f_rest: i64, f_bitten: i64, bite_n: i64, rec: *i64, p: *i64) -> i64 |