/ proof-of-concept / cymplay
Sign in
proof-of-concept / cymplay
cymplay / src / derived.ts
52 lines · 2.2 KBBlameHistoryRaw
1// The parameters of the modal bank for the configuration currently being designed.
2//
3// A modes file is computed for one shape at a reference material and listener. The material and
4// the damping enter analytically (see precompute/pipeline.ts), so they are applied here, on every
5// slider move, without touching the eigensolve. The listener enters through the gains, which are
6// a separate and slower computation done in the worker.
7import type { SimulationConfig } from "./config/schema.ts";
8import type { ModesData } from "./modes.ts";
10export interface Derived {
11 freq: Float64Array; // [Hz]
12 sigma: Float64Array; // [1/s]
13 phiFactor: number; // mode-shape rescaling for a density change
14 overdamped: number; // modes whose loss had to be clamped below critical
15 t60Low: number; // 60 dB decay of the lowest mode [s]
16 t60High: number; // 60 dB decay of the highest mode [s]
19export function derive(data: ModesData, cfg: SimulationConfig): Derived {
20 const { E0, rho0 } = data.meta;
21 const sE = cfg.material.E / E0, sRho = cfg.material.rho / rho0;
22 const fScale = Math.sqrt(sE / sRho);
23 const Nm = data.nModes;
24 const freq = new Float64Array(Nm), sigma = new Float64Array(Nm);
25 let overdamped = 0;
26 for (let m = 0; m < Nm; m++) {
27 const f = data.freq[m] * fScale;
28 freq[m] = f;
29 const s = cfg.material.sigma0 + cfg.material.sigma1 * data.dampQ[m];
30 const crit = 0.999 * 2 * Math.PI * f;
31 if (s > crit) overdamped++;
32 sigma[m] = Math.min(s, crit);
33 }
34 return {
35 freq, sigma, phiFactor: 1 / Math.sqrt(sRho), overdamped,
36 t60Low: 6.907755 / sigma[0],
37 t60High: 6.907755 / sigma[Nm - 1],
38 };
41/** The live quantities the gains depend on, as a comparable string. The gains are a sum over
42 * elements at the mode frequencies, so they go stale when the listener moves and when the
43 * material changes the frequencies. */
44export function gainState(cfg: SimulationConfig): string {
45 return JSON.stringify([cfg.material.E, cfg.material.rho, cfg.listener]);
48/** The same string for the state a freshly loaded modes file was computed at. */
49export function storedGainState(data: ModesData): string {
50 const stored = data.meta.config as unknown as SimulationConfig;
51 return JSON.stringify([data.meta.E0, data.meta.rho0, stored.listener]);
↑↓ move↵openescclose