Chaos Distortion — User Guide

A configurable multi-stage lo-fi processor combining drive, reflection-pass wave folding, two quantizer designs, two rate-reduction methods, positionable noise, and an explicit output-level stage.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 0.5.1 (2026) License: MIT License Repo: https://github.com/ShaiCohen-ops/Praat-plugin_AudioTools
Contents:

What this does

Chaos Distortion processes one selected Sound through a serial degradation chain. The fixed backbone is Drive → Fold → Bit Crush → Rate Reduction; optional uniform noise can be inserted before the bit crusher, before rate reduction, or after the other processing. A final output-level stage can preserve the rendered level, attenuate only when the peak exceeds 0.9, or normalize the peak to 0.9.

The script preserves the input duration and channel structure. Stereo and multichannel Sounds are not converted to mono. The processed object is named <source>_chaos_<preset>.

Two deliberately different kinds of “sample-rate reduction” are available. Band-limit uses Praat resampling with anti-alias filtering, so it removes high-frequency content rather than folding it back into the spectrum. Sample & hold repeats each retained sample for an integer block and therefore produces the hard temporal stepping and aliasing associated with unfiltered downsampling.

Key features:

Quick start

  1. Select exactly one Sound in Praat.
  2. Run Chaos_Distortion.praat.
  3. Choose a preset or Custom.
  4. Choose the fold algorithm, quantizer, rate-reduction method, noise position/seed, and output-level mode.
  5. Run the script. The Info window reports the resolved settings, including the effective sample rate used by the rate-reduction stage.
Preset scope: presets set Drive, Fold count, Fold threshold, Bit crush, Sample-rate percent, Add noise, and Noise amount. They do not override Fold_algorithm, Quantizer, Rate_reduction, Noise_position, Random_seed, or Output_level. The same named preset can therefore sound different when those mode choices change.

Processing pipeline

1. Drive x1 = input × Drive 2. Fold repeat Fold_count reflection passes around ±Fold_threshold 3. Optional Noise position A if selected: add uniform noise before bit crush 4. Bit Crush legacy step quantizer OR true 2^N-level quantizer 5. Optional Noise position B if selected: add uniform noise before rate reduction 6. Rate Reduction anti-aliased band-limit OR integer-block sample & hold 7. Optional Noise position C if selected: add uniform noise after processing 8. Output Level Preserve / conditional global attenuation / normalize to 0.9

Noise is added at one of the three selected positions, not at all three. Its position matters: noise placed before the crusher is itself quantized; noise placed before band-limited rate reduction is filtered by that stage; noise added last remains full-rate and full-resolution.

Parameters & presets

Form parameters

ParameterDefaultMeaning
PresetDefault (balanced)Five named presets plus Custom.
Drive3.0Positive pre-gain applied before folding.
Fold_count3Integer number of reflection passes. 0 disables folding; negative values are rejected.
Fold_threshold0.7Positive amplitude threshold used by each reflection pass.
Fold_algorithmSingle reflection per passOne sign branch per pass, or the v0.2 legacy double-reflection behavior.
Bit_crush6Natural-number resolution parameter; higher values give finer quantization. Exact mapping depends on Quantizer.
QuantizerStep 1/2^N, unboundedLegacy step quantizer or true 2^N levels over −1…+1.
Sample_rate_percent30Requested percentage of the original sample rate. Values above 100 are treated as 100%; effective rates below 1000 Hz are floored at 1000 Hz.
Rate_reductionBand-limitAnti-aliased resampling or sample & hold with true aliasing.
Add_noiseYesEnable uniform random noise.
Noise_amount0.03Noise is drawn independently in [−amount,+amount].
Noise_positionAfter processingBefore bit crush, before rate reduction, or after processing.
Random_seed00 = unpredictable; positive = reproducible noise realization.
Output_levelNormalize to 0.9Preserve; attenuate only if peak > 0.9; or normalize to 0.9.
Draw_visualizationYesDraw the diagnostic page.
Play_resultYesPlay the processed Sound after rendering.

Named presets

PresetDriveFoldsThresholdBitsSR requestNoise
Default (balanced)3.030.7630%On, 0.03
Gentle Grit1.610.7885%Off
Heavy Crush4.550.7440%On, 0.05
Lo-Fi Glitch2.220.7320%On, 0.04
Mild Boost/Crush1.2500.712100%Off
Mild Boost/Crush is not a clean bypass. Folding and rate reduction are off and noise is disabled, but the signal is still multiplied by 1.25 and quantized at 12 bits according to the selected Quantizer. With the default Output level, the final result is also normalized to 0.9.

Algorithm details

Drive and reflection-pass folding

Drive is a simple multiplication. It does not clip by itself. Folding is then applied for Fold_count passes. This is not an infinite or periodic triangular wavefolder: with high Drive and too few passes, a sample can finish outside ±Fold_threshold.

Single reflection per pass: if x > +T: x = T - (x - T) else if x < -T: x = -T - (x + T) Double reflection per pass (v0.2 legacy): test/refelect positive side then independently test/reflect negative side T = Fold_threshold

For the transfer visualization, the first fold starts when the input magnitude reaches approximately T / Drive. The graph therefore marks vertical first-fold input thresholds at ±Fold_threshold/Drive.

Bit crushing: two mappings

Legacy step quantizer
round(x × 2^N) / 2^N

This sets a quantization step of 1/2^N but does not clamp the signal. Across −1…+1 it produces 2×2^N+1 possible values, not 2^N; values outside that range remain possible.
True 2^N-level quantizer
First clamps to −1…+1, then maps that interval to exactly 2^N uniformly spaced levels.

This behaves more like a conventional fixed-range N-bit amplitude quantizer.

Rate reduction

Band-limit (resample, anti-aliased)
The Sound is resampled down with Praat precision 50 and then back to the original sampling frequency. Anti-alias filtering removes content above the new Nyquist frequency. This produces bandwidth reduction, not intentional alias folding.
Sample & hold (true aliasing)
The script repeats each block leader for an integer number of samples. The achievable rate is therefore sr/N for whole-number N. The Info window reports the nearest actual rate and warns when it differs materially from the requested percentage.

The requested reduced rate is never allowed below 1000 Hz. If the requested percentage is 100% or higher, the stage is off. For sample & hold, the percentage displayed in the report and visualization is the effective percentage after resolving the integer hold factor.

Noise and random seed

When enabled, the script adds independent uniform random values from −Noise_amount to +Noise_amount to each sample. Random_seed = 0 initializes unpredictably; a positive seed reproduces the same random sequence. After a seeded render, the script restores the generator to an unpredictable state so it does not determine later random operations in the Praat session.

Output level

Visualization

The optional 8-inch diagnostic page contains five components:

Notes & limitations

Applications

Controlled lo-fi
Gentle Grit with Band-limit mode for reduced bandwidth and quantization without deliberate sample-rate aliasing.
Aggressive digital destruction
Heavy Crush or Lo-Fi Glitch with low-bit quantization and Sample & hold for stepped, aliased textures.
Noise as part of the device
Place noise before Bit Crush or before Rate Reduction so the noise itself is quantized or rate-reduced.
Full-rate hiss layer
Keep Noise position After processing when the noise should sit above the degraded signal rather than pass through the degradation stages.