Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Effects

Signal processing effects for shaping sound character.

Saturator

Soft clipping distortion based on analog saturation curves.

use quiver::analog::{Saturator, saturation};

let sat = patch.add("saturator", Saturator::new(saturation::tanh_sat));

Inputs

PortSignalDescription
inAudioInput signal
driveUnipolar CVSaturation amount

Output

PortSignalDescription
outAudioSaturated output

Saturation Types

FunctionCharacter
tanh_satSmooth, tube-like
soft_clipAdjustable knee
asym_satEven harmonics
diode_clipHard, aggressive

Wavefolder

Creates complex harmonics by reflecting the signal about a threshold. Supports opt-in oversampling via set_oversample. type_id: wavefolder.

let folder = patch.add("folder", Wavefolder::new(1.0)); // threshold

Inputs

PortSignalDescription
inAudioInput signal
thresholdUnipolar CVFold threshold (default = constructor value)

Output

PortSignalDescription
outAudioFolded output

The Folding Process

Input:   ╱╲
        ╱  ╲
       ╱    ╲

1 Fold: ╱╲╱╲
       ╱    ╲

2 Folds: ╱╲╱╲╱╲╱╲
        ╱      ╲

$$y = \sin(f \cdot \pi \cdot x)$$

Where $f$ is the fold amount.


Crosstalk

Simulates channel bleed between left and right.

let crosstalk = patch.add("xtalk", Crosstalk::new());

Inputs

PortSignalDescription
leftAudioLeft channel
rightAudioRight channel
amountUnipolar CVBleed amount (0-10%)

Outputs

PortSignalDescription
leftAudioLeft with right bleed
rightAudioRight with left bleed

The Effect

$$L_{out} = L_{in} + \text{amount} \cdot R_{in}$$ $$R_{out} = R_{in} + \text{amount} \cdot L_{in}$$

Adds subtle width and analog character.


Ground Loop

Simulates 50/60Hz power supply hum.

let hum = patch.add("hum", GroundLoop::new(44100.0));

Inputs

PortSignalDescription
amountUnipolar CVHum level

Output

PortSignalDescription
outAudioHum signal

Configuration

let hum = GroundLoop::new(44100.0)
    .with_frequency(60.0)   // 60Hz (US) or 50Hz (EU)
    .with_harmonics(3);     // Include 2nd and 3rd harmonics

Mix very subtly for vintage authenticity.


Scope

Real-time waveform visualization.

let scope = patch.add("scope", Scope::new(44100.0));

Inputs

PortSignalDescription
inAudioSignal to display
triggerGateTrigger sync

Trigger Modes

ModeDescription
FreeContinuous display
RisingEdgeSync on positive zero-cross
FallingEdgeSync on negative zero-cross
SingleOne-shot capture

Reading the Buffer

let waveform = scope.buffer();
// Vec<f64> of recent samples

Spectrum Analyzer

FFT-based frequency analysis.

let analyzer = patch.add("spectrum", SpectrumAnalyzer::new(44100.0));

Input

PortSignalDescription
inAudioSignal to analyze

Reading Data

let bins = analyzer.bins();           // Frequency bins
let mags = analyzer.magnitudes();     // dB values
let peak = analyzer.peak_frequency(); // Dominant frequency

Level Meter

RMS and peak level monitoring.

let meter = patch.add("meter", LevelMeter::new(44100.0));

Input

PortSignalDescription
inAudioSignal to meter

Reading Levels

let rms = meter.rms();       // RMS level in volts
let peak = meter.peak();     // Peak level
let rms_db = meter.rms_db(); // RMS in dB

Peak Hold

let meter = LevelMeter::new(44100.0)
    .with_peak_hold(500.0);  // 500ms hold time

Distortion

Waveshaping distortion with four selectable algorithms (soft clip, hard clip, foldback, asymmetric), a one-pole tone control, dry/wet mix, and opt-in oversampling (set_oversample). type_id: distortion.

let dist = patch.add("dist", Distortion::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
driveUnipolar CV0-10VDrive into the shaper, default 0.5
toneUnipolar CV0-10VTone (one-pole lowpass), default 0.5
modeUnipolar CV0-10VAlgorithm select (4 modes)
mixUnipolar CV0-10VDry/wet, default fully wet

Output

PortSignalDescription
outAudioDistorted output

Bitcrusher

Lo-fi bit-depth and sample-rate reduction. type_id: bitcrusher.

let crush = patch.add("crush", Bitcrusher::new());

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
bitsUnipolar CV0-10VBit-depth reduction (~1–16 bits), default 0.5
downsampleUnipolar CV0-10VSample-rate reduction

Output

PortSignalDescription
outAudioCrushed output

Delay Line

Delay of up to 2 seconds with feedback and wet/dry mix; slew-smoothed delay time for CV-modulated effects. Breaks feedback cycles. type_id: delay_line.

let delay = patch.add("delay", DelayLine::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
timeUnipolar CV0-10VDelay time (1 ms–2 s, exponential), default 0.5
feedbackUnipolar CV0-10VFeedback (0–0.99)
mixUnipolar CV0-10VDry/wet, default 0.5

Output

PortSignalDescription
outAudioMixed dry + delayed output

Chorus

Three-voice modulated-delay chorus with a mono and a stereo-spread output. type_id: chorus.

let chorus = patch.add("chorus", Chorus::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
rateUnipolar CV0-10VLFO rate (0.1–5 Hz), default 0.3
depthUnipolar CV0-10VModulation depth (0–25 ms), default 0.5
mixUnipolar CV0-10VDry/wet, default 0.5

Outputs

PortSignalDescription
outAudioMono mixed output
leftAudioLeft stereo-spread output
rightAudioRight stereo-spread output

Flanger

Short-modulated-delay flanger with feedback; mono in, stereo out via a spread control. out mirrors left for backward compatibility. type_id: flanger.

let flanger = patch.add("flanger", Flanger::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
rateUnipolar CV0-10VLFO rate, default 0.3
depthUnipolar CV0-10VSweep depth, default 0.5
feedbackBipolar CV±5VFeedback (−0.95–0.95)
mixUnipolar CV0-10VDry/wet, default 0.5
spreadUnipolar CV0-10VStereo L/R decorrelation (0 = mono, 1 = 180°), default 0.5

Outputs

PortSignalDescription
outAudioLegacy mono output (mirrors left)
leftAudioLeft channel
rightAudioRight channel (phase-offset sweep)

Phaser

Cascaded-allpass phaser (2/4/6 selectable stages) with feedback; mono in, stereo out with a spread control. out mirrors left. type_id: phaser.

let phaser = patch.add("phaser", Phaser::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
rateUnipolar CV0-10VLFO rate, default 0.3
depthUnipolar CV0-10VNotch sweep depth, default 0.7
feedbackBipolar CV±5VFeedback (−0.95–0.95)
mixUnipolar CV0-10VDry/wet, default 0.5
stagesUnipolar CV0-10VAllpass stage count (<0.33 → 2, <0.66 → 4, else 6)
spreadUnipolar CV0-10VStereo L/R decorrelation, default 0.5

Outputs

PortSignalDescription
outAudioLegacy mono output (mirrors left)
leftAudioLeft channel
rightAudioRight channel (phase-offset notch sweep)

Tremolo

Amplitude-modulation tremolo with a sine-to-triangle shape blend. type_id: tremolo.

let trem = patch.add("trem", Tremolo::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
rateUnipolar CV0-10VLFO rate (0.1–20 Hz), default 0.3
depthUnipolar CV0-10VModulation depth, default 0.5
shapeUnipolar CV0-10VLFO shape blend (sine ↔ triangle)

Output

PortSignalDescription
outAudioAmplitude-modulated output

Vibrato

Pitch-modulation vibrato via a modulated delay line; defaults fully wet. type_id: vibrato.

let vib = patch.add("vib", Vibrato::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
rateUnipolar CV0-10VLFO rate (0.1–15 Hz), default 0.3
depthUnipolar CV0-10VPitch-modulation depth, default 0.5
mixUnipolar CV0-10VDry/wet, default fully wet

Output

PortSignalDescription
outAudioPitch-modulated output

Reverb

Freeverb-style algorithmic reverb (8 comb + 4 allpass) with size, damping, mix, and pre-delay. Stereo output. type_id: reverb.

let reverb = patch.add("reverb", Reverb::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
sizeUnipolar CV0-10VRoom size / decay, default 0.5
dampingUnipolar CV0-10VHigh-frequency damping, default 0.5
mixUnipolar CV0-10VDry/wet, default 0.5
predelayUnipolar CV0-10VPre-delay (0–100 ms)

Outputs

PortSignalDescription
leftAudioLeft reverb channel
rightAudioRight reverb channel

Pitch Shifter

Granular (two-grain, crossfaded) real-time pitch shifter. type_id: pitch_shifter.

let shift = patch.add("shift", PitchShifter::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio input
shiftBipolar CV±5VPitch shift (±24 semitones)
windowUnipolar CV0-10VGrain window (10–100 ms), default 0.5
mixUnipolar CV0-10VDry/wet, default fully wet

Output

PortSignalDescription
outAudioPitch-shifted output

Granular

Granular processor: records the input into a circular buffer and plays overlapping Hann-windowed grains. type_id: granular.

let gran = patch.add("gran", Granular::new(44100.0));

Inputs

PortSignalRangeDescription
inAudio±5VAudio recorded into the buffer
positionUnipolar CV0-10VPlayback position, default 0.5
sizeUnipolar CV0-10VGrain size (10–500 ms), default 0.3
densityUnipolar CV0-10VGrains per second (1–20), default 0.5
pitchBipolar CV±5VPitch shift (±24 semitones)
sprayUnipolar CV0-10VPosition randomization, default 0.1
freezeGate0/5VStops recording while high

Output

PortSignalDescription
outAudioGranular output

Vocoder

Channel vocoder: per-band envelope followers on the modulator impose its spectral envelope onto the carrier. type_id: vocoder.

let voc = patch.add("voc", Vocoder::new(44100.0));

Inputs

PortSignalRangeDescription
carrierAudio±5VCarrier (typically an oscillator)
modulatorAudio±5VModulator (typically voice)
bandsUnipolar CV0-10VBand count (4–16), default 1.0
attackUnipolar CV0-10VEnvelope-follower attack, default 0.3
releaseUnipolar CV0-10VEnvelope-follower release, default 0.3

Output

PortSignalDescription
outAudioVocoded output

Building Effect Chains

Serial Processing

// Input → Saturator → Filter → Output
patch.connect(input, sat.in_("in"))?;
patch.connect(sat.out("out"), vcf.in_("in"))?;
patch.connect(vcf.out("lp"), output)?;

Parallel Processing

// Dry/wet mix
patch.connect(input, mult.in_("in"))?;
patch.connect(mult.out("out_1"), effect.in_("in"))?;  // Wet
patch.connect(mult.out("out_2"), xfade.in_("a"))?;    // Dry
patch.connect(effect.out("out"), xfade.in_("b"))?;    // Wet

Feedback Loop

// With unit delay to prevent infinite loop
patch.connect(effect.out("out"), delay.in_("in"))?;
patch.connect(delay.out("out"), atten.in_("in"))?;  // Feedback amount
patch.connect(atten.out("out"), effect.in_("in"))?;