/** * MP3 encoding — MPEG-1 Layer III, constant bitrate, long blocks. * * The frame loop. Everything it needs already exists in its own module: * {@link analyseGranule} produces the spectrum, {@link quantizeGranule} decides * what survives the bit budget, and {@link FrameAssembler} handles the reservoir. * This is the part that runs them in the right order and divides the bits. * * ## Rate control across a frame * * A frame's slot is fixed by the bitrate, but its four granule-channels do not * need equal shares. Bits are handed out one unit at a time from a running pool, * so a granule that finishes under budget leaves the remainder to the ones after * it — within the frame, immediately, and across frames through the reservoir. * * The pool starts at the frame's own slot plus a bounded draw on the reservoir. * Bounded, because a granule that empties the reservoir leaves the next hard * passage with nothing to borrow; capping the draw at half a frame keeps a * buffer for the frames that need it more than this one does. * * ## What this does not do yet * * No joint stereo and no variable bitrate: the two channels are coded * independently, and every frame is the same size. Both cost bitrate rather than * correctness, and both are additions rather than changes to what is here. * * The output is valid MPEG-1 Layer III that any decoder reads. The README * publishes measured quality figures rather than adjectives. */ import type { Audio } from '../audio.js'; /** * Samples of latency between an encoder input sample and the corresponding * decoder output sample. * * Measured rather than derived: a windowed burst surrounded by silence, encoded * and decoded, moves its energy centroid by exactly this much. `test/mp3.test.ts` * repeats that measurement and fails if it drifts, because the figure is what * gapless playback subtracts and an error here is an audible offset. * * It comes out at the filterbank pair's own delay — the MDCT's granule of * lookahead is absorbed by feeding the transform the *previous* granule as the * first half of its window rather than delaying the input. */ export declare const ENCODER_DELAY = 528; export interface Mp3EncodeOptions { /** * Constant bitrate in kbit/s. One of 32, 40, 48, 56, 64, 80, 96, 112, 128, * 160, 192, 224, 256, 320. * * The default is 192 rather than the more familiar 128 because this encoder * has no psychoacoustic model yet: it spends bits evenly rather than where * they are least audible, and 192 is where that stops being noticeable. */ bitrate?: number; /** * Write the leading Xing/Info frame carrying frame count, duration, and the * priming and padding figures gapless playback needs. On by default. * * Turn it off only when the output is a fragment that will be concatenated * into a larger stream, where a tag partway through would misreport the whole. */ tag?: boolean; /** * Shape quantisation noise using the psychoacoustic model. On by default. * * Turning it off quantises flat — noise spread evenly across the spectrum * rather than hidden under the signal. Faster, and markedly worse below about * 256 kbps; useful mainly for measuring what the model is worth. */ psychoacoustic?: boolean; /** * Switch to short blocks on transients. On by default. * * A long block spreads its quantisation noise over 24 ms, so noise from a * drum hit is audible before the hit itself — pre-echo. Short blocks confine * it to 4 ms at the cost of coding efficiency, so they are used only where an * attack is detected. */ windowSwitching?: boolean; /** * Let each frame take the bitrate its content needs, instead of giving every * frame the same size. * * A constant-bitrate stream spends the same bytes on a cymbal crash and on a * held note, which means overspending on most of a track to afford the hardest * moments of it. Variable bitrate spends what transparency costs and stops. * `bitrate` then acts as a ceiling rather than a target. * * Requires the psychoacoustic model, which is what defines "enough". */ vbr?: boolean; /** * Variable-bitrate quality, 0 (best) to 9 (smallest). Default 4. * * Scales the masking thresholds: a lower number demands the noise sit further * below what masks it, which costs bits. On dense material the range runs from * roughly 240 kbit/s at 0 to 90 at 9, but the whole point is that the figure * follows the material rather than the setting. * * Ignored unless `vbr` is on. */ quality?: number; /** * How many passes the outer loop may take at shaping noise. Higher is slower * and slightly better. Ignored when `psychoacoustic` is off. */ effort?: number; } /** * Encodes an {@link Audio} to an MPEG-1 Layer III stream. * * ```ts * const mp3 = encodeMp3(audio, { bitrate: 192 }); * ``` * * MPEG-1 only, so the source must already be 32, 44.1 or 48 kHz and mono or * stereo. Resample or downmix first — silently changing the sample rate of * someone's audio is a worse outcome than refusing to. */ export declare function encodeMp3(audio: Audio, options?: Mp3EncodeOptions): Uint8Array; /** * Encodes planar float PCM, for callers that have channels rather than an * `Audio` — a streaming source, or a worker that was handed raw buffers. * * @param channels One `Float32Array` per channel, nominally in [-1, 1], all the * same length. Mono and stereo only. * @param sampleRate 32000, 44100 or 48000 Hz. */ export declare function encodeMp3Channels(channels: readonly Float32Array[], sampleRate: number, options?: Mp3EncodeOptions): Uint8Array;