Math Operations Between Sounds — User Guide

Sample-by-sample mathematical combination of two Sound objects, with 17 operation presets, 31 manual operations, explicit channel handling, deterministic random scatter when seeded, and four output-level modes.

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

What this does

Math Operations Between Sounds combines two Sound objects by applying one mathematical rule to corresponding samples. The script offers four operation tiers: Basic, Modulation, Nonlinear, and Advanced. In Custom mode, only the highest active tier runs: Advanced > Nonlinear > Modulation > Basic.

Important terminology: several operations are deliberately named as mathematical approximations rather than established DSP algorithms. FM-like operations are sample-value waveshapers, not conventional FM with phase integration. Pseudo-Sync is not oscillator hard sync. Logistic-Style Shaping is a non-recursive static formula, not a logistic-map dynamical system. Cross-Phase Waveshaper is sample-wise trigonometric recombination, not a phase vocoder.

The script works on a copy of Sound 1, uses Sound 2 as the second operand, then applies the selected output-level policy. Presets select an operation and, where relevant, set Modulation_depth or Nonlinear_intensity. They do not reset global output scaling, channel policy, random seed, divide epsilon, fold passes, or magnitude-product polarity.

Inputs, order, duration, and channels

Select exactly two Sound objects. Sound 1 and Sound 2 follow the Praat Objects-list order, top to bottom — not the order in which you clicked them. Order matters for non-commutative operations such as Subtract, Divide, Power Mod, and operations whose sign or channel layout is defined by Sound 1.

Sample rate and duration

Channel policy

PolicyBehavior
Sound 1 defines layout (default; v0.2/v0.3 behavior)The result has Sound 1's channel layout. Mono Sound 2 is broadcast across Sound 1's channels. If Sound 2 has extra channels, they are ignored. If Sound 1 has more channels than Sound 2, Sound 1's extra channels are processed against silence.
Require matching channel countsThe script exits if the two inputs do not have the same number of channels.
Mix both to monoEach input is converted to mono before the operation; the result is mono.

Quick start

  1. Select exactly two Sound objects in Praat. Check their top-to-bottom order.
  2. Choose a Preset, or choose Custom (manual settings).
  3. For Custom, select operations in one or more tiers. If more than one tier is active, only the highest-priority tier runs.
  4. Adjust the parameter that actually belongs to that operation: modulation depth, nonlinear intensity, fold passes, divide epsilon, product polarity, or random seed.
  5. Choose a Channel_policy.
  6. Choose an Output_mode and Output_scaling.
  7. Run the script. The result is named Sound1_PresetName_Sound2.
Preset scope: presets choose the transform and set only the transform-specific depth/intensity values shown below. Output level remains under the user's control. For example, choosing Quantized Lo-Fi does not force normalization, and Random Amplitude Scatter does not overwrite Random_seed.

Presets

The menu contains Custom + 17 operation presets. The values below are the settings assigned by each preset. Other form controls keep their current values.

PresetSelected operationPreset parameterOutput tag
Clean AddBasic: AddAdd
Clean Multiply (Ring Mod)Basic: MultiplyRingMod
Tremolo EffectModulation: TremoloMod depth = 0.5Tremolo
Crunch Mod (Arctan)Modulation: Soft clip (arctan)Mod depth = 2.0Crunch
FM-like WaveshapingModulation: FM-like sin(S1) × S2Mod depth = 2.0FM
Double Sine WaveshapingModulation: sin(S1) × sin(S2)Mod depth = 1.5DoubleSine
Wavefold DistortionNonlinear: WavefoldIntensity = 0.8; current Fold_passes retainedWavefold
Quantized Lo-FiNonlinear: Quantize to 1/N amplitude stepsIntensity = 0.5 → N = 8QuantizedLoFi
Cosine Cross-WaveshaperNonlinear: Cosine cross-waveshapeIntensity = 1.2CosXWaveshape
Pseudo-SyncNonlinear: Hard sync simIntensity = 0.9PseudoSync
Logistic-Style ShapingAdvanced: Logistic-style non-recursiveIntensity = 0.5 → r = 3.5LogisticStyle
Soft Normalized MixNonlinear: Soft normalize mixIntensity = 0.8SoftNormMix
Cross-Phase WaveshaperAdvanced: Cross-phase waveshaperIntensity = 0.5 → index = 50CrossPhase
Random Amplitude ScatterAdvanced: Random amplitude scatterIntensity = 0.5; current seed retainedRandAmpScatter
Geometric Product (sqrt magnitudes)Advanced: Geometric productCurrent Geometric_polarity retained; intensity unusedGeoProduct
Vector MorphAdvanced: Vector morphIntensity = 0.5VectorMorph
Rectify DistortionAdvanced: Rectify & mixIntensity = 0.5 → S2 magnitude weight = 1.0Rectify

Operations

In the formulas below, S1 is the current sample of Sound 1 and S2 is the corresponding sample of Sound 2. d denotes Modulation_depth; i denotes Nonlinear_intensity.

Basic operations

OperationActual formula / behaviorNotes
AddS1 + S2Can exceed full scale.
SubtractS1 − S2Order-sensitive.
Multiply (Ring Mod)S1 × S2For sinusoidal inputs, produces sum/difference components.
Divide0 when |S2| ≤ Divide_epsilon; otherwise S1/S2Order-sensitive; guard avoids near-zero denominator blow-ups.
Average(S1 + S2)/2Arithmetic average; not an equal-power crossfade.
Minimummin(S1,S2)Sample-wise minimum, not envelope extraction.
Maximummax(S1,S2)Sample-wise maximum, not envelope extraction.
Absolute difference|S1 − S2|Unsigned / rectified difference.
XOR-like (sign mixing)Average magnitude; negative when the signs differ, positive otherwiseA sign-based custom mapping, not digital XOR.

Modulation tier

OperationFormulaMeaning
AM unipolar (sin)S1 × [0.5 + 0.5 sin(S2 × 10πd)]S2 sample values drive a sine-shaped unipolar gain factor.
AM unipolar (cos)S1 × [0.5 + 0.5 cos(S2 × 10πd)]Cosine variant of the same sample-value modulation.
FM-like (sin)sin(S1 × 5πd) × S2Static sine waveshaping/cross-modulation; no phase integration.
FM-like (cos)cos(S1 × 5πd) × S2Cosine variant; not conventional FM.
Double sine waveshapingsin(S1 × 5πd) × sin(S2 × 5πd)Both sample streams are sine-waveshaped, then multiplied.
Soft clip (arctan)(2/π) arctan(S1 × S2 × 10d)Bounded nonlinear transform of the sample product.
Power modSigned |S1|^max(1+S2d,0.05), with a near-zero safety guardExponent is floored at 0.05; negative exponents are not allowed.
TremoloS1 × (1 + S2d)Acts as tremolo when S2 is an LFO. For depth > 1 the gain can become negative.

Nonlinear tier

OperationActual behaviorRole of intensity
Cosine cross-waveshapeS1 × cos(2π × S2 × 100i)Scales the cosine shaping index. This is not a frequency shifter.
AM depth controlS1 × (1 + S2i)Direct gain-modulation depth.
WavefoldRepeated reflection of S1+S2 around threshold T=1/(0.5+i)Higher intensity lowers the threshold; Fold_passes sets repeated reflections.
Hard sync simIf |S2| > |S1|i, output takes sign(S2) × |S1|; otherwise S1×S2Controls the switching criterion. It is not oscillator reset/sync.
Quantize to 1/N amplitude stepsround((S1+S2)N)/NN = max(1, round(16i)). This defines step size 1/N; it is not an N-bit quantizer.
Amplitude-dependent blendS1(1−i|S2|) + S2iControls both S1 attenuation and S2 contribution.
Soft normalize mix(S1+S2) / [1+i(|S1|+|S2|)]Controls static amplitude-dependent compression of the sum.

Advanced tier

OperationActual formula / behaviorNotes
Geometric product (sqrt magnitudes)sqrt(|S1|) × sqrt(|S2|)With default polarity, Sound 1's sign is restored. Unsigned mode remains nonnegative.
Magnitude product|S1| × |S2|Also optionally restores Sound 1's sign. It is a direct magnitude product, not an exponential-domain transform.
Vector morphS1(1−i) + S2iA linear crossfade only for 0≤i≤1. Values above 1 extrapolate and give Sound 1 a negative weight.
Logistic-style shaping(S1+S2) × [r − r|S1||S2|], with r=7iNon-recursive static shaping; not a logistic-map iteration or chaotic state system.
Rectify and mix|S1| − (2i)|S2|Output may be positive or negative because one rectified magnitude is subtracted from the other.
Cross-phase waveshaperS1 cos(S2×100i×π) + S2 sin(S1×100i×π)Sample-wise trigonometric recombination; no FFT, frames, phase estimation, or overlap-add.
Random amplitude scatter(S1+S2) × [0.8 + 0.8i·U(−1,1)]Per-sample random gain. At i=0.5 the gain spans 0.4–1.2.

Operation-specific parameters

ParameterDefaultUsed byBehavior
Modulation_depth1.0All Modulation-tier operationsControls shaping/modulation strength.
Nonlinear_intensity0.5Most Nonlinear and Advanced operationsIts mapping is operation-specific. It is not used by the two magnitude-product operations.
Fold_passes4Wavefold onlyNumber of reflection passes. One pass may still leave very large values outside the threshold.
Divide_epsilon0.001Divide onlyIf |S2| ≤ epsilon, output is defined as 0 for that sample.
Geometric_polarityRestore sign of Sound 1Both magnitude productsSigned mode restores sign(S1); unsigned mode returns a nonnegative magnitude signal and can therefore contain substantial DC.
Random_seed0Random amplitude scatter onlyPositive seed = reproducible run. 0 = safely initialized unpredictable seed.
Parameter report: v0.5.1's visualization reports the controls that actually affect the running operation. Divide shows its epsilon; Wavefold shows intensity and pass count; magnitude products show polarity; Random Scatter shows intensity and seed. Inactive Mod depth / Intensity values are no longer presented as if they were live controls.

Output level

Output_scaling is a positive scalar. The four modes differ in where scaling is applied relative to peak normalization.

Output modeProcessing orderConsequence
Normalize to 0.95 (v0.2/v0.3; scaling inert)Apply Output_scaling → measure → normalize peak to 0.95For a non-silent result and positive scaling, normalization divides the scaling back out. Changing Output_scaling does not change the final samples.
Normalize to 0.95, then apply scalingNormalize to 0.95 → multiply by Output_scalingScaling survives. Values above about 1.0526 can push a normalized peak above 1.0.
Attenuate to 0.95 only if peak > 0.95 (after scaling)Apply Output_scaling → if peak exceeds 0.95, globally Scale peak to 0.95This is global attenuation, not a dynamics limiter. Signals already below 0.95 are left unchanged.
Preserve (scaling only)Multiply by Output_scaling onlyNo peak normalization. Output may exceed ±1.0.

All normalization modes guard silent output: if the measured peak is zero, normalization is skipped. The report warns if the final measured peak exceeds 1.0 and also checks for undefined samples.

Visualization and reporting

When Draw_visualization is enabled, the script draws an 8×8 summary page. It is descriptive of the actual run rather than a generic catalog of all controls.

The Info window separately reports source durations/channel counts, channel-policy consequences, each source's original start time, the operation actually applied, final output level, random seed when relevant, and warnings for peaks above 1.0 or undefined samples.

Limitations and interpretation

Division and extreme parameter values: the divide guard prevents near-zero denominator blow-ups, but other formulas can still generate very large intermediate values. Preserve mode and Normalize-then-scaling mode can therefore produce peaks above 1.0; check the measured peak in the report before export or playback in a full-scale-limited context.

Examples

Ring modulation

S1: source audio

S2: sine tone or another pitched Sound

Preset: Clean Multiply (Ring Mod)

The result is the direct sample product. For two sinusoids this produces sum- and difference-frequency components.

Rhythmic amplitude control

S1: source audio

S2: low-frequency or rhythmic control waveform

Preset: Tremolo Effect

The operation is S1 × (1 + S2×depth); the behavior depends on the actual amplitude and shape of S2.

Reproducible random scatter

Preset: Random Amplitude Scatter

Random_seed: choose a positive integer

The same inputs, parameters, and seed reproduce the same random-gain sequence.

Signed vs unsigned magnitude product

Use either magnitude-product operation and compare Restore sign of Sound 1 with Unsigned magnitude product. The unsigned version is nonnegative and can carry a strong DC component.