Tanh Soft Clipping — User Guide
Memoryless tanh waveshaping with input-reference options, oversampling, parallel dry/wet mixing, and explicit output-level policies.
What this does
Tanh Soft Clipping applies a static nonlinear transfer function to every sample of the selected Sound. The wet waveshaper is:
y = Wet_level × tanh(Drive_amount × x)
As Drive_amount increases, the curve becomes progressively flatter near its positive and negative limits, compressing peaks smoothly rather than truncating them abruptly as a hard clipper would.
This is a memoryless, symmetric, odd waveshaper. It can be used for saturation and overdrive-like effects, but it is not a physical tube, tape, transformer, or magnetic-hysteresis model. It contains no bias, attack/release, hysteresis, head bump, frequency-dependent saturation, or deliberate even-harmonic mechanism.
For a symmetric sinusoidal input, the odd symmetry of tanh primarily generates odd harmonics. The nonlinear stage can also create components above Nyquist; oversampling is therefore available to reduce aliasing.
Quick start
- In the Praat Objects window, select exactly one Sound object.
- Run
Tanh_Soft_Clip.praat. - Choose a preset, or select Custom to use the Drive and Wet level fields directly.
- Choose whether Drive should follow the source's existing peak level or first use a normalized input reference.
- Leave Oversample = 4 for the default alias-reduced render; 1 disables oversampling. This script refuses 2× because of the documented round-trip phase offset on the tested Praat version.
- Set Dry/Wet and the desired output-level policy, then click OK.
Practical starting point: use a named preset, Input_reference = Use the source level, Oversample = 4, Dry_Wet = 1, and the default Normalize-to-target output mode. Switch to Normalize input peak before drive when you want the same Drive setting to behave more consistently across files with very different source levels.
Signal path
Selected Sound ↓ optional input-reference peak normalization ↓ optional oversampling ↓ tanh(Drive × x) × Wet_level ↓ anti-aliased downsampling to original rate ↓ Dry/Wet mix with the original Sound ↓ output policy ↓ Output_gain ↓ final Sound
The original duration, time domain, sample rate, and channel count are preserved. With multichannel Sounds, the same processing is applied channel by channel. Any global peak scaling uses one peak for the complete Sound object, so channel balance is linked rather than normalized independently per channel.
Input reference
Use the source level sends the source directly to the waveshaper. In this mode, saturation depth depends on both Drive and the source's existing amplitude: a quiet file may remain nearly linear at a Drive that heavily distorts a hot file.
Normalize input peak before drive first scales the copied source to a peak of 0.95 when its peak is above Silence_floor. This makes Drive more comparable across source files, at the cost of changing their original gain before waveshaping.
Oversampling
The wet branch can be processed at an integer multiple of the original sample rate and then resampled back. This gives nonlinear harmonics additional spectral headroom before downsampling removes out-of-band energy. It reduces aliasing; it does not make the process mathematically alias-free.
Supported effective range is 1–8×. Values below 1 are clamped to 1 and values above 8 to 8, with the effective value reported. 2× is explicitly disabled in this script because a frequency-dependent phase offset was measured for the 2× resampling round trip on Praat 6.1.38; this matters especially when wet and dry paths are mixed.
Parameters & presets
| Parameter | Default | Meaning |
|---|---|---|
| Preset | Gentle | Named presets set both Drive_amount and Wet_level. Custom leaves the manual values unchanged. |
| Drive_amount | 8 | Input multiplier inside tanh. Larger values reach the flattened part of the curve sooner. |
| Wet_level | 0.7 | Gain applied to the saturated branch before Dry/Wet mixing. With partial Dry/Wet it changes the wet/dry ratio and cannot be undone by later peak normalization. |
| Input_reference | Use source level | Use the source's existing peak, or normalize the copied input to 0.95 before Drive. |
| Oversample | 4 | Wet-path oversampling factor. 1 = off; 2 is refused; effective range 1–8. |
| Output_mode | Normalize to target | Selects final peak policy before Output_gain. |
| Scale_peak | 0.95 | Target used by Normalize and conditional Attenuate modes. It is ignored in Preserve mode. |
| Output_gain | 1.0 | Final post-policy makeup/trim gain. It survives every output mode. |
| Silence_floor | 1e-9 | Numerical guard used by Normalize mode and input-reference normalization. Peaks at or below the threshold are not raised. |
| Dry_Wet | 1.0 | 1 = fully processed branch; 0 = dry branch. The dry path returns at its original level only when the output policy is Preserve rendered level. |
| Draw_visualization | Yes | Draw the diagnostic AudioTools figure. |
| Play_result | Yes | Play the final Sound when processing finishes. |
Named presets
| Preset | Drive | Wet level |
|---|---|---|
| Gentle | 2.5 | 0.85 |
| Medium | 4 | 0.80 |
| Strong | 6 | 0.75 |
| Very strong | 8 | 0.70 |
| Heavy | 12 | 0.60 |
All five presets use the same tanh algorithm. They are not different analog models; they only choose different Drive and Wet-level values.
Output policies
The output policy is applied after waveshaping and Dry/Wet mixing. Output_gain is then applied last.
| Mode | Behavior |
|---|---|
| Normalize to target | If the pre-output peak is above Silence_floor, globally scale the complete rendered Sound to Scale_peak. Peaks at or below the guard are left at their current level. This mode can therefore raise a quiet but non-negligible signal to the target. |
| Preserve rendered level | No target-based scaling. The rendered level from waveshaping, Wet level, Dry/Wet mixing, and Input reference is preserved; only final Output_gain may change it. |
| Attenuate to target only if peak > target | Globally scale down only when the rendered peak exceeds Scale_peak. A signal already at or below the target is unchanged. This is whole-file attenuation, not a sample-by-sample limiter. |
Scale_peak is validated only in the two modes that use it and must be greater than 0 and no greater than 1.0. Output_gain is applied afterwards, so a gain above 1 can still produce a final peak above full scale; the script reports and warns about that condition.
Visualization
When enabled, the script draws a diagnostic figure rather than a generic effects display. It includes:
- Original waveform and Soft Clipped waveform over the full file.
- 20 ms zoom views of the source and result, starting at the Sound's actual start time rather than assuming time zero.
- Nominal wet transfer curve showing
Wet_level × tanh(kx). If input-reference normalization changed the input scale, the effective Drive shown in this curve includes that gain. - Wet half-slope markers at the mathematically defined points where the tanh curve's local slope has fallen to half its value at the origin. These markers describe the wet tanh curve, not the complete Dry/Wet output.
- Drive Comparison for bare
tanhcurves at Drive 2, 8, and 15. Its title and legend are placed in dedicated bands outside the plotted data. - Summary strip with source information, Drive, Wet level, Dry/Wet, oversampling, output policy, Output gain, and final peak.
The transfer panel intentionally does not pretend to be a final sample-by-sample transfer function when oversampling is active. Resampling filters make each output sample depend on neighboring samples, so the complete oversampled chain is not a static y = f(x) mapping. Dry mixing and global peak scaling are therefore reported numerically rather than folded into a misleading curve.
Limitations and interpretation
- No analog-device model: tanh alone does not reproduce tube, tape, transformer, hysteresis, dynamic bias, or frequency-dependent behavior.
- Level-dependent distortion: with source-level reference, the same Drive can produce very different saturation on quiet and hot files.
- Aliasing: nonlinear harmonics can exceed Nyquist. Oversampling reduces but does not eliminate aliasing.
- 2× oversampling disabled: this is a conservative script-specific safeguard based on the documented phase-offset measurement in the tested Praat version.
- Normalize-mode guard is a hard threshold:
Silence_flooris a numerical guard, not a psychoacoustic definition of silence. If a musical-level threshold is desired, raise it deliberately or use conditional attenuation instead. - Global peak policy: peak scaling acts on the complete Sound object and therefore links channels in multichannel material.
Outputs
- Object name:
<source>_tanh_<preset>, for examplevoice_tanh_Gentle. - Duration and time domain: restored to the original Sound after any oversampling round trip.
- Sample rate: same as the original Sound.
- Channels: same channel count as the original Sound.
- Selection: the processed Sound remains selected at the end.
- Playback: optional, controlled by
Play_result.