/** * Create an incremental RMS meter. * * Emits one RMS value per complete frame: * rms = sqrt(mean(frame^2)) * For a steady sine of amplitude g, RMS ≈ g / sqrt(2). * * @param {Object} [opts] * @param {number} [opts.frameSize=2048] - samples per analysis frame * @param {number} [opts.hop=512] - samples between successive frames * @returns {{ * push: (chunk: Float32Array) => number[], * read: () => {current: number|null, frameCount: number, pendingSamples: number}, * reset: () => void, * }} push() returns the RMS values newly completed by this chunk; read() * reports the most recent value and totals without consuming anything. */ export function createRmsMeter({ frameSize, hop }?: { frameSize?: number; hop?: number; }): { push: (chunk: Float32Array) => number[]; read: () => { current: number | null; frameCount: number; pendingSamples: number; }; reset: () => void; }; /** * Create an incremental spectral-flux analyzer. * * Each complete frame is Hann-windowed and transformed (nFft-point FFT); * flux is the sum of positive magnitude increases versus the previous * frame's spectrum: * flux[t] = sum_k max(0, |X_t[k]| - |X_{t-1}[k]|) * The first frame has no predecessor and reports flux 0. Flux spikes at * energy/amplitude onsets (e.g. an amplitude step in the input). * * @param {Object} [opts] * @param {number} [opts.nFft=2048] - frame/FFT size in samples * @param {number} [opts.hop=512] - samples between successive frames * @returns {{ * push: (chunk: Float32Array) => number[], * read: () => {current: number|null, frameCount: number, pendingSamples: number}, * reset: () => void, * }} push() returns the flux values newly completed by this chunk; read() * reports the most recent value and totals without consuming anything. */ export function createFluxAnalyzer({ nFft, hop }?: { nFft?: number; hop?: number; }): { push: (chunk: Float32Array) => number[]; read: () => { current: number | null; frameCount: number; pendingSamples: number; }; reset: () => void; };