Dynamic Distortion — User Guide
Amplitude-contour-controlled tanh distortion with zero-phase or causal envelope tracking.
What this does
Dynamic Distortion applies a tanh nonlinearity whose drive changes sample by sample according to an amplitude contour derived from the input. The core relationship is:
output(t) = Output_Gain × tanh( mono_input(t) × drive(t) )
With positive Base_Drive and positive Sensitivity, larger envelope values produce a larger drive magnitude and therefore stronger saturation. The form also permits zero and negative values, so Manual mode can reverse that relationship, cross through zero drive, invert polarity, or silence the result through Output_Gain = 0.
The script offers two distinct ways to build the amplitude contour: the historical zero-phase smoothing mode, which is offline and acausal, and a causal attack/release follower. These are not interchangeable implementations of the same timing model; they have different temporal behavior.
Quick start
- Select exactly one Sound in Praat.
- Run
Dynamic_Distortion.praat. - Choose Manual or one of the four presets.
- Choose an Envelope_mode: zero-phase smoothing or causal attack/release.
- For zero-phase mode, set Response_Speed_Hz. For causal mode, set Attack_ms and Release_ms.
- Choose whether to Clamp_envelope_to_zero.
- Choose the Output_level behavior and run the script.
Base_Drive, Sensitivity, Response_Speed_Hz, and Output_Gain. They do not change Envelope_mode, Attack_ms, Release_ms, Clamp_envelope_to_zero, Output_level, visualization, or playback. In causal mode, a preset's Response_Speed_Hz value is present but unused.
Signal path
Processing sequence
↓
Praat Convert to mono
↓
Copy → absolute value |x|
↓
[Zero-phase Hann-band smoothing] OR [Causal attack/release follower]
↓
Optional envelope clamp: max(envelope, 0)
↓
drive(t) = Base_Drive + Sensitivity × envelope(t)
↓
y(t) = tanh(x(t) × drive(t)) × Output_Gain
↓
Preserve / conditional attenuation / peak normalization
The output is named <source>_DynDist_<presetName>, using Manual, TouchSensitive, DrumPumper, PolarityCrossing, or ExpressiveLead.
Envelope modes
1. Zero-phase smoothing (default)
The mono signal is full-wave rectified with abs(), then processed by Praat's Filter (pass Hann band) from 0 Hz to Response_Speed_Hz with a 20 Hz transition width. In this mode, Response_Speed_Hz is a smoothing cutoff, not an attack or release time.
Response_Speed_Hz must be greater than 0 and below the Sound's Nyquist frequency. Higher values retain faster amplitude variation; lower values produce a smoother contour.
2. Causal attack/release follower
This mode uses a recursive one-pole follower with separate time constants for rising and falling values. The rectified input is processed from left to right:
aRelease = exp( -1 / (fs × Release_seconds) )
if input[n] > envelope[n-1]:
envelope[n] = aAttack × envelope[n-1] + (1-aAttack) × input[n]
else:
envelope[n] = aRelease × envelope[n-1] + (1-aRelease) × input[n]
Attack_ms and Release_ms must both be greater than 0. Unlike zero-phase smoothing, this mode does not anticipate future samples.
Clamp_envelope_to_zero
Rectification itself is non-negative, but the zero-phase Hann-band filter can ring below zero around sharp changes. With the clamp disabled (the default), those negative values remain part of the control contour. With the clamp enabled, the script applies:
This distinction matters because a negative envelope can move the computed drive below Base_Drive when Sensitivity is positive. For that reason, Base_Drive is described as the nominal drive at zero envelope, not as an unconditional minimum.
Parameters & presets
Form parameters
| Parameter | Default | Behavior |
|---|---|---|
| Preset | Manual | Manual or four parameter presets. |
| Base_Drive | 1.0 | Nominal drive when the envelope is exactly 0. Any real value is accepted. |
| Sensitivity | 5.0 | Envelope-to-drive multiplier. Any real value is accepted; negative values reverse the drive response. |
| Response_Speed_Hz | 20.0 | Zero-phase smoothing cutoff. Used only in zero-phase mode; must be >0 and below Nyquist. |
| Envelope_mode | Zero-phase | Zero-phase acausal smoothing or causal attack/release follower. |
| Attack_ms | 5.0 | Causal-mode rise time constant; must be >0. |
| Release_ms | 50.0 | Causal-mode fall time constant; must be >0. |
| Clamp_envelope_to_zero | No | Clamps negative envelope undershoot to 0 when enabled. |
| Output_Gain | 0.9 | Constant scalar after tanh. Negative values invert polarity; 0 silences the shaped signal. |
| Output_level | Normalize peak to 0.95 | Preserve, conditionally attenuate, or normalize the final mono result. |
| Draw_visualization | Yes | Draw the diagnostic 8×8-inch Picture-page visualization. |
| Play_result | Yes | Play the result after processing. |
Built-in presets
| Preset | Base | Sensitivity | Response | Output Gain |
|---|---|---|---|---|
| Touch Sensitive Drive | 0.8 | 3.0 | 15 Hz | 0.9 |
| Drum Pumper | 1.0 | 8.0 | 50 Hz | 0.8 |
| Polarity-Crossing Crunch | -0.5 | 10.0 | 80 Hz | 1.0 |
| Expressive Lead | 1.2 | 4.0 | 10 Hz | 0.9 |
Negative and zero values
envelope = -Base_Drive / Sensitivity. The output reaches zero at that control value and changes polarity across it. The script reports whether that crossing actually falls inside the measured envelope range of the current file.
Negative Sensitivity means larger envelope values lower the drive rather than raise it. Sensitivity = 0 makes the drive constant at Base_Drive. Output_Gain < 0 inverts the entire shaped result; Output_Gain = 0 makes it silent.
Output level
| Mode | Exact behavior |
|---|---|
| Preserve shaped level | No peak scaling. If the absolute peak exceeds 1.0, the script prints a warning. |
| Attenuate to 0.95 only if peak > 0.95 | If the shaped peak exceeds 0.95, the entire file is scaled globally so its peak becomes 0.95. This is peak attenuation, not a sample-by-sample limiter. |
| Normalize peak to 0.95 | For any non-silent result, globally scale the peak to 0.95. A zero-peak result is left unchanged and normalization is skipped safely. |
Visualization
The 8×8-inch Picture display is diagnostic rather than decorative. It follows the Sound's actual time domain, including Sounds whose start time is not 0.
Two tanh mappings based on the measured envelope extremes are drawn over the same input range. The gray curve uses the envelope minimum and the red curve uses the envelope maximum. The curves include
Output_Gain and any global output-level scaling actually applied to the render. Negative drive therefore appears as a polarity-inverted curve rather than being hidden.Panel B — Envelope and computed drive
The upper sub-panel shows the measured envelope with min/max references. In v0.5.1, a negative zero-phase undershoot is included in the Y range rather than clipped from view. The lower sub-panel shows
Base_Drive + envelope × Sensitivity, with zero and Base_Drive references when visible.Panel C — Processing source vs result
Gray is the actual mono processing source; red is the distorted result. This is the correct comparison for stereo or multichannel inputs because processing occurs after the mono conversion.
Panel D — Output waveform
Final mono waveform across the complete Sound domain.
Panel E — Summary
Preset, envelope mode, level mode, Output_Gain, measured envelope range, measured drive range, mono-collapse note, duration, and final peak.
When an output-level stage has applied global scaling, Panel A uses that measured scale. The underlying normalization factor depends on the peak of the whole file, so the panel should be read as representative transfer curves for this render rather than as a self-contained memoryless description of the entire processor.
Behavioral notes and limitations
- Mono only: all input channels are collapsed before analysis and processing.
- Zero-phase mode is offline/acausal: it can alter drive before a transient. Use the causal follower when forward-time behavior is required.
- No oversampling: tanh is nonlinear and generates harmonics; high-frequency products can alias at the native sample rate.
- The envelope is a control signal, not an RMS meter: it is derived from absolute-value rectification followed by the selected smoothing method.
- Negative zero-phase ringing is intentional when unclamped: it can push the drive below Base_Drive.
- Presets are partial: envelope mode, clamp, causal timings, and output-level mode remain whatever the user selected.
- Extreme real-valued settings are allowed: negative Sensitivity, negative drive, and large Output_Gain can produce polarity changes or strong level changes.
Applications
Useful applications include level-dependent saturation on instruments or voice, transient-sensitive distortion on percussion, inverted dynamic response with negative Sensitivity, and experimental polarity-crossing textures. These are creative uses of the control law; the processor is not a physical model of a tube amplifier, pedal, compressor, or noise gate.