Skip to content

Audio Repair Workflow ​

Repair starts with evidence. A click, a clipped peak, a mains hum, a steady noise floor, and a diffuse room tail need different measurements and different algorithms. Measure the original buffer first, choose only the stages the evidence supports, then listen again at the same playback gain.

If dBFS, noise floor, or clipping are unfamiliar, read Audio Basics first — this page assumes that vocabulary and focuses on which repair stage to run.

The six repair stages are classical DSP. They reconstruct or attenuate part of the signal; they do not recover an original recording that was never captured. The stages run in one fixed order inside a mastering chain; when you combine the one-shot APIs, apply that same order yourself.

Terms on this page

  • Detector: a measurement that reports evidence for one defect (counts, levels, fractions) without changing the audio.
  • Linked: one gain mask computed from all channels together and applied to each, so the level and timing relationship between channels does not move.
  • Causal: a stage that needs only the audio it has already seen, plus a fixed delay, so it can run on a live stream; a non-causal stage needs the whole buffer.
  • Latency and tail: latency is how many samples late a realtime stage's output is; tail is how many samples of output keep coming after the input stops.
  • Streaming-safe noise estimator: the spp (speech-presence probability) estimator, which tracks the noise frame by frame instead of ranking the whole file, so the same denoise can run offline and live.

Choose the defect ​

What you hear or seeMeasure firstCandidate stageDo not use it as a substitute for
A steady broadband hiss or equipment floormasteringRepairDetectNoiseFloordenoiseRemoving a tonal hum or a clipped peak
A narrow 50/60 Hz tone and harmonicsmasteringRepairDetectHumdehumBroadband denoising of the whole spectrum
Isolated discontinuities or popsmasteringRepairDetectClicksdeclickRepairing a flat-topped waveform
Flat-topped peaks or a hard digital ceilingmasteringRepairDetectClippingdeclipRestoring samples that were overwritten for a long time
Many short, sample-scale surface defectsmasteringRepairDetectCrackledecrackleRemoving a sustained noise floor
A sustained, diffuse tail after the direct soundmasteringRepairDetectReverbdereverbRoom-impulse-response deconvolution
A/B PROCESS · DENOISEIDLE
Denoise repair — damaged vs repaired

Broadband hiss is added to a clean chord. Compare the noisy and denoised signals and their spectra, then choose a denoising algorithm. Both retain their processed levels without extra loudness matching. Noise reduction can also change musical transients and timbre. FLOOR shows the average high-band reduction in dB.

Compare
Algorithm

This embedded A/B uses the classical denoiser and does not apply loudness matching. It is a listening aid for the offline comparison workflow; select a repair stage only after inspecting the source.

Unwanted silence at the start or end is a separate utility, masteringRepairTrimSilence (detect it with masteringRepairDetectTrimRange); see Trimming silence and the CLI recording-cleanup workflow.

The detectors report what their corresponding algorithm measures. They are not a universal damage score, and a non-zero result still needs an audition. In particular, a full-scale sine or a square wave can look clipped to a time-domain detector even when it was intentional.

Drum hits are not read as defects. A hum candidate has to be a stationary line through most of each analysis frame, so a repeating kick reports fundamentalProminence 1.0 (a linear ratio, where 1.0 means no peak); crackle samples and click runs are counted only where they stand above the local transient level. A 6 s loop of twelve synthetic kicks at 44.1 kHz measured prominence 1.0, a click count of 0 and a crackle sampleCount of 0. The repair stages themselves still act inside transients, so replacedSamples and repairedRuns can exceed the detected counts.

Measure before repair ​

These detectors are exported by the WebAssembly package. samples below is a decoded mono Float32Array; keep the original sample rate instead of resampling only for the detector.

ts
import {
  init,
  masteringRepairDetectClipping,
  masteringRepairDetectClicks,
  masteringRepairDetectCrackle,
  masteringRepairDetectHum,
  masteringRepairDetectNoiseFloor,
  masteringRepairDetectReverb,
} from '@libraz/libsonare';

await init();

const reports = {
  clipping: masteringRepairDetectClipping(samples, sampleRate),
  clicks: masteringRepairDetectClicks(samples, sampleRate),
  crackle: masteringRepairDetectCrackle(samples, sampleRate),
  hum: masteringRepairDetectHum(samples, sampleRate),
  noise: masteringRepairDetectNoiseFloor(samples, sampleRate),
  reverb: masteringRepairDetectReverb(samples, sampleRate),
};

console.log(reports);

Fixed stage order ​

When more than one defect is present, apply only the selected stages in this order. This is also the order used by the repair slot in masterAudio and masteringChain.

Repair stages in run order
detectorstage, in run orderwhat it repairsshort-time defectsmasteringRepairDetectClipping1declipflat-topped peaks, a hard digital ceilingmasteringRepairDetectClicks2declickisolated discontinuities and popsmasteringRepairDetectCrackle3decrackledense, sample-scale surface defectssustained defectsmasteringRepairDetectHum4dehuma 50/60 Hz tone and its harmonicsmasteringRepairDetectNoiseFloor5denoisea steady broadband noise floormasteringRepairDetectReverb6dereverba diffuse tail after the direct soundA stage runs only when enabled. Enabling one never moves it.
Each detector enables one stage. Short-time defects are repaired first, then the sustained ones, so every detector and estimator sees material the stage before it has already cleaned.
OrderStageWhy this position matters
1declipA flat clipped region can hide the transient that the click detector needs to see.
2declickRepair isolated discontinuities after clipped peaks have been reconstructed.
3decrackleSmooth dense, sample-scale surface defects after the larger impulses are gone.
4dehumRemove the tracked fundamental and harmonics before estimating broadband noise.
5denoiseEstimate and attenuate the remaining stationary spectral floor.
6dereverbRun last because a broadband floor can look like a sustained late tail.

The order does not mean that every stage should run. A clean recording should skip the stages whose detectors do not support them. Re-run the relevant detector after a strong repair and keep the before/after reports with the rendered file.

Restoration presets ​

The restoration presets are named chain configurations, not new algorithms. They enable repair stages only and do not add loudness normalization, a target, or a final limiter. Their current stage choices are:

PresetIntended sourceEnabled repair stages
vinylLP transfer with clicks, crackle, and a noise floordeclick, decrackle, denoise
tapeHissTape transfer whose main defect is broadband hissdenoise
fieldRecordingLocation recording with noise, possible hum, and room taildenoise, adaptive dehum, dereverb
voiceMemoPhone or laptop capture with possible clipping, noise, and room taildeclip, denoise, dereverb
shellac7878 rpm transfer with wider clicks and denser surface noisedeclick, decrackle, deeper denoise

Read the exact preset parameters in Mastering Processors. A preset is a starting point: inspect the source and the report before keeping its output.

Measure and repair in one call ​

masteringRepairAnalyze runs all six detectors on every channel and returns the stages the evidence supports, each with its settings. masteringRepairApply runs those stages, or your own, over a channel set of any size. The recommendation is the same repair selection the mastering assistant makes when enableRepair is on.

ts
import { ErrorCode, init, isSonareError, masteringRepairAnalyze, masteringRepairApply } from '@libraz/libsonare';

await init();

const analysis = masteringRepairAnalyze({ channels: [left, right], sampleRate });
console.log(analysis.recommended.map((s) => s.stage), analysis.explanation);

let userPressedStop = false; // set from a Stop button
try {
  const { channels, reports } = masteringRepairApply({
    channels: [left, right],
    sampleRate,
    stages: analysis.recommended,
    onProgress: (fraction, stage) => console.log(stage, fraction), // "repair.declick", 0.33
    cancel: () => userPressedStop,
  });
} catch (error) {
  if (isSonareError(error) && error.code === ErrorCode.Cancelled) {
    // The user stopped the run; nothing was returned.
  } else {
    throw error;
  }
}
python
import libsonare

analysis = libsonare.mastering_repair_analyze([left, right], 48000)
print([s["stage"] for s in analysis["recommended"]], analysis["explanation"])

result = libsonare.mastering_repair_apply(
    [left, right], 48000, stages=analysis["recommended"]
)
print(result.reports[0].stage)  # the first stage that ran, e.g. "declick"
cleaned = result.channels
bash
# Measure and report only; writes nothing
sonare repair noisy.wav --detect --json

# Measure, choose the stages, repair, and say why each was chosen
sonare repair noisy.wav -o clean.wav --explain

Node uses the same names as the browser build. masteringRepairAnalyze returns:

FieldMeaning
defectsThe channels' detector results, aggregated
channelsEach channel's own defects, in input order
declipThresholdSafeWhether a declip at the measured flat level leaves louder unclipped audio alone; when false, declip is withheld from recommended
integratedLufsProgramme loudness the noise floor is compared against
recommendedThe supported stages in application order, each with every setting; pass it to masteringRepairApply as it stands
explanationWhy each stage was or was not chosen

Dereverb is never recommended, because the late-decay statistic cannot tell a sustaining dry source from a reverberant one. When a denoise is recommended it uses the streaming-safe noise estimator unless you pass preferStreamingSafe: false (Python prefer_streaming_safe=False).

How stages and the reports are spelled:

WhereSpelling
stage in stages, and reports[].stageThe bare name (declick). repair.declick is refused.
Setting names beside stageThe catalog parameters of the matching processor (repair.declick has maxClickSamples). A setting left out takes its default; an unknown setting, a repeated stage, or an out-of-range value is refused with InvalidParameter.
The onProgress stage argumentrepair.<stage>
  • The stages run in the fixed order above whatever order the array gives.
  • Declip, declick, and dehum decide over the whole channel set: a defect found in one channel is repaired in all of them, and dehum tracks one fundamental. Decrackle runs each channel alone. Denoise and dereverb apply one linked mask. The first three groups report once per channel (scope: 'channel'); the linked stages report once for the set (scope: 'linked').
  • onProgress is called after each stage with the fraction done. When cancel returns true after a report, the call throws a SonareError with code Cancelled.

The individual detectors and stages carry the same mastering_repair_ prefix in Python (mastering_repair_detect_hum, mastering_repair_declick_stereo, mastering_repair_denoise_classical_linked, mastering_repair_dereverb_config_for_room, mastering_repair_noise_band_bins). The CLI command is described in CLI reference and the recording-cleanup workflow.

Realtime inserts ​

Four of the stages are causal and run as realtime mixer inserts under their catalog ids. Each reproduces its offline function for the same settings, delayed by the latency the instance reports. Denoise and dereverb link their masks across the insert's channels.

InsertLatencyTailCost
repair.decrackle (median mode)11low
repair.dehum0146567low
repair.denoiseClassical12791023moderate
repair.dereverbClassical (subtraction mask)10231023moderate

Latency and tail are in samples, at 48 kHz with default settings. masteringInsertTiming(name, params, sampleRate) returns the figures for your own configuration, and a bounce must keep pulling output for tailSamples after the input ends so the tail is not cut off (repair.dehum rings for about 3 s).

A setting that needs the whole signal is refused by name: wavelet decrackle (mode: 1), WPE (weighted prediction error, a dereverb pre-stage), and the quantile noise estimator (noiseEstimator: 0, which ranks the whole file to find the floor), so the insert's denoise estimator defaults to spp. In a mixer scene an enum setting is the choice's number, not its name:

json
{ "processor": "repair.denoiseClassical", "slot": "pre", "params": { "reductionDb": 20, "noiseEstimator": 3 } }

repair.declick, repair.declip, and repair.trimSilence are offline only; the capability catalog marks them causal: false. See Effects Inserts for how a host reads the catalog.

Trimming silence ​

masteringRepairTrimSilence keeps a margin around the signal: paddingSamples, or paddingSec for the same margin in seconds rounded to the nearest sample. Give one or the other. At 22.05 kHz, paddingSec: 0.1 on a 1 s tone with 1 s of silence on each side returns 26460 samples (1.2 s); the same input without padding returns 22050. A negative padding throws RangeError.

Accepted ranges: threshold in [0, 1], paddingSamples up to 960000, windowMs in (0, 10000], and gateLufs in [-144, 0] for lufsGated mode. A value outside them throws InvalidParameter.

Offline contract ​

  • The masteringRepair* functions consume a complete buffer and return a new buffer or a result containing new channel buffers. Apart from the four realtime inserts above, they are offline operations.
  • All six repair stages preserve input length in their mono and stereo forms. Denoise and dereverb also provide linked forms for more than two channels. The separate masteringRepairTrimSilence utility is the boundary operation that can shorten a buffer.
  • Denoise and dereverb pad an input shorter than nFft for analysis and return it at its own length (a 512-sample input to masteringRepairDenoiseClassical returns a 512-sample result), so a short clip is measured rather than refused. Every stage refuses a setting above its upper bound; the bounds are listed on the stage pages. Other validation rules are in the JavaScript mastering API.
  • nFft must be a power of two from 4 through 524288. hopLength must be in (0, nFft / 2], and the periodic-Hann analysis window with the symmetric-Hann synthesis window must cover every overlap residue; a pair that leaves one uncovered is rejected. Offline mono, stereo, and linked repair and the streaming denoiser share this check.
  • Repair does not match LUFS or add gain to make the result appear equally loud. Measure loudness separately and compare at a controlled playback gain.

The DSP implementation notes explain the classical algorithms and their real-time boundary. For the exact overloads and report fields, use the JavaScript mastering API.