/** * Compute chroma features from audio buffer * @returns {Float32Array[]} 12 chroma rows × numFrames columns (empty array if * the buffer is too short for a single frame) */ export function computeChroma(audioBuffer: any, hopLength?: number): Float32Array[]; /** * Time-delay embedding to stack chroma features. * Accepts rows as plain arrays or typed arrays (Float32Array). */ export function stackMemory(chroma: any, nSteps?: number, delay?: number): Float32Array[]; /** * Proper recurrence matrix (xa-style) */ export function recurrenceMatrix(data: any, k?: any, width?: number, metric?: string, sym?: boolean, axis?: number, sparse?: boolean, mode?: string, bandwidth?: any, hop_length?: number, win_length?: any): Float32Array[]; /** * Convert recurrence matrix to lag representation (xa-style). * Accepts rows as plain arrays or typed arrays. */ export function recurrenceToLag(recurrence: any, pad?: boolean, axis?: number): Float32Array[]; /** * Convert frames to time (xa-style) */ export function framesToTime(frames: any, hopLength?: number, sr?: number): number | number[]; /** * Find peaks in lag matrix to identify loop-lag candidates. * * Lag strengths are normalized by the number of frame positions that can * contribute at each lag (numFrames − lag). Without this, raw lag sums decay * linearly with lag and real repetition peaks drown in the ramp (Wave 3 fix). * * @param {Float32Array[]} lagMatrix - output of recurrenceToLag * @param {number} [frameTime] - seconds per lag step * @param {number} [numFrames] - frames in the ORIGINAL (unpadded) recurrence * matrix; defaults to lagMatrix.length / 2 (i.e., assumes pad=true) */ export function findLoopCandidates(lagMatrix: Float32Array[], frameTime?: number, numFrames?: number): { lagFrames: number; lagSeconds: number; strength: number; }[]; /** * Recurrence loop detection using matrix analysis. * * Returns REAL candidates validated against the raw audio, or THROWS a * diagnostic error. There are no fabricated fallbacks: every returned * confidence is the normalized cross-correlation (0..1) between the candidate * loop segment and the audio that follows it. * * Cost note: the similarity matrix is O(frames² × features). For long buffers * the hop length is scaled up (documented in `diagnostics.hopLength`) so that * frame count stays under `maxFrames` — a resolution trade within the same * algorithm, never a switch to a different strategy. * * @param {AudioBuffer|Object} audioBuffer - AudioBuffer or shim with getChannelData * @param {Object} [options] * @param {number} [options.hopLength=512] * @param {number} [options.maxFrames=1500] - cap on chroma frames (matrix is frames²) * @param {number} [options.minConfidence=0.1] - quality gate on audio-validated NCC * @returns {Promise} { loopStart, loopEnd, confidence, candidates, diagnostics } */ export function recurrenceLoopDetection(audioBuffer: AudioBuffer | any, options?: { hopLength?: number; maxFrames?: number; minConfidence?: number; }): Promise;