/* auto-generated by NAPI-RS */ /* eslint-disable */ /** Native bridge class exposed to Node.js via napi-rs. */ export declare class DecibriBridge { constructor(options?: DecibriOptions | undefined | null) /** * Construct a microphone bridge without blocking the JS event loop. The * device resolution and Silero model load run on the libuv thread pool; * the returned Promise resolves to a fully constructed bridge, or rejects * with the matching error. The synchronous `new` remains available and * unchanged. */ static openAsync(options?: DecibriOptions | undefined | null): Promise /** Start capturing audio. The callback receives `(err, chunk)` for each buffer. */ start(callback: (err: Error | null, chunk: Buffer) => void): void /** Stop capturing audio. */ stop(): void /** Whether the microphone is currently capturing. */ get isOpen(): boolean /** * Latest VAD speech probability (0.0 to 1.0). Updated by pump thread. * Returns 0.0 if VAD is not active. */ get vadProbability(): number /** * Number of capture buffers dropped because the consumer could not keep * pace (the core stream's overrun counter). Returns 0 while the consumer * keeps up or when no stream is active. Returned as f64 (an exact JS * number for any realistic count) to match the `vadProbability` getter. */ get overrunCount(): number /** * Queue far-end reference audio for the echo canceller. `buffer` is mono * PCM bytes in the bridge's configured format, at the declared reference * rate, in played order. Never blocks and never fails: a full queue * discards and counts rather than erroring. A push with no active stream * (not started, or stopped) is discarded and counted into the * `referenceDropped` metric when a canceller is configured; with echo * cancellation off it is a no-op. */ pushAecReference(buffer: Buffer): void /** * The echo canceller's transport and cancellation metrics, merged with the * reference queue's own counters, or `null` when no stream is active or * echo cancellation is off. Counters are returned as f64 (exact JS numbers * for any realistic count), matching the `overrunCount` getter. * * The top-level engine fields report the first delivered channel's * canceller; `channels` carries every delivered channel's engine report in * delivered order, one entry per channel, so the two agree on a * single-channel stream. */ aecMetrics(): AecMetricsJs | null /** List all available audio input devices. */ static devices(): Array /** Version information. */ static version(): VersionInfoJs } /** Native bridge class for audio output, exposed to Node.js via napi-rs. */ export declare class DecibriOutputBridge { constructor(options?: DecibriOutputOptions | undefined | null) /** * Construct a speaker bridge without blocking the JS event loop. The device * resolution runs on the libuv thread pool; the returned Promise resolves * to a constructed bridge, or rejects with the matching error. The * synchronous `new` remains available and unchanged. */ static openAsync(options?: DecibriOutputOptions | undefined | null): Promise /** * Write PCM data for playback. Starts the output stream on first call. * Empty buffers are a no-op. */ write(buffer: Buffer): void /** * Non-blocking write: convert the samples and start the stream on the JS * thread (a fast device open, same as the synchronous first write), then * perform the blocking channel `send` (which stalls under backpressure when * the queue is full) on the libuv thread pool. The returned Promise * resolves when the samples are queued, or rejects with the matching error. * Empty buffers resolve immediately. The synchronous `write` is unchanged. */ writeAsync(buffer: Buffer): Promise /** * Graceful drain: blocks until all queued samples have been played. * * Fails when the device died while the audio was still queued: the drain * returns early once the stream stops running, which covers a deliberate * stop and a driver failure alike, and only the failure stashes a typed * cause. An empty slot therefore leaves a normal drain silent. */ drain(): void /** * Non-blocking drain: the poll loop that waits for the cpal callback to play * everything queued runs on the libuv thread pool instead of the event loop. * The returned Promise resolves when the buffer has drained. With no stream * yet created it resolves immediately. The synchronous `drain` is unchanged. */ drainAsync(): Promise /** Immediate stop. Discards remaining samples. */ stop(): void /** Whether audio is currently being output. */ get isPlaying(): boolean /** * Number of samples emitted as silence fill because the playback queue * ran dry (the core stream's underrun counter). Returns 0 while the * producer keeps the queue fed or when no stream is active. Returned as * f64 (an exact JS number for any realistic count) to match the * microphone bridge's `overrunCount` getter. */ get underrunCount(): number /** List all available audio output devices. */ static devices(): Array /** Version information. */ static version(): VersionInfoJs } /** * Native offline-source handle exposed to Node.js via napi-rs. The public * `File` Readable lives in the JS wrapper; consumers construct that, not * this handle, directly. */ export declare class FileHandle { /** * Open an audio path as an offline source, synchronously (blocks on * disk I/O; the JS wrapper's async `File.open` uses `openAsync` * instead). */ static open(path: string, options?: FileOptions | undefined | null): FileHandle /** * Open an audio path without blocking the JS event loop: the disk read, * decode, and chain construction run on the libuv thread pool. */ static openAsync(path: string, options?: FileOptions | undefined | null): Promise /** * Wrap in-memory samples as an offline source. `samples` are f32 in * [-1.0, 1.0], frame-interleaved at the options' `inputChannels` (1 * when unset); `inputRate` is their native rate (raw samples carry no * header). No I/O, so construction is synchronous. */ static buffer(samples: Float32Array, inputRate: number, options?: FileOptions | undefined | null): FileHandle /** * Pull the next conditioned chunk, advancing the per-chunk VAD score on * the pre-conditioning feed. Returns `null` once the source is fully * delivered (after the end-of-stream tail) or already consumed. */ readChunk(): Buffer | null /** * Consume the source with the core's whole-recording analysis, off the * JS event loop. Resolves to the `VadReport`; a `File` built without VAD * rejects with the core's typed error, never a silently constructed * detector. * * Everything checkable is checked before the source is taken, so a * rejected call leaves the File exactly as it was and the caller can fix * the configuration and retry. */ analyze(): Promise /** * Consume the source and write the conditioned recording to disk, off * the JS event loop. Resolves to the `SaveReport`. * * Everything checkable is checked before the source is taken, so a * rejected call leaves the File exactly as it was and the caller can fix * the arguments and retry. */ save(path: string, options?: SaveOptions | undefined | null): Promise /** Release the source. Idempotent; a closed File reads as ended. */ close(): void /** * Most recent per-chunk VAD score (0.0 to 1.0), computed on the * pre-conditioning feed. 0.0 before the first chunk or with VAD off. */ get vadProbability(): number /** The target output rate every delivered chunk carries. */ get sampleRate(): number /** * The source's native rate, from the file's header or the explicit * `inputRate` of `buffer`. */ get inputRate(): number } /** * One delivered channel's canceller report inside `AecMetricsJs.channels`. * Engine-level fields only: the reference queue's counters (`referenceDropped`, * `referenceSilence`) describe the shared queue and stay on the top level. */ export interface AecChannelMetricsJs { /** * This channel's active delay alignment in samples, or `null` while its * estimator is still searching. The offset from the reference frontier as * the feeding established it, not a measurement of the room's echo path. */ delaySamples?: number /** * This channel's smoothed echo-return-loss-enhancement estimate in dB. * Not a quality ranking across channels: ERLE rises with echo distance, * because a weaker echo is easier to reduce in ratio terms, so a far * microphone routinely reports a higher figure than a near one while * removing less echo in absolute terms. Compare a channel against its own * history, not against its neighbours. */ erleDb: number /** * Whether this channel's double-talk detector currently believes the * near-end talker is active; its adaptation is held while true. */ doubleTalk: boolean /** * Near-end samples this channel's canceller could find no far-end sample * for while an alignment was active. */ referenceStarved: number /** * Near-end samples this channel processed while no delay alignment was * active: the searching span, not a transport failure. */ acquisitionParked: number /** * Times this channel's canceller inferred a capture discontinuity and * rebuilt its alignment from the reference frontier. */ referenceReanchors: number } /** * Echo-cancellation metrics returned to JS by `aecMetrics()`. One object * carries the canceller's own report and the reference queue's counters, so a * caller reads one surface for the whole diagnosis. */ export interface AecMetricsJs { /** * The active delay alignment in samples, or `null` while the estimator is * still searching. Staying `null` while `acquisitionParked` climbs is the * signature of a canceller with no usable reference: none pushed, not at * the declared rate, or not the signal that produced the echo. */ delaySamples?: number /** * Smoothed echo-return-loss-enhancement estimate in dB: how much echo the * canceller is currently removing. 0 before the filter has converged. */ erleDb: number /** * Whether the double-talk detector currently believes the near-end talker * is active; adaptation is held while true. */ doubleTalk: boolean /** * Near-end samples the canceller could find no far-end sample for while an * alignment was active. The core keeps the far-end stream level with the * capture, so this stays 0 for a caller who simply stops pushing; a * non-zero count means the caller ran further ahead of the capture than * the canceller's far-end history reaches. */ referenceStarved: number /** * Near-end samples processed while no delay alignment was active: the * searching span, not a transport failure. */ acquisitionParked: number /** * Times the canceller inferred a capture discontinuity and rebuilt its * alignment from the reference frontier. */ referenceReanchors: number /** * Far-end samples discarded, at the declared reference rate: a single * push exceeded the reference queue's bound, or the push arrived while * capture was not running. The span an oversized push occupied is still * represented as silence, so that discard costs the cancellation of the * span alone. */ referenceDropped: number /** * Far-end samples the core supplied as silence because the caller had * pushed none for them, at the capture rate. An accounting figure, not a * fault: while nothing is playing, the far end is silence. */ referenceSilence: number /** * Every delivered channel's canceller report, in delivered order, one * entry per channel. One canceller engine runs per delivered channel, * each fed the same pushed reference and each finding its own channel's * echo delay, so the entries differ where the channels' acoustic paths * differ. On a single-channel stream this holds one entry agreeing with * the top-level fields. */ channels: Array } /** * Options passed from JS constructor. * * Note on `ort_library_path` (exposed to JS as `ortLibraryPath`): this is an * internal plumbing field used by the JS wrapper in * `npm/decibri/src/decibri.js`. The wrapper auto-resolves the bundled ORT * dylib path via `require.resolve('@decibri/decibri-')` and passes * the absolute path through to here so Rust's `ort::init_from` can load the * correct library for the user's platform. * * The field is hidden from the auto-generated TypeScript definitions via * `#[napi(skip_typescript)]` so TS/JS consumers do not see `ortLibraryPath` * on the public options surface. It is still marshaled at runtime, so the * JS wrapper can pass it through. Rationale: adding a typed public option * later is non-breaking; removing one is breaking, so we default to not * exposing it until a concrete use case arises. * * Users who need to override ORT resolution (e.g. point at a system ORT, or * A/B between bundled and custom builds) should set the `ORT_DYLIB_PATH` * environment variable before Node starts. That's the supported public * mechanism. * * If this field is `None` (the default when not injected by the wrapper), * Rust calls `ort::init()` which honours `ORT_DYLIB_PATH`. */ export interface DecibriOptions { sampleRate?: number channels?: number /** * Capture channel map: 0-based device channel indices, one per delivered * channel (the shape of CoreAudio AUHAL's channel map, an index list, not * miniaudio's spatial `channelMap`). Absent delivers the documented * average of every opened channel. Entries are validated against the * resolved device's own report when the stream starts; no fixed maximum * exists. */ channelMap?: Array framesPerBuffer?: number format?: string device?: any vadMode?: string modelPath?: string /** * Capture DC-removal toggle. When `true`, removes a constant (DC) offset * from the captured audio with a one-pole DC-blocking high-pass, applied * first in the transform chain (before denoise). Absent or `false` leaves * it off (the default), a byte-identical no-op. Pure DSP: no bundled file * and no model path, like `highpass`. */ dcRemoval?: boolean /** * Capture denoise model selector. The only accepted value is * `'fastenhancer-t'`; absent leaves denoise off. The JS wrapper resolves * the bundled model file and passes its path through `denoise_model_path`. */ denoise?: string /** * Capture high-pass filter cutoff in Hz. The accepted values are `80` (an * 80 Hz second-order Butterworth high-pass) and `100` (a 100 Hz one); * absent leaves the high-pass off. Pure DSP: no bundled file and no model * path, unlike `denoise`. */ highpass?: number /** * Capture AGC target level in dBFS: an integer in `-40..=-3` (typical -18); * absent leaves AGC off. Drives the captured level toward the target. Pure * DSP: no bundled file and no model path, like `highpass`. */ agc?: number /** * Capture limiter ceiling in dBFS (sample-peak): a number in `-3.0..=0.0` * (typical -1.0); absent leaves the limiter off. Holds the captured signal * at or below the ceiling, catching a peak the AGC would let through. Pure * DSP: no bundled file and no model path, like `agc`. */ limiter?: number /** * Echo canceller model name. The accepted set is owned by the canceller * (`AecModel::from_str`); today it is `'tau'`. Absent leaves echo * cancellation off. The JS wrapper resolves both public forms (the string * shorthand and the `AecOptions` object) into this field and the three * below. Pure DSP: no bundled file and no model path, like `highpass`. */ aec?: string /** * Echo canceller filter tail in milliseconds: an integer in `16..=500`. * Absent takes the canceller's own default. Consulted only when `aec` * names a model. */ aecTailMs?: number /** * Residual-suppression policy for the echo canceller: `'conservative'` or * `'off'`. Absent takes the canceller's own default. Consulted only when * `aec` names a model. */ aecSuppression?: string /** * Sample rate in Hz of the far-end reference pushed through * `pushAecReference`, in `1000..=384000`. Absent means the reference is * already at the capture rate; when it names a different rate, the core * converts the reference before the canceller sees it. Consulted only * when `aec` names a model. */ aecReferenceSampleRate?: number /** * Number of channels in the far-end reference pushed through * `pushAecReference`, at least 1. Absent means the reference is mono; * when it names a count above 1, the core collapses each interleaved * frame to one mono sample before the canceller sees it. The declared * count must match the pushed buffer: a mismatch is not detected and * raises no error, and shows up only as `aecMetrics().delaySamples` * staying `null` with no fault reported. Consulted only when `aec` * names a model. */ aecReferenceChannels?: number } /** Options passed from JS constructor for output. */ export interface DecibriOutputOptions { sampleRate?: number channels?: number format?: string device?: any } /** Device info returned to JS. */ export interface DeviceInfoJs { index: number name: string /** * Stable per-host device ID suitable for `device: { id: ... }` selection. * The lowercase host name, a colon, then the platform device identifier: * `wasapi:` then the endpoint ID on Windows, `coreaudio:` then the device * UID on macOS, `alsa:` then the PCM identifier on Linux. Empty string if * cpal cannot produce a stable ID for this device. */ id: string maxInputChannels: number defaultSampleRate: number isDefault: boolean } /** * Options passed from the JS `File` wrapper. The conditioning fields mirror * `DecibriOptions` exactly, as do `channels` and `channelMap`, with the * source's own channel count standing where the device's report stands; the * live-capture-only fields (device, framesPerBuffer) do not apply to an * offline source. `inputChannels` is the interleave of the caller's own * samples and is honoured by `FileHandle::buffer` alone (a path's count * comes from its header; the JS wrapper refuses the option on the open * path). `vadThreshold` and `vadHoldoffMs` are internal plumbing (the user * passes them on the `vad` config object; the wrapper resolves them), * hidden from the generated TypeScript like `ortLibraryPath`. */ export interface FileOptions { sampleRate?: number channels?: number channelMap?: Array inputChannels?: number format?: string vadMode?: string modelPath?: string dcRemoval?: boolean denoise?: string highpass?: number agc?: number limiter?: number } /** Output device info returned to JS. */ export interface OutputDeviceInfoJs { index: number name: string /** * Stable per-host device ID. See `DeviceInfoJs.id` for format and * fallback semantics; identical rules for output devices. */ id: string maxOutputChannels: number defaultSampleRate: number isDefault: boolean } /** * Options passed from the JS `File.save` wrapper: the container format * override and the FLAC compression level. */ export interface SaveOptions { format?: string compression?: number } /** * What a save did to the samples on their way into the file: finite * samples outside full scale clamped and counted, non-finite samples * replaced (NaN with silence, an infinity with full scale) and counted. */ export interface SaveReport { clippedSamples: number nonFiniteSamples: number } /** One merged speech region of a recording, in seconds of file time. */ export interface Segment { start: number end: number } /** * The whole-recording analysis `File.analyze()` resolves to: per-window * scores and merged speech segments, in file order. */ export interface VadReport { scores: Array segments: Array } /** * One scored voice-activity window of a recording: `start` / `end` in * seconds of file time, the speech probability, and the raw threshold test. */ export interface VadWindow { start: number end: number vadScore: number isSpeech: boolean } /** Version info returned to JS. */ export interface VersionInfoJs { decibri: string audioBackend: string }