Audio Effects
Whether you’re using a synth or a sample, you can apply any of the following built-in audio effects. As you might suspect, the effects can be chained together, and they accept a pattern string as their argument.
Filters
Filters are an essential building block of subtractive synthesis. Strudel comes with 3 types of filters:
- low-pass filter: low frequencies may pass, high frequencies are cut off
- high-pass filter: high frequencies may pass, low frequencies are cut off
- band-pass filters: only a frequency band may pass, low and high frequencies around are cut off
Each filter has 2 parameters:
- cutoff: the frequency at which the filter starts to work. e.g. a low-pass filter with a cutoff of 1000Hz allows frequencies below 1000Hz to pass.
- q-value: Controls the resonance of the filter. Higher values sound more aggressive. Also see Q-Factor
lpf
cutoff, ctf, lpApplies the cutoff frequency of the low-pass filter.
When using mininotation, you can also optionally add the 'lpq' parameter, separated by ':'.
- frequency (number|Pattern): audible between 0 and 20000
s("bd sd,hh*3").lpf("<4000 2000 1000 500 200 100>")s("bd*8").lpf("1000:0 1000:10 1000:20 1000:30")lpq
resonanceControls the low-pass q-value.
- q (number|Pattern): resonance factor between 0 and 50
s("bd sd,hh*4").lpf(2000).lpq("<0 10 20 30>")hpf
hp, hcutoffApplies the cutoff frequency of the high-pass filter.
When using mininotation, you can also optionally add the 'hpq' parameter, separated by ':'.
- frequency (number|Pattern): audible between 0 and 20000
s("bd sd,hh*4").hpf("<4000 2000 1000 500 200 100>")s("bd sd,hh*4").hpf("<2000 2000:25>")hpq
hresonanceControls the high-pass q-value.
- q (number|Pattern): resonance factor between 0 and 50
s("bd sd,hh*4").hpf(2000).hpq("<0 10 20 30>")bpf
bandf, bpSets the center frequency of the band-pass filter. When using mininotation, you can also optionally supply the 'bpq' parameter separated by ':'.
- frequency (number|Pattern): center frequency
s("bd sd,hh*3").bpf("<1000 2000 4000 8000>")bpq
bandqSets the band-pass q-factor (resonance).
- q (number|Pattern): q factor
s("bd sd").bpf(500).bpq("<0 1 2 3>")ftype
Sets the filter type. The 24db filter is more aggressive. More types might be added in the future.
- type (number|Pattern): 12db (default) or 24db
note("<c2 e2 f2 g2>")
.sound('sawtooth')
.lpf(500)
.bpenv(4)
.ftype("<12db 24db>")vowel
Formant filter to make things sound like vowels.
- vowel (string|Pattern): You can use a e i o u.
note("c2 <eb2 <g2 g1>>").s('sawtooth')
.vowel("<a e i <o u>>")Amplitude Envelope
The amplitude envelope controls the dynamic contour of a sound. Strudel uses ADSR envelopes, which are probably the most common way to describe an envelope:
![]()
attack
attAmplitude envelope attack time: Specifies how long it takes for the sound to reach its peak value, relative to the onset.
- attack (number|Pattern): time in seconds.
note("c3 e3").attack("<0 .1 .5>")decay
Amplitude envelope decay time: the time it takes after the attack time to reach the sustain level. Note that the decay is only audible if the sustain value is lower than 1.
- time (number|Pattern): decay time in seconds
note("c3 e3").decay("<.1 .2 .3 .4>").sustain(0)sustain
susAmplitude envelope sustain level: The level which is reached after attack / decay, being sustained until the offset.
- gain (number|Pattern): sustain level between 0 and 1
note("c3 e3").decay(.2).sustain("<0 .1 .4 .6 1>")release
relAmplitude envelope release time: The time it takes after the offset to go from sustain level to zero.
- time (number|Pattern): release time in seconds
note("c3 e3 g3 c4").release("<0 .1 .4 .6 1>/2")Filter Envelope
Each filter can receive an additional filter envelope controlling the cutoff value dynamically. It uses an ADSR envelope similar to the one used for amplitude. There is an additional parameter to control the depth of the filter modulation: lpenv|hpenv|bpenv. This allows you to play subtle or huge filter modulations just the same by only increasing or decreasing the depth.
note("[c eb g <f bb>](3,8,<0 1>)".sub(12))
.s("<sawtooth>/64")
.lpf(sine.range(500,3000).slow(16))
.lpa(0.005)
.lpd(perlin.range(.02,.2))
.lps(perlin.range(0,.5).slow(3))
.lpq(sine.range(2,10).slow(32))
.release(.5)
.lpenv(perlin.range(1,8).slow(2))
.ftype('24db')
.room(1)
.juxBy(.5,rev)
.sometimes(add(note(12)))
.stack(s("bd*2").bank('RolandTR909'))
.gain(.5)There is one filter envelope for each filter type and thus one set of envelope filter parameters preceded either by lp, hp or bp:
lpattack,lpdecay,lpsustain,lprelease,lpenv: filter envelope for the lowpass filter.- alternatively:
lpa,lpd,lps,lprandlpe.
- alternatively:
hpattack,hpdecay,hpsustain,hprelease,hpenv: filter envelope for the highpass filter.- alternatively:
hpa,hpd,hps,hprandhpe.
- alternatively:
bpattack,bpdecay,bpsustain,bprelease,bpenv: filter envelope for the bandpass filter.- alternatively:
bpa,bpd,bps,bprandbpe.
- alternatively:
lpattack
lpaSets the attack duration for the lowpass filter envelope.
- attack (number|Pattern): time of the filter envelope
note("<c2 e2 f2 g2>")
.sound('sawtooth')
.lpf(500)
.lpa("<.5 .25 .1 .01>/4")
.lpenv(4)lpdecay
lpdSets the decay duration for the lowpass filter envelope.
- decay (number|Pattern): time of the filter envelope
note("<c2 e2 f2 g2>")
.sound('sawtooth')
.lpf(500)
.lpd("<.5 .25 .1 0>/4")
.lps(0.2)
.lpenv(4)lpsustain
lpsSets the sustain amplitude for the lowpass filter envelope.
- sustain (number|Pattern): amplitude of the lowpass filter envelope
note("<c2 e2 f2 g2>")
.sound('sawtooth')
.lpf(500)
.lpd(.5)
.lps("<0 .25 .5 1>/4")
.lpenv(4)lprelease
lprSets the release time for the lowpass filter envelope.
- release (number|Pattern): time of the filter envelope
note("<c2 e2 f2 g2>")
.sound('sawtooth')
.clip(.5)
.lpf(500)
.lpenv(4)
.lpr("<.5 .25 .1 0>/4")
.release(.5)lpenv
lpeSets the lowpass filter envelope modulation depth.
- modulation (number|Pattern): depth of the lowpass filter envelope between 0 and n
note("<c2 e2 f2 g2>")
.sound('sawtooth')
.lpf(500)
.lpa(.5)
.lpenv("<4 2 1 0 -1 -2 -4>/4")Dynamics
gain
Controls the gain by an exponential amount.
- amount (number|Pattern): gain.
s("hh*8").gain(".4!2 1 .4!2 1 .4 1")velocity
Sets the velocity from 0 to 1. Is multiplied together with gain.
s("hh*8")
.gain(".4!2 1 .4!2 1 .4 1")
.velocity(".4 1")Panning
jux
The jux function creates strange stereo effects, by applying a function to a pattern, but only in the right-hand channel.
s("lt ht mt ht hh").jux(rev)juxBy
juxbyJux with adjustable stereo width. 0 = mono, 1 = full stereo.
s("lt ht mt ht hh").juxBy("<0 .5 1>/2", rev)pan
Sets position in stereo.
- pan (number|Pattern): between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)
s("[bd hh]*2").pan("<.5 1 .5 0>")Waveshaping
coarse
fake-resampling for lowering the sample rate. Caution: This effect seems to only work in chromium based browsers
- factor (number|Pattern): 1 for original 2 for half, 3 for a third and so on.
s("bd sd,hh*4").coarse("<1 4 8 16 32>")crush
bit crusher effect.
- depth (number|Pattern): between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).
s("<bd sd>,hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>")shape
Wave shaping distortion. CAUTION: it might get loud
- distortion (number|Pattern): between 0 and 1
s("bd sd,hh*4").shape("<0 .2 .4 .6 .8>")Global Effects
Local vs Global Effects
While the above listed “local” effects will always create a separate effects chain for each event, global effects use the same chain for all events of the same orbit:
orbit
An orbit is a global parameter context for patterns. Patterns with the same orbit will share the same global effects.
- number (number|Pattern):
stack(
s("hh*3").delay(.5).delaytime(.25).orbit(1),
s("~ sd").delay(.5).delaytime(.125).orbit(2)
)delay
Sets the level of the delay signal.
When using mininotation, you can also optionally add the 'delaytime' and 'delayfeedback' parameter, separated by ':'.
- level (number|Pattern): between 0 and 1
s("bd").delay("<0 .25 .5 1>")s("bd bd").delay("0.65:0.25:0.9 0.65:0.125:0.7")delaytime
delayt, dtSets the time of the delay effect.
- seconds (number|Pattern): between 0 and Infinity
s("bd").delay(.25).delaytime("<.125 .25 .5 1>").slow(2)delayfeedback
delayfb, dfbSets the level of the signal that is fed back into the delay. Caution: Values >= 1 will result in a signal that gets louder and louder! Don't do it
- feedback (number|Pattern): between 0 and 1
s("bd").delay(.25).delayfeedback("<.25 .5 .75 1>").slow(2)room
Sets the level of reverb.
When using mininotation, you can also optionally add the 'size' parameter, separated by ':'.
- level (number|Pattern): between 0 and 1
s("bd sd").room("<0 .2 .4 .6 .8 1>")s("bd sd").room("<0.9:1 0.9:4>")roomsize
size, szSets the room size of the reverb, see room.
- size (number|Pattern): between 0 and 10
s("bd sd").room(.8).roomsize("<0 1 2 4 8>")Next, we’ll look at strudel’s support for Csound.