/** * The `Audio` value type — the thing you actually hold and pass around. * * ## Immutability * * Every transform returns a **new** `Audio`; nothing mutates in place. That * costs an allocation per step, and buys three things worth more than the * allocation: `const original = ...` stays true, an accidental second call * cannot corrupt earlier state, and chains read in the order they happen. * * For very large files where the copies matter, use the standalone functions in * `dsp/` directly, or stream the work — see `audiobox/stream`. * * ## Sample representation * * Planar `Float32Array`, one per channel, nominally in [-1, 1]. Values outside * that range are *allowed* between steps — summing two signals legitimately * exceeds 1 — and are clamped only when encoding to an integer format. Clamping * earlier would throw away headroom that a later `normalize()` could recover. */ import type { AudioMetadata, DecodeInfo, TimePosition } from './types.js'; import type { MixOptions } from './dsp/edit.js'; import type { ResampleOptions } from './dsp/resample.js'; import type { FadeCurve, NormalizeOptions, NormalizeResult } from './dsp/gain.js'; import type { FilterOptions, LimiterOptions } from './dsp/filter.js'; import type { TrimSilenceOptions, SilenceOptions, SilentRange } from './dsp/silence.js'; import type { LoudnessResult } from './analyze/loudness.js'; /** Options for {@link Audio.cut}. */ export interface CutOptions { /** Start position. Defaults to the beginning. Negative counts from the end. */ from?: TimePosition; /** End position. Defaults to the end. Negative counts from the end. */ to?: TimePosition; } /** Options for {@link Audio.fade}. */ export interface AudioFadeOptions { /** Fade-in length. */ in?: TimePosition; /** Fade-out length. */ out?: TimePosition; /** Shape. Defaults to `'linear'`. */ curve?: FadeCurve; } export declare class Audio { #private; /** Samples per second. */ readonly sampleRate: number; /** What the decoder found, when this came from a file. */ readonly info: DecodeInfo | undefined; /** * @param channelData One `Float32Array` per channel; all must be equal length. * @param sampleRate Samples per second. */ constructor(channelData: readonly Float32Array[], sampleRate: number, info?: DecodeInfo); /** Creates silence. */ static silence(duration: TimePosition, sampleRate?: number, channels?: number): Audio; /** Wraps interleaved samples, as produced by most capture APIs. */ static fromInterleaved(data: Float32Array, channels: number, sampleRate: number): Audio; /** * Wraps a Web Audio `AudioBuffer`. * * Typed structurally rather than against the DOM `AudioBuffer` so that core * stays free of browser type dependencies; a real `AudioBuffer` satisfies it. */ static fromAudioBuffer(buffer: { numberOfChannels: number; sampleRate: number; getChannelData(channel: number): Float32Array; }): Audio; /** Number of channels. */ get channels(): number; /** Frames per channel. */ get frames(): number; /** Duration in seconds. */ get duration(): number; /** Duration as `h:mm:ss.mmm`. */ get durationFormatted(): string; /** The raw samples for one channel. Treat as read-only. */ channelData(index: number): Float32Array; /** All channels. Treat as read-only. */ get allChannels(): readonly Float32Array[]; /** Interleaves into a single array, as most playback APIs expect. */ toInterleaved(): Float32Array; /** Copies into an existing Web Audio `AudioBuffer`. */ copyToAudioBuffer(buffer: { numberOfChannels: number; copyToChannel(source: Float32Array, channel: number): void; }): void; /** * Keeps the region between `from` and `to`. * * ```ts * audio.cut({ from: '0:30', to: '1:00' }); // the second half-minute * audio.cut({ from: -10 }); // the last ten seconds * audio.cut({ to: { sample: 44100 } }); // exactly one second at 44.1k * ``` */ cut(options: CutOptions): Audio; /** Deletes the region between `from` and `to`, closing the gap. */ remove(options: CutOptions): Audio; /** Appends other audio. All inputs must share a sample rate and channel count. */ concat(...others: readonly Audio[]): Audio; /** Adds silence at the start and/or end. */ pad(options: { start?: TimePosition; end?: TimePosition; }): Audio; /** Reverses the audio. */ reverse(): Audio; /** Sums other audio on top of this. */ mix(other: Audio, options?: Omit & { at?: TimePosition; }): Audio; /** Crossfades into `next` over `duration`. */ crossfadeTo(next: Audio, duration: TimePosition, curve?: FadeCurve): Audio; /** Converts to a different sample rate. */ resample(targetRate: number, options?: ResampleOptions): Audio; /** Downmixes to one channel by averaging. */ toMono(): Audio; /** Converts to two channels. */ toStereo(): Audio; /** Converts to an arbitrary channel count. */ toChannels(count: number): Audio; /** Reorders or duplicates channels by index. `[1, 0]` swaps a stereo pair. */ mapChannels(mapping: readonly number[]): Audio; /** Constant-power stereo pan. -1 is hard left, 1 is hard right. */ pan(position: number): Audio; /** Splits into one mono `Audio` per channel. */ split(): Audio[]; /** Merges mono buffers into one multi-channel `Audio`. */ static merge(...parts: readonly Audio[]): Audio; /** Applies a linear gain. */ gain(linear: number): Audio; /** Applies a gain in decibels. */ gainDb(db: number): Audio; /** * Scales to a target level. * * ```ts * audio.normalize(); // peak to -1 dBFS * audio.normalize({ to: -14, unit: 'LUFS' }); // streaming loudness * ``` */ normalize(options?: NormalizeOptions): Audio; /** Like {@link normalize}, but also reports what was measured and applied. */ normalizeWithReport(options?: NormalizeOptions): { audio: Audio; report: Omit; }; /** Applies a fade-in and/or fade-out. */ fade(options: AudioFadeOptions): Audio; /** Applies a biquad filter. */ filter(options: FilterOptions): Audio; /** Applies a soft limiter. */ limit(options?: LimiterOptions): Audio; /** Removes DC offset. */ removeDcOffset(): Audio; /** Trims silence from the start and/or end. */ trimSilence(options?: TrimSilenceOptions): Audio; /** Finds silent spans without modifying anything. */ detectSilence(options?: SilenceOptions): SilentRange[]; /** Changes speed and pitch together, like a varispeed tape machine. */ speed(factor: number): Audio; /** Changes duration while preserving pitch. */ tempo(factor: number): Audio; /** Shifts pitch while preserving duration. */ pitch(semitones: number): Audio; /** Highest absolute sample value, as a linear ratio. */ peak(): number; /** Peak in dBFS. */ peakDb(): number; /** Inter-sample peak in dBTP. */ truePeakDb(): number; /** RMS level in dBFS. */ rmsDb(): number; /** Integrated loudness and range, per ITU-R BS.1770. */ loudness(): LoudnessResult; /** * Min/max pairs per bucket, for drawing a waveform. * * Returns extremes rather than averages: averaging washes out transients and * produces the flat, lifeless waveform displays that make it impossible to * see where the beats are. * * @param buckets Number of horizontal pixels to draw. */ waveform(buckets: number): { min: Float32Array; max: Float32Array; }; /** A short human-readable summary, handy when logging. */ toString(): string; } /** Re-exported so callers can build metadata without a second import. */ export type { AudioMetadata };