// The interface shared by the CPU and the GPU time loops, extended (relative to cymsimweb) with // modal drive and projection: a backend can start from a prescribed state, apply a distributed // harmonic force, and return snapshots of the state projected onto a set of transverse modes. export interface ChunkResult { firstSample: number; // audio index of pressureFront[0] pressureFront: Float32Array; // baffled Rayleigh pressure [Pa] pressureBack: Float32Array; // diffracted back term [Pa]; unbaffled = front - back frames: Float32Array[]; // displacement w at every node, captured every `movieEvery` audio samples frameSamples: number[]; // audio sample index of each frame proj: Float32Array[]; // modal snapshots (2 Nm each: q_m then qdot_m), every `projEvery` audio samples projSamples: number[]; // audio sample index of each modal snapshot trace: Float32Array; // one mode's coordinate q_m at every audio sample (empty when off) traceBase: number; // audio sample index of trace[0] } export interface HitState { peakForce: number; contactTime: number; velocity: number; height: number } export interface Diagnostics { time: number; kinetic: number; membrane: number; bending: number; exciters: number; maxWoverH: number; hits: HitState[]; } /** A distributed transverse drive f_w(n, t) = fNode[n] * env(t) * sin(omega t), env a linear ramp * over rampSteps sub-steps, cut off at stopStep. fNode is in Newtons per node. */ export interface DriveParams { fNode: Float64Array; // (N,) nodal force amplitudes on w omega: number; // [rad/s] rampSteps: number; // sub-steps of the linear onset ramp (>= 1) stopStep: number; // first sub-step at which the drive is off } /** Projection of the running state onto Nm transverse modes: q_m = sum_n phiM[m N + n] w_n and * the same sum over the velocities. phiM is the mass-weighted mode matrix (mode-major), so with * mass-normalised shapes the q_m are the modal coordinates. */ export interface ProjectionSpec { phiM: Float32Array; // (Nm, N) mode-major, phi_m(n) * Mw(n) nModes: number; every: number; // audio samples between snapshots } export interface BackendOptions { movieEvery?: number; // > 0 captures w every that many audio samples drive?: DriveParams; projection?: ProjectionSpec; /** Mode whose coordinate is captured at the full audio rate (needs `projection`), so its true * oscillation frequency, unlike the energy envelopes, can be read off an STFT. */ traceMode?: number; } export interface SimulatorBackend { readonly kind: "cpu" | "gpu"; readonly samplesDone: number; /** Largest chunk (audio samples) runChunk accepts. */ readonly maxChunk: number; /** Set the state before the run: q and v are (5 N) node-major (u, v, w, thx, thy). */ setState(q: Float64Array, v: Float64Array): void; /** Advance by nSamples audio samples and return the pressure samples completed meanwhile. */ runChunk(nSamples: number): Promise; diagnostics(): Promise; /** Transverse displacement w at every node, for the plate view. */ displacement(): Promise; dispose(): void; }