/** * Chunked audio reader (NOT true streaming — honesty note, 2026-07-02). * * The whole source is decoded up front via decodeAudioData, then yielded in * fixed-size sample windows: each block is `blockLength` SAMPLES and the * window advances by `hopLength` samples, so blockLength > hopLength yields * OVERLAPPING blocks. This is a simplified streaming contract — a true * frame-based streamer would count block_length in FRAMES of * frameLength/hopLength each and read incrementally. Memory use is O(file), * not O(block). For live input use createMediaStreamProcessor instead. * * With blockLength === hopLength the blocks are non-overlapping and lossless: * ceil(N / blockLength) blocks whose concatenation reproduces the decoded * source exactly (proof: examples/web/file-io.html). * * @param {string|File|Blob|MediaStream|HTMLMediaElement} source - Audio source * @param {Object} options - Streaming options * @param {number} options.blockLength - Number of frames per block (default: 2048) * @param {number} options.frameLength - Frame length for analysis (default: 2048) * @param {number} options.hopLength - Hop length between frames (default: 512) * @param {boolean} options.mono - Convert to mono (default: true) * @param {number} options.offset - Start time in seconds (default: 0.0) * @param {number} options.duration - Duration to stream in seconds (default: null, entire file) * @param {number} options.fillValue - Fill value for incomplete blocks (default: 0.0) * @param {AudioContext} options.audioContext - Web Audio context (default: new AudioContext()) * @param {Function} options.onBlock - Callback for each audio block * @returns {Promise>} Async generator yielding audio blocks * * @example * // Stream audio file in 2048-sample blocks * const file = document.getElementById('audio-input').files[0]; * const generator = await stream(file, { * blockLength: 2048, * mono: true, * onBlock: (block) => { * // Process each block in real-time * const features = mfcc(block); * console.log('Block features:', features); * } * }); * * // Iterate through blocks * for await (const block of generator) { * // Process block * console.log('Block shape:', block.length); * } */ export function stream(source: string | File | Blob | MediaStream | HTMLMediaElement, options?: { blockLength: number; frameLength: number; hopLength: number; mono: boolean; offset: number; duration: number; fillValue: number; audioContext: AudioContext; onBlock: Function; }): Promise>; /** * Get a sorted list of audio files using File System Access API * * Allows users to select a directory and find all audio files within it. * Uses the File System Access API (Chrome 86+, Edge 86+) for directory access. * Falls back to input element for older browsers. * * @param {FileSystemDirectoryHandle|Object|string} directory - Directory handle * (or a DirectoryHandle-shaped object in non-browser environments), or the * string 'select' to open the browser picker * @param {Object} options - Search options * @param {string|Array} options.ext - File extensions to match (default: common audio formats) * @param {boolean} options.recurse - Search subdirectories recursively (default: true) * @param {boolean} options.caseSensitive - Case-sensitive extension matching (default: false) * @param {number} options.limit - Maximum number of files to return (default: null, no limit) * @param {number} options.offset - Skip first N files (default: 0) * @returns {Promise>} Sorted list of audio File objects * * @example * // Find all audio files in a user-selected directory * const audioFiles = await find_files('select', { * ext: ['.mp3', '.wav', '.ogg', '.flac'], * recurse: true, * limit: 100 * }); * * console.log(`Found ${audioFiles.length} audio files`); * audioFiles.forEach(file => console.log(file.name)); * * @example * // Find files with Directory Handle * const dirHandle = await window.showDirectoryPicker(); * const files = await find_files(dirHandle, { * ext: '.wav', * recurse: false * }); */ export function find_files(directory: FileSystemDirectoryHandle | any | string, options?: { ext: string | Array; recurse: boolean; caseSensitive: boolean; limit: number; offset: number; }): Promise>; /** * Get citation information for the pleco-xa library * * Returns citation information in BibTeX format for academic use. * * @param {string} version - Optional version string (default: the shipped package version) * @returns {string} Citation information in BibTeX format * * @example * console.log(cite()); * // Prints: * // @software{pleco_xa, * // title = {pleco-xa: Browser-native audio analysis engine}, * // author = {Cameron Brooks}, * // ... * // } * * @example * // Get citation for specific version * const citation = cite('2.0.0'); * document.getElementById('citation').textContent = citation; */ export function cite(version?: string): string; /** * Create a real-time audio stream processor for live input * * Sets up a MediaStream source (microphone, etc.) with real-time * block processing using AudioWorklet or ScriptProcessorNode. * * @param {MediaStream} mediaStream - MediaStream from getUserMedia or other source * @param {Object} options - Processing options * @param {number} options.blockLength - Processing block size (default: 2048) * @param {boolean} options.mono - Convert to mono (default: true) * @param {Function} options.onBlock - Callback for each audio block (required) * @param {AudioContext} options.audioContext - Audio context (default: new AudioContext()) * @returns {Object} Stream controller with start(), stop(), and context properties * * @example * // Real-time microphone analysis * const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); * const processor = createMediaStreamProcessor(stream, { * blockLength: 2048, * onBlock: (audioBlock) => { * // Real-time feature extraction * const rms = Math.sqrt(audioBlock.reduce((sum, x) => sum + x * x, 0) / audioBlock.length); * console.log('RMS level:', rms); * } * }); * * processor.start(); * // ... later ... * processor.stop(); */ export function createMediaStreamProcessor(mediaStream: MediaStream, options?: { blockLength: number; mono: boolean; onBlock: Function; audioContext: AudioContext; }): any;