Polynomial Sound Shaper — User Guide

A polynomial gain-envelope processor that maps the Sound's actual time domain onto a mathematical domain, evaluates either coefficient or root form, then applies absolute or signed gain shaping with optional exponent weighting and gain limits.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 1.3.1 (2026) License: MIT License Repo: Praat AudioTools
Contents:

What this does

Polynomial Sound Shaper multiplies every sample of one selected Sound by a gain derived from a polynomial. Audio time is mapped linearly from the Sound's real interval [t_start, t_end] onto the mathematical interval [Start_x, End_x]. The polynomial can be entered directly as cubic coefficients or defined by two or three real roots.

u(t) = Start_x + ((t - t_start) / duration) × (End_x - Start_x) Coefficient mode: p(u) = a u³ + b u² + c u + d Root mode, quadratic: p(u) = (u - r₁)(u - r₂) Root mode, cubic: p(u) = (u - r₁)(u - r₂)(u - r₃)

The raw polynomial is not necessarily the applied gain. The script can first take |p|, then raise the magnitude to Perceptual_weight, and finally clamp it to [Min_gain, Max_gain]. In signed mode the sign is preserved, so negative polynomial regions invert polarity.

Not a waveshaper: the polynomial is evaluated as a function of time, not sample amplitude. The processor therefore changes the amplitude envelope over time; it does not apply a nonlinear transfer function to the waveform samples themselves.

Quick start

  1. Select exactly one Sound in Praat.
  2. Run Polynomial_Sound_Shaper.praat.
  3. Choose one of the nine presets, or leave Custom.
  4. Choose Polynomial coefficients or Polynomial from roots. Root mode can use two roots (quadratic) or three roots (cubic).
  5. Set the mathematical domain with Start_x and End_x.
  6. Use Treat_as_envelope = On for non-negative gain, or Off for a signed polarity envelope.
  7. Set Perceptual_weight, Min_gain, and Max_gain, then run the script.
Useful starting point: Fade In and Fade Out are true linear ramps. Swell gives a centre-peaked 1-x² envelope because its negative quadratic is converted to absolute gain. Double Pulse uses three roots and |p(x)| to form two lobes.

Gain calculation

Stage 1 — raw or absolute polynomial

Treat_as_envelope = On: q(t) = |p(u(t))| Treat_as_envelope = Off: q(t) = p(u(t))

With envelope mode On, negative polynomial values do not invert the waveform; their magnitude becomes positive gain. With signed mode Off, negative values remain negative and therefore reverse sample polarity.

Stage 2 — exponent weighting

Envelope mode: w(t) = q(t)^Perceptual_weight Signed mode: w(t) = sign(q(t)) × |q(t)|^Perceptual_weight

Perceptual_weight = 1 leaves the polynomial magnitude unchanged. Values above 1 suppress sub-unity gain values more strongly and make the envelope more concentrated around its larger values. The control is an exponent applied to gain; it is not a calibrated psychoacoustic loudness model.

Stage 3 — dynamic-range clamp

Envelope mode: gain(t) = clamp(w(t), Min_gain, Max_gain) Signed mode: gain(t) = sign(w(t)) × clamp(|w(t)|, Min_gain, Max_gain) Output sample: y(t) = x(t) × gain(t)

Min_gain must be non-negative and Max_gain must be at least Min_gain. In signed mode, a positive Min_gain keeps a minimum magnitude on both sides of zero; if a smooth zero crossing is required, use Min_gain = 0.

Presets

There are nine named presets plus Custom. Presets set their listed polynomial type/parameters and mathematical domain. They do not reset Min_gain, Max_gain, Treat_as_envelope, output normalization, visualization, or playback. Quartic In and Quartic Out explicitly set Perceptual_weight = 2; the other presets leave the submitted weight unchanged.

PresetPolynomial / rootsDomainResult with envelope mode
Fade In (linear)p(x)=x[0, 1]Linear 0 → 1.
Fade Out (linear)p(x)=1-x[0, 1]Linear 1 → 0.
Swell (peak center)roots −1, +1; quadratic[−1, 1]|x²-1| = 1-x²: zero at edges, peak at centre.
Attack-Decayp(x)=-4x²+4x[0, 1]Symmetric 0 → 1 → 0 parabola.
Slow Attackp(x)=x³[0, 1]Slow-start cubic rise.
Double Pulseroots 0, 0.5, 1; cubic[0, 1]Two absolute-value lobes separated by the centre root.
Asymmetric Riseroots 0, 2; quadratic[0, 1]|x(x-2)| = 2x-x², rising to 1.
Quartic Inp(x)=x², weight 2[0, 1]Effective x⁴.
Quartic Outp(x)=(1-x)², weight 2[0, 1]Effective (1-x)⁴.

Parameters

ParameterDefaultMeaning
PresetCustomCustom or one of nine named polynomial recipes.
Envelope_typePolynomial coefficientsDirect cubic coefficients, or a polynomial constructed from real roots.
Polynomial_degreeQuadratic (2 roots)Used in root mode: two roots or three roots.
Start_x / End_x0 / 1Mathematical interval traversed over the full Sound. Must satisfy Start_x < End_x.
Coef_a / b / c / d0 / 0 / 1 / 0Coefficients of ax³ + bx² + cx + d. Defaults give p(x)=x.
Root_1 / Root_2 / Root_3−1 / 1 / 0Real zeros used by root mode. Root 3 is used only for Cubic.
Perceptual_weight1.0Positive exponent applied to gain magnitude after the raw/absolute polynomial stage.
Min_gain0.0Minimum permitted gain magnitude. Must be ≥0.
Max_gain1.0Maximum permitted gain magnitude; must be ≥ Min_gain.
Treat_as_envelopeOnOn uses |p(x)|; Off preserves the sign and permits polarity inversion.
Peak_normalize_outputOffIf enabled, calls Praat Scale peak: 0.95 after envelope application.
Draw_visualizationOnDraws the diagnostic figure described below.
Play_resultOnPlays the completed Sound.

Processing details

The script creates a mono control Sound named polyEnv at 1000 Hz. Its time domain extends 5 ms before and after the source interval. The polynomial mapping itself uses the source's actual t_start and duration, so Sounds whose time domain does not begin at zero are handled correctly.

The control Sound is processed in three passes: raw/absolute polynomial, exponent weighting, then gain clamping. Only the interval corresponding to the source is used for the reported envelope minimum/maximum. The source is copied and every channel is multiplied by the same time-varying control through Praat's formula lookup at time x, so channel relationships are preserved.

1000 Hz control rate: the polynomial itself is mathematically continuous, but the applied control is represented as a 1 kHz Sound and read by time position during the audio-rate Formula operation. This is an offline control-envelope implementation, not direct evaluation of the polynomial independently at every audio sample.

Peak normalization is separate from the polynomial processing and is Off by default. When enabled it runs after shaping and scales the result to peak 0.95.

Visualization

The v1.3.1 Picture is diagnostic rather than decorative. It separates the mathematical polynomial from the gain that is actually applied:

Panel A and Panel B intentionally use different vertical scales because one is the raw mathematical function and the other is the clamped applied gain. The output waveform also uses its own amplitude scale.

Output and interpretation

The source is copied rather than replaced. The result is named:

<source>_shaped_<preset name>

Examples include voice_shaped_FadeIn, voice_shaped_DoublePulse, and voice_shaped_Custom. Duration, sampling frequency, channel count and the source Sound's time domain are inherited from the copied input.

Gain range matters: with the defaults Min_gain=0 and Max_gain=1, envelope mode can only attenuate. Raising Max_gain above 1 permits amplification. Signed mode can invert polarity. Peak normalization, if enabled, changes the final absolute level after all of these operations.

Because named presets do not reset every form field, controls such as Min_gain, Max_gain, Treat_as_envelope and, for non-quartic presets, Perceptual_weight remain part of the chosen configuration. This is useful for variations, but it also means a preset name alone does not fully specify a render unless those global controls are reported as well.