misceffects.lib
Miscellaneous Effects library. Its official prefix is ef.
This library contains a collection of diverse audio effects and utilities not included in other specialized Faust libraries. It includes filtering, mixing, time based, pitch shifters, and other creative or experimental signal processing components for sound design and musical applications.
The library is organized into 9 sections:
- Dynamic
- Fibonacci
- Filtering
- Dither and Noise Shaping
- Meshes
- Mixing
- Time Based
- Pitch Shifting
- Saturators
References
Dynamic
(ef.)cubicnl, (ef.)cubicnl_nodc
Cubic nonlinearity distortion. The cubicnl_nodc variant adds a
dcblocker on the output.
cubicnl is a standard Faust function.
Usage:
_ : cubicnl(drive,offset) : _
_ : cubicnl_nodc(drive,offset) : _
Where:
drive: distortion amount, between 0 and 1offset: constant added before nonlinearity to give even harmonics. Note: offset can introduce a nonzero mean - feed cubicnl output to dcblocker to remove this.
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
cubicnl_test = os.osc(440) : ef.cubicnl(0.5, 0.0);
References
- https://ccrma.stanford.edu/~jos/pasp/Cubic_Soft_Clipper.html
- https://ccrma.stanford.edu/~jos/pasp/Nonlinear_Distortion.html
(ef.)gate_mono
Mono signal gate.
gate_mono is a standard Faust function.
Usage
_ : gate_mono(thresh,att,hold,rel) : _
Where:
thresh: dB level threshold above which gate opens (e.g., -60 dB)att: attack time = time constant (sec) for gate to open (e.g., 0.0001 s = 0.1 ms)hold: hold time = time (sec) gate stays open after signal level < thresh (e.g., 0.1 s)rel: release time = time constant (sec) for gate to close (e.g., 0.020 s = 20 ms)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
gate_mono_test = os.osc(440) : ef.gate_mono(-60, 0.0001, 0.1, 0.02);
References
- http://en.wikipedia.org/wiki/Noise_gate
- http://www.soundonsound.com/sos/apr01/articles/advanced.asp
- http://en.wikipedia.org/wiki/Gating_(sound_engineering)
(ef.)gate_stereo
Stereo signal gates.
gate_stereo is a standard Faust function.
Usage
_,_ : gate_stereo(thresh,att,hold,rel) : _,_
Where:
thresh: dB level threshold above which gate opens (e.g., -60 dB)att: attack time = time constant (sec) for gate to open (e.g., 0.0001 s = 0.1 ms)hold: hold time = time (sec) gate stays open after signal level < thresh (e.g., 0.1 s)rel: release time = time constant (sec) for gate to close (e.g., 0.020 s = 20 ms)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
gate_stereo_test = os.osc(440), os.osc(441) : ef.gate_stereo(-60, 0.0001, 0.1, 0.02);
References
- http://en.wikipedia.org/wiki/Noise_gate
- http://www.soundonsound.com/sos/apr01/articles/advanced.asp
- http://en.wikipedia.org/wiki/Gating_(sound_engineering)
(ef.)gate_gain_mono
The gain signal of the mono gate: the core shared by gate_mono and
gate_stereo, which multiply their input by it. Returns a smoothed
gain between 0 and 1 following the level of the input signal.
Usage
_ : gate_gain_mono(thresh,att,hold,rel) : _
Where:
thresh: dB level threshold above which gate opens (e.g., -60 dB)att: attack time = time constant (sec) for gate to open (e.g., 0.0001 s = 0.1 ms)hold: hold time = time (sec) gate stays open after signal level < thresh (e.g., 0.1 s)rel: release time = time constant (sec) for gate to close (e.g., 0.020 s = 20 ms)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
gate_gain_mono_test = os.osc(440) : ef.gate_gain_mono(-60, 0.0001, 0.1, 0.02);
Fibonacci
(ef.)fibonacci
Fibonacci system where the current output is the current input plus the sum of the previous N outputs.
Usage
_ : fibonacci(N) : _
Where:
N: the Fibonacci system's order, where 2 is standard
Test
ef = library("misceffects.lib");
fibonacci_test = 1 : ef.fibonacci(2);
Example
Generate the famous series: [1, 1, 2, 3, 5, 8, 13, ...]
1. : ba.impulsify : fibonacci(2)
(ef.)fibonacciGeneral
Fibonacci system with customizable coefficients. The order of the system is inferred from the number of coefficients.
Usage
_ : fibonacciGeneral(wave) : _
Where:
wave: a waveform such aswaveform{1, 1}
Test
ef = library("misceffects.lib");
fibonacciGeneral_test = 1 : ef.fibonacciGeneral(waveform{2, 3});
Example:
Use the update equation y = 2*y' + 3*y'' + 4*y'''
1. : ba.impulsify : fibonacciGeneral(waveform{2, 3, 4})
(ef.)fibonacciSeq
First N numbers of the Fibonacci sequence [1, 1, 2, 3, 5, 8, ...] as parallel channels.
Usage
fibonacciSeq(N) : si.bus(N)
Where:
N: The number of Fibonacci numbers to generate as channels.
Test
ef = library("misceffects.lib");
fibonacciSeq_test = ef.fibonacciSeq(5);
Filtering
(ef.)speakerbp
Dirt-simple speaker simulator (overall bandpass eq with observed
roll-offs above and below the passband). speakerbp is a standard Faust function.
Low-frequency speaker model = +12 dB/octave slope breaking to flat near f1. Implemented using two dc blockers in series.
High-frequency model = -24 dB/octave slope implemented using a fourth-order Butterworth lowpass.
Usage
_ : speakerbp(f1,f2) : _
Where:
f1: low-frequency break point in Hz for the speaker modelf2: high-frequency lowpass cutoff in Hz for the speaker model
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
speakerbp_test = os.osc(440) : ef.speakerbp(100.0, 5000.0);
Example
Based on measured Celestion G12 (12" speaker):
speakerbp(130,5000)
(ef.)piano_dispersion_filter
Piano dispersion allpass filter in closed form.
Usage
piano_dispersion_filter(M,B,f0)
_ : piano_dispersion_filter(1,B,f0) : +(totalDelay),_ : fdelay(maxDelay) : _
Where:
M: number of first-order allpass sections (compile-time only) Keep below 20. 8 is typical for medium-sized piano strings.B: string inharmonicity coefficient (0.0001 is typical)f0: fundamental frequency in Hz
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
piano_dispersion_filter_test = os.osc(110) : ef.piano_dispersion_filter(4, 0.0001, 110);
Outputs
- MINUS the estimated delay at
f0of allpass chain in samples, provided in negative form to facilitate subtraction from delay-line length. - Output signal from allpass chain
References
- "Dispersion Modeling in Waveguide Piano Synthesis Using Tunable Allpass Filters", by Jukka Rauhala and Vesa Valimaki, DAFX-2006, pp. 71-76
- http://lib.tkk.fi/Diss/2007/isbn9789512290666/article2.pdf An erratum in Eq. (7) is corrected in Dr. Rauhala's encompassing dissertation (and below).
- http://www.acoustics.hut.fi/research/asp/piano/
(ef.)stereo_width
Stereo Width effect using the Blumlein Shuffler technique.
stereo_width is a standard Faust function.
Usage
_,_ : stereo_width(w) : _,_
Where:
w: stereo width between 0 and 1
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
stereo_width_test = os.osc(440), os.osc(550) : ef.stereo_width(0.5);
At w=0, the output signal is mono ((left+right)/2 in both channels).
At w=1, there is no effect (original stereo image).
Thus, w between 0 and 1 varies stereo width from 0 to "original".
References
- "Applications of Blumlein Shuffling to Stereo Microphone Techniques" Michael A. Gerzon, JAES vol. 42, no. 6, June 1994
(ef.)ms_enc, (ef.)ms_dec
Mid/side encoder and decoder. ms_enc converts a left/right stereo pair
into mid = (l+r)/2 and side = (l-r)/2; ms_dec is its exact inverse
(l = m+s, r = m-s), so ms_enc : ms_dec is the identity. Process the mid
and side channels independently between the two (e.g. compress the mid,
EQ or widen the side) for classic M/S mastering.
Usage
_,_ : ms_enc : _,_ // (l,r) to (m,s)
_,_ : ms_dec : _,_ // (m,s) to (l,r)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
ms_enc_test = os.osc(440), os.osc(550) : ef.ms_enc;
ms_dec_test = os.osc(440), os.osc(550) : ef.ms_enc : ef.ms_dec;
Dither and Noise Shaping
Requantization to a target bit depth, done properly: TPDF dither decorrelates the quantization error from the signal, and error-feedback noise shaping pushes it towards high frequencies where hearing is least sensitive. Use these at the very end of a chain that feeds an integer output format.
(ef.)dither
TPDF-dithered requantizer to a given bit depth: adds triangular dither of
2 LSB peak-to-peak (the sum of two independent uniform noises), then
rounds to the nearest of the 2^nbits levels covering [-1,1). Unlike the
plain ba.bitcrusher, the quantization error is decorrelated from the
signal: low-level material fades into a constant noise floor instead of
developing correlated distortion.
Usage
_ : dither(nbits) : _
Where:
nbits: target bit depth (e.g. 16), a constant numerical expression
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
dither_test = os.osc(440)*0.001 : ef.dither(16);
References
- S.P. Lipshitz, R.A. Wannamaker, J. Vanderkooy, "Quantization and Dither: A Theoretical Survey", JAES vol. 40, no. 5, 1992.
(ef.)dither_shaped
TPDF-dithered requantizer with error-feedback noise shaping: the
quantization error is fed back through (1-z^-1)^K, giving a noise
transfer function that rises at 6*K dB/octave and pushes the error energy
towards Nyquist. K = 1 or 2 are the useful orders: higher plain
difference orders boost the total noise power faster than hearing
benefits (psychoacoustically weighted shapers need dedicated
coefficients).
Usage
_ : dither_shaped(K,nbits) : _
Where:
K: noise shaping order, 1 or 2 (a constant numerical expression)nbits: target bit depth (e.g. 16), a constant numerical expression
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
dither_shaped_test = os.osc(440)*0.001 : ef.dither_shaped(2, 16);
References
- S.P. Lipshitz, R.A. Wannamaker, J. Vanderkooy, "Quantization and Dither: A Theoretical Survey", JAES vol. 40, no. 5, 1992.
- R.A. Wannamaker, "Psychoacoustically Optimal Noise Shaping", JAES vol. 40, no. 7/8, 1992.
Meshes
(ef.)mesh_square
Square Rectangular Digital Waveguide Mesh.
Usage
bus(4*N) : mesh_square(N) : bus(4*N)
Where:
N: number of nodes along each edge - a power of two (1,2,4,8,...)
Test
ef = library("misceffects.lib");
mesh_square_test = (1,0.5,-0.5,0.25) : ef.mesh_square(1);
Signal Order In and Out
The mesh is constructed recursively using 2x2 embeddings. Thus,
the top level of mesh_square(M) is a block 2x2 mesh, where each
block is a mesh(M/2). Let these blocks be numbered 1,2,3,4 in the
geometry NW,NE,SW,SE, i.e., as:
1 2
3 4
Each block has four vector inputs and four vector outputs, where the
length of each vector is M/2. Label the input vectors as Ni,Ei,Wi,Si,
i.e., as the inputs from the North, East South, and West,
and similarly for the outputs. Then, for example, the upper
left input block of M/2 signals is labeled 1Ni. Most of the
connections are internal, such as 1Eo -> 2Wi. The 8*(M/2) input
signals are grouped in the order:
1Ni 2Ni
3Si 4Si
1Wi 3Wi
2Ei 4Ei
and the output signals are:
1No 1Wo
2No 2Eo
3So 3Wo
4So 4Eo
or:
In: 1No 1Wo 2No 2Eo 3So 3Wo 4So 4Eo
Out: 1Ni 2Ni 3Si 4Si 1Wi 3Wi 2Ei 4Ei
Thus, the inputs are grouped by direction N,S,W,E, while the
outputs are grouped by block number 1,2,3,4, which can also be
interpreted as directions NW, NE, SW, SE. A simple program
illustrating these orderings is process = mesh_square(2);.
Example
Reflectively terminated mesh impulsed at one corner:
mesh_square_test(N,x) = mesh_square(N)~(busi(4*N,x)) // input to corner
with {
busi(N,x) = bus(N) : par(i,N,*(-1)) : par(i,N-1,_), +(x);
};
process = 1-1' : mesh_square_test(4); // all modes excited forever
In this simple example, the mesh edges are connected as follows:
1No -> 1Ni, 1Wo -> 2Ni, 2No -> 3Si, 2Eo -> 4Si,
3So -> 1Wi, 3Wo -> 3Wi, 4So -> 2Ei, 4Eo -> 4Ei
A routing matrix can be used to obtain other connection geometries.
References
Mixing
(ef.)dryWetMixer
Linear dry-wet mixer for an N-inputs, N-outputs effect. The dry and wet gains sum to 1 for all positions, so this mixer is mono-safe but not constant-power: total power dips at the midpoint (each channel at −6 dB).
wetAmount = 0: dry = 1.0 (0 dB), wet = 0wetAmount = 0.5: dry = 0.5 (−6 dB), wet = 0.5 (−6 dB)wetAmount = 1: dry = 0, wet = 1.0 (0 dB)
Usage
si.bus(inputs(FX)) : dryWetMixer(wetAmount, FX) : si.bus(inputs(FX))
Where:
wetAmount: the wet amount (0-1). 0 produces only the dry signal at unity, and 1 produces only the wet signal at unityFX: an arbitrary effect (N inputs and N outputs) to apply to the input bus
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
fi = library("filters.lib");
dryWetMixer_test = os.osc(440) : ef.dryWetMixer(0.5, fi.dcblocker);
(ef.)dryWetMixerConstantPower
Constant-power dry-wet mixer for an N-inputs, N-outputs effect. The dry input is scaled by cos(θ)/√2 and the wet output by sin(θ)/√2, where θ = π*wetAmount/2.
wetAmount = 0: dry = 1/√2 ≈ 0.707 (−3 dB), wet = 0wetAmount = 0.5: dry = 0.5 (−6 dB), wet = 0.5 (−6 dB)wetAmount = 1: dry = 0, wet = 1/√2 ≈ 0.707 (−3 dB)
Normalization
A standard constant-power crossfade uses bare cos/sin gains, which peak at unity (0 dB) when fully dry or fully wet and dip to 1/√2 (−3 dB) at center. This implementation divides by √2, which makes the mixer mono-safe: the sum of the dry and wet gains is bounded by 1 for all positions:
dryGain + wetGain = (cos θ + sin θ) / √2 ≤ 1
This holds because cos θ + sin θ peaks at √2 (at θ = π/4), and √2/√2 = 1. As a result, if the dry and wet paths carry correlated or in-phase material, their sum can never clip. Total power (dryGain² + wetGain²) is constant at 0.5 for all positions.
Note that the extremes attenuate by −3 dB rather than passing at unity. Use
dryWetMixer if unity passthrough at the extremes is required.
Usage
si.bus(inputs(FX)) : dryWetMixerConstantPower(wetAmount, FX) : si.bus(inputs(FX))
Where:
wetAmount: the wet amount (0-1). 0 produces only the dry signal at −3 dB and 1 produces only the wet signal at −3 dBFX: an arbitrary effect (N inputs and N outputs) to apply to the input bus
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
fi = library("filters.lib");
dryWetMixerConstantPower_test = os.osc(440) : ef.dryWetMixerConstantPower(0.5, fi.dcblocker);
(ef.)mixLinearClamp
Linear mixer for N buses, each with C channels. The output will be a sum of 2 buses
determined by the mixing index mix. 0 produces the first bus, 1 produces the
second, and so on. mix is clamped automatically. For example, mixLinearClamp(4, 1, 1)
will weight its 4 inputs by (0, 1, 0, 0). Similarly, mixLinearClamp(4, 1, 1.1)
will weight its 4 inputs by (0,.9,.1,0).
Usage
si.bus(N*C) : mixLinearClamp(N, C, mix) : si.bus(C)
Where:
N: the number of input busesC: the number of channels in each busmix: the mixing index, continuous in [0;N-1].
Test
ef = library("misceffects.lib");
mixLinearClamp_test = (1,0.5,0,0) : ef.mixLinearClamp(4, 1, 1.2);
(ef.)mixLinearLoop
Linear mixer for N buses, each with C channels. Refer to mixLinearClamp. mix
will loop for multiples of N. For example, mixLinearLoop(4, 1, 0) has the same
effect as mixLinearLoop(4, 1, -4) and mixLinearLoop(4, 1, 4).
Usage
si.bus(N*C) : mixLinearLoop(N, C, mix) : si.bus(C)
Where:
N: the number of input busesC: the number of channels in each busmix: the mixing index (N-1) selects the last bus, and 0 or N selects the 0th bus.
Test
ef = library("misceffects.lib");
mixLinearLoop_test = (1,0,0,0) : ef.mixLinearLoop(4, 1, -0.3);
(ef.)mixPowerClamp
Constant-power mixer for N buses, each with C channels. The output will be a sum of 2 buses
determined by the mixing index mix. 0 produces the first bus, 1 produces the
second, and so on. mix is clamped automatically. mixPowerClamp(4, 1, 1)
will weight its 4 inputs by (0, 1./sqrt(2), 0, 0). Similarly, mixPowerClamp(4, 1, 1.5)
will weight its 4 inputs by (0,.5,.5,0).
Usage
si.bus(N*C) : mixPowerClamp(N, C, mix) : si.bus(C)
Where:
N: the number of input busesC: the number of channels in each busmix: the mixing index, continuous in [0;N-1].
Test
ef = library("misceffects.lib");
mixPowerClamp_test = (1,0,0,0) : ef.mixPowerClamp(4, 1, 1.5);
(ef.)mixPowerLoop
Constant-power mixer for N buses, each with C channels. Refer to mixPowerClamp. mix
will loop for multiples of N. For example, mixPowerLoop(4, 1, 0) has the same effect
as mixPowerLoop(4, 1, -4) and mixPowerLoop(4, 1, 4).
Usage
si.bus(N*C) : mixPowerLoop(N, C, mix) : si.bus(C)
Where:
N: the number of input busesC: the number of channels in each busmix: the mixing index (N-1) selects the last bus, and 0 or N selects the 0th bus.
Test
ef = library("misceffects.lib");
mixPowerLoop_test = (1,0,0,0) : ef.mixPowerLoop(4, 1, -0.5);
Time Based
(ef.)echo
A simple echo effect.
echo is a standard Faust function.
Usage
_ : echo(maxDuration,duration,feedback) : _
Where:
maxDuration: the max echo duration in secondsduration: the echo duration in secondsfeedback: the feedback coefficient
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
echo_test = os.osc(440) : ef.echo(0.5, 0.25, 0.4);
(ef.)reverseEchoN
Reverse echo effect.
Usage
_ : ef.reverseEchoN(N,delay) : si.bus(N)
Where:
N: Number of output channels desired (1 or more), a constant numerical expressiondelay: echo delay (integer power of 2)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
reverseEchoN_test = os.osc(440) : ef.reverseEchoN(2, 32);
Demo
_ : dm.reverseEchoN(N) : _,_
Description
The effect uses N instances of reverseDelayRamped at different phases.
(ef.)reverseDelayRamped
Reverse delay with amplitude ramp.
Usage
_ : ef.reverseDelayRamped(delay,phase) : _
Where:
delay: echo delay (integer power of 2)phase: float between 0 and 1 giving ramp delay phase*delay
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
reverseDelayRamped_test = os.osc(440) : ef.reverseDelayRamped(32, 0.6);
Demo
_ : ef.reverseDelayRamped(32,0.6) : _,_
(ef.)uniformPanToStereo
Pan nChans channels to the stereo field, spread uniformly left to right.
Usage
si.bus(N) : ef.uniformPanToStereo(N) : _,_
Where:
N: Number of input channels to pan down to stereo, a constant numerical expression
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
uniformPanToStereo_test = os.osc(440), os.osc(550), os.osc(660) : ef.uniformPanToStereo(3);
Demo
_,_,_ : ef.uniformPanToStereo(3) : _,_
(ef.)tapeStop
A tape-stop effect, like putting a finger on a vinyl record player.
Usage:
_,_ : tapeStop(2, LAGRANGE_ORDER, MAX_TIME_SAMP,
crossfade, gainAlpha, stopAlpha, stopTime, stop) : _,_
_ : tapeStop(1, LAGRANGE_ORDER, MAX_TIME_SAMP,
crossfade, gainAlpha, stopAlpha, stopTime, stop) : _
Where:
C: The number of input and output channels.LAGRANGE_ORDER: The order of the Lagrange interpolation on the delay line. [2-3] recommended.MAX_TIME_SAMP: Maximum stop time in samplescrossfade: A crossfade in samples to apply when resuming normal playback. Crossfade is not applied during the enabling of the tape-stop.gainAlpha: During the tape-stop, lower alpha stays louder longer. Safe values are in the range [.01,2].stopAlpha:stopAlpha==1represents a linear deceleration (constant force).stopAlpha<1represents an initially weaker, then stronger force.stopAlpha>1represents an initially stronger, then weaker force. Safe values are in the range [.01,2].stopTime: Desired duration of the stop time, in samples.stop: Whenstopbecomes positive, the tape-stop effect will start. Whenstopbecomes zero, normal audio will resume via crossfade.
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
tapeStop_test = os.osc(440), os.osc(441) : ef.tapeStop(2, 3, 44100, 128, 1.0, 1.0, 22050, button("stop"));
Pitch Shifting
(ef.)transpose
A simple pitch shifter based on 2 delay lines.
transpose is a standard Faust function.
Usage
_ : transpose(w, x, s) : _
Where:
w: the window length (samples)x: crossfade duration duration (samples)s: shift (semitones)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
transpose_test = os.osc(440) : ef.transpose(1024, 512, 7);
(ef.)transpose_windowed
Delay-line pitch shifter with P overlapping Hann-windowed read taps:
the windowed-tap refinement of ef.transpose. Each tap sweeps the same
w-sample window with a phase offset of 1/P, weighted by
an.window_hann of its own phase; since Hann windows at any regular
overlap sum to a constant, the crossfade is click-free and
equal-amplitude by construction (with s = 0 the output is exactly a
delayed copy). P = 2 matches the classic two-tap topology; higher P
smears transients less at large shifts.
Usage
_ : transpose_windowed(P, w, s) : _
Where:
P: number of overlapping taps, 2 or more (a constant numerical expression)w: window length in samples (up to 65536)s: shift in semitones (positive or negative, may vary at run time)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
transpose_windowed_test = os.osc(440) : ef.transpose_windowed(2, 1024, 7);
(ef.)granular
Live granulator on an internal delay line: P voices continuously replay
Hann-windowed grains of dur seconds taken pos seconds back in the
input, each voice offset by 1/P of a grain so the voices overlap into a
continuous texture (Hann overlaps sum to a constant: with ratio = 1,
jit = 0 the output is exactly the delayed input). The grain start
position is latched when each grain begins - pos and jit can move
freely without tearing grains. ratio repitches the material inside
each grain by resampling (2 = up an octave, 0.5 = down an octave), and
jit adds a per-grain random offset to the position for the classic
granular cloud.
When repitching tonal material with jit = 0, note that the voices read
the source offset by dur/P seconds from one another: if that offset
lands near an odd half-period of a source partial, that partial cancels
between overlapping grains (ordinary granular phasiness). Choose dur
against the material, or add a little jit, to decorrelate the voices.
Usage
_ : granular(P, dur, ratio, pos, jit) : _
Where:
P: number of overlapping grain voices, 2 or more (a constant numerical expression)dur: grain duration in secondsratio: playback speed inside each grain (1 = unchanged pitch)pos: read position in seconds behind the write headjit: random position jitter in seconds, latched per grain
The latched read offset pos + jit + (ratio-1)*dur must stay within the
65536-sample internal line (about 1.36 s at 48 kHz).
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
granular_test = os.osc(440) : ef.granular(4, 0.05, 1.5, 0.2, 0.1);
(ef.)doppler_shift
Pitch shifter for signals with known fundamental frequency. Uses Doppler effect from a continuously ramping delay line, with phase-coherent phasor reset synced to the signal period. Best suited for harmonic/periodic signals like oscillator outputs.
Usage
_ : doppler_shift(freq, ratio) : _
Where:
freq: fundamental frequency of the input signal (Hz)ratio: pitch ratio (1.0 = no shift, 2.0 = octave up, 0.5 = octave down)
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
doppler_shift_test = os.sawtooth(220) : ef.doppler_shift(220, 1.5);
References
Saturators
(ef.)softclipQuadratic
Quadratic softclip nonlinearity.
Usage
_ : softclipQuadratic : _
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
softclipQuadratic_test = os.osc(440) : ef.softclipQuadratic;
References
- U. Zölzer: Digital Audio Signal Processing. John Wiley & Sons Ltd, 2022.
(ef.)wavefold
Wavefolding nonlinearity.
Usage
_ : wavefold(width) : _
Where:
width: The width of the folded section [0..1] (float).
Test
ef = library("misceffects.lib");
os = library("oscillators.lib");
wavefold_test = os.osc(440) : ef.wavefold(0.5);