// The parameters of the modal bank for the configuration currently being designed. // // A modes file is computed for one shape at a reference material and listener. The material and // the damping enter analytically (see precompute/pipeline.ts), so they are applied here, on every // slider move, without touching the eigensolve. The listener enters through the gains, which are // a separate and slower computation done in the worker. import type { SimulationConfig } from "./config/schema.ts"; import type { ModesData } from "./modes.ts"; export interface Derived { freq: Float64Array; // [Hz] sigma: Float64Array; // [1/s] phiFactor: number; // mode-shape rescaling for a density change overdamped: number; // modes whose loss had to be clamped below critical t60Low: number; // 60 dB decay of the lowest mode [s] t60High: number; // 60 dB decay of the highest mode [s] } export function derive(data: ModesData, cfg: SimulationConfig): Derived { const { E0, rho0 } = data.meta; const sE = cfg.material.E / E0, sRho = cfg.material.rho / rho0; const fScale = Math.sqrt(sE / sRho); const Nm = data.nModes; const freq = new Float64Array(Nm), sigma = new Float64Array(Nm); let overdamped = 0; for (let m = 0; m < Nm; m++) { const f = data.freq[m] * fScale; freq[m] = f; const s = cfg.material.sigma0 + cfg.material.sigma1 * data.dampQ[m]; const crit = 0.999 * 2 * Math.PI * f; if (s > crit) overdamped++; sigma[m] = Math.min(s, crit); } return { freq, sigma, phiFactor: 1 / Math.sqrt(sRho), overdamped, t60Low: 6.907755 / sigma[0], t60High: 6.907755 / sigma[Nm - 1], }; } /** The live quantities the gains depend on, as a comparable string. The gains are a sum over * elements at the mode frequencies, so they go stale when the listener moves and when the * material changes the frequencies. */ export function gainState(cfg: SimulationConfig): string { return JSON.stringify([cfg.material.E, cfg.material.rho, cfg.listener]); } /** The same string for the state a freshly loaded modes file was computed at. */ export function storedGainState(data: ModesData): string { const stored = data.meta.config as unknown as SimulationConfig; return JSON.stringify([data.meta.E0, data.meta.rho0, stored.listener]); }