/** * Harmonic analysis functions * * Provides: * - f0_harmonics - Extract energy at harmonics of fundamental frequency * - interp_harmonics - Interpolate harmonics from time-frequency representation * - salience - Compute harmonic salience function */ /** * Compute the energy at selected harmonics of a time-varying fundamental frequency * * @param {Array>} x - Time-frequency representation (e.g., spectrogram) [freq x time] * @param {Array} f0 - Fundamental frequency curve in Hz [time] * @param {Array} freqs - Frequency values for each row of x [freq] * @param {Array} harmonics - Harmonic numbers to extract (e.g., [1, 2, 3, 4, 5]) * @param {string} kind - Interpolation type ('linear', 'nearest', 'cubic') * @param {number} fill_value - Value for out-of-bounds harmonics * @param {number} axis - Frequency axis (default: -2, i.e., first axis) * @returns {Array>} Energy at harmonics [n_harmonics x time] */ export function f0_harmonics(x: Array>, f0: Array, freqs: Array, harmonics: Array, kind?: string, fill_value?: number, axis?: number): Array>; /** * Compute the energy at harmonics of a time-frequency representation * * Similar to f0_harmonics, but harmonics are constant multiples rather than * varying with a fundamental frequency curve. * * @param {Array>} x - Time-frequency representation [freq x time] * @param {Array} freqs - Frequency values [freq] * @param {Array} harmonics - Harmonic ratios to extract * @param {string} kind - Interpolation type * @param {number} fill_value - Fill value for out-of-bounds * @param {number} axis - Frequency axis * @returns {Array>} Harmonic energies [n_harmonics x freq x time] */ export function interp_harmonics(x: Array>, freqs: Array, harmonics: Array, kind?: string, fill_value?: number, axis?: number): Array>; /** * Compute the harmonic salience function * * Salience measures how well the energy distribution matches a harmonic * template: aggregate (default: weighted MEAN, np.average) of the energy at * each bin's harmonics, then — when filter_peaks is true — keep salience only * where the ORIGINAL spectrogram has a local maximum along the FREQUENCY axis * (scipy.signal.argrelmax(S, axis=-2)); all other positions get fill_value. * * Tier-2 repair note (2026-07-02): the previous implementation filtered each * harmonic-energy row for local maxima along the TIME axis and aggregated by * weighted SUM — diverging whenever filter_peaks=true (the * default). Repaired to frequency-axis peaks of S + weighted average. * * @param {Array>} S - Spectrogram or time-frequency representation [freq x time] * @param {Array} freqs - Frequency values [freq] * @param {Array} harmonics - Harmonic numbers to consider [1, 2, 3, ...] * @param {Array|null} weights - Weights for each harmonic (default: null, uniform) * @param {Function|null} aggregate - Aggregation fn(values, weights) per bin * (default: null, weighted average like np.average — NaN propagates) * @param {boolean} filter_peaks - Keep only frequency-axis peaks of S (default: true) * @param {number} fill_value - Value for filtered-out / out-of-bounds bins (default: NaN) * @param {string} kind - Interpolation type * @param {number} axis - Frequency axis * @returns {Array>} Salience function [freq x time] */ export function salience(S: Array>, freqs: Array, harmonics: Array, weights?: Array | null, aggregate?: Function | null, filter_peaks?: boolean, fill_value?: number, kind?: string, axis?: number): Array>; /** * Harmonic interpolation helper - static frequency grid * Equivalent to the _f_interps nested function * * Interpolates data at target frequencies, filtering out non-finite frequencies * * @private * @param {Array} data - Data values to interpolate [n_freqs] * @param {Array} freqs - Frequency grid [n_freqs] * @param {Array} target_freqs - Target frequencies to interpolate at * @param {string} kind - Interpolation type ('linear', 'nearest', 'cubic') * @param {number} fill_value - Fill value for out-of-bounds * @returns {Array} Interpolated values at target frequencies */ export function _f_interps(data: Array, freqs: Array, target_freqs: Array, kind?: string, fill_value?: number): Array; /** * Harmonic interpolation helper - dynamic frequency grid * Equivalent to the _f_interpd nested function * * Interpolates data at target frequencies using a dynamic (per-frame) frequency grid * * @private * @param {Array} data - Data values to interpolate [n_points] * @param {Array} frequencies - Frequency grid (can vary per frame) [n_points] * @param {Array} target_freqs - Target frequencies to interpolate at * @param {string} kind - Interpolation type ('linear', 'nearest', 'cubic') * @param {number} fill_value - Fill value for out-of-bounds * @returns {Array} Interpolated values at target frequencies */ export function _f_interpd(data: Array, frequencies: Array, target_freqs: Array, kind?: string, fill_value?: number): Array; /** * Harmonic interpolation - outer product variant * Equivalent to the _f_interp nested function * * Interpolates using outer product of frequencies with harmonics * Used in interp_harmonics for computing harmonic energy across frequency grid * * @private * @param {Array} freqs - Base frequency grid [n_freqs] * @param {Array} data - Data values [n_freqs] * @param {Array} harmonics - Harmonic multipliers (e.g., [0.5, 1, 2, 3]) * @param {string} kind - Interpolation type ('linear', 'nearest', 'cubic') * @param {number} fill_value - Fill value for out-of-bounds * @returns {Array>} Interpolated harmonic data [n_freqs x n_harmonics] */ export function _f_interp(freqs: Array, data: Array, harmonics: Array, kind?: string, fill_value?: number): Array>; /** * Compute harmonic product spectrum (HPS) for pitch detection * * Helper function that can be used with salience for robust pitch detection. * * @param {Array} spectrum - Magnitude spectrum * @param {number} n_harmonics - Number of harmonics to multiply * @returns {Array} Harmonic product spectrum */ export function harmonic_product_spectrum(spectrum: Array, n_harmonics?: number): Array; /** * Compute harmonic sum spectrum (HSS) for pitch detection * * Alternative to HPS that sums instead of multiplies harmonics. * * @param {Array} spectrum - Magnitude spectrum * @param {number} n_harmonics - Number of harmonics to sum * @param {Array|null} weights - Weights for each harmonic * @returns {Array} Harmonic sum spectrum */ export function harmonic_sum_spectrum(spectrum: Array, n_harmonics?: number, weights?: Array | null): Array;