# 2.2 Player Effects Effects can be added to a Player in the same way that its attributes are changed; using keyword arguments. Just as with the Player attributes, these can be a single value, or a sequence. This page contains descriptions of the different effects available in FoxDot and how to apply them. Most effects are applied using a single value, such as `pan`, but some have a single "parent" and one or more "child" effect. One example is `slide`, which is the parent, and `slidedelay` is the child. If the parent effect is set to 0, then the effect is not applied. Child values of 0 are still applied if the parent is nonzero ``` python # Slide effect added p1 >> pluck(dur=4, slide=1, slidedelay=0.5) # Slide effect not added p1 >> pluck(dur=4, slide=0, slidedelay=0.5) # Slide effect added, with zero delay p1 >> pluck(dur=4, slide=1, slidedelay=0) ``` ## Sustain __Keywords: `sus`, `blur=1`__ The keyword argument sus is used to set the "sustain" of a note, which means how long the sound of the note lasts. By default this is the same as the note’s duration (set using the `dur` keyword) and is a value measured in terms of "beats". The following code will play a 1-beat note one repeat with a half-beat sustain: ``` python # One beat duration, half-beat duration p1 >> pluck(dur=1, sus=1/2) ``` Use `blur` to create a "legato" effect (a word which means "tied together" in Italian). This is a musical term that refers to how smoothly notes follow on from one another, or blur together. The `sus` value is multiplied by the current `blur` value such that the following code doubles the length of every other note’s sustain: ``` python # Doubles the length of every other note p1 >> pluck(dur=PDur(3,8), blur=[1, 2]) ``` ## Stereo Panning __Keyword: `pan`__ Panning (in audio) is the distribution of sound across multiple speakers. Currently FoxDot only uses two output channels (for the left and right speaker) but there are plans to expand this for multiple speakers. To change the panning of a sound, use the `pan` and set the value between -1 (hard left) and 1 (hard right). A `pan` value of 0 sends the audio signal out of both speakers equally. ``` python # Alternate between left, center, and right p1 >> pluck(pan = [-1, 0, 1]) # Play two notes at the same time, but in different speakers p1 >> pluck((0, 4), pan=(-1,1)) # Gradually move the sound's panning from left to right using a "linvar" p1 >> pluck([0, 2, 4, 7], dur=1/4, pan=linvar([-1,1],8)) ``` ## Frequency Modifier __Keyword: `fmod`__ This adds a value to the frequency used to generate a note, but only in one of the channels. For example, starting a player with no instructions will continually play a note on middle C, which is 261.6 Hz, through both speaker channels. Using `fmod = 10` will play the note at 261.6 Hz in one channel, and 271.6 Hz in the other. This creates a noticeable "dissonance" or an "atonal" sound because the frequencies are so close together. Using a smaller value, such as 2, creates a sort of [flanger](https://en.wikipedia.org/wiki/Flanging) effect: ``` python # Simple flanger effect p1 >> pluck(fmod=2) # Vary the effect over time p1 >> pluck(fmod=linvar([-10,10],8), dur=1/4, sus=1) ``` ## Vibrato __Keywords: `vib`, `vibdepth = 0.02`__ Vibrato is a musical term that refers to a continual modulation of pitch i.e. changing over time. You can set the rate of the vibrato of a note by using the `vib` keyword and the depth (the size of the modulation) of the vibrato by using the `vibdepth` keyword. The depth defaults to 0.02, which means the vibrato fluctuates between +/- the note’s frequency multiplied by 0.02. You can also think of it as fluctuating between 99% and 101% of the frequency value. ``` python p1 >> pads(dur=4, vib=4) p1 >> pads(dur=4, vib=4, vibdepth=0.1) p1 >> pads(dur=4, vib=4, vibdepth=1) ``` ## Slide __Keywords: `slide`, `slidedelay = 0`__ This is used to change a note’s frequency over time. The frequency "slides" to `#!supercollider (1 + n) * freq` where n is the value supplied to the `slide` keyword. For example, a `slide` value of `1` will slide the frequency to twice its original value (one octave up). A `slide` value of `-1` will slide to a frequency of `0`. ``` python # Slide one octave up p1 >> pluck(dur=4, slide=1) # Slide to 0 p1 >> pluck(dur=4, slide=-1) # Delay the slide effect to start half way through the note p1 >> pluck(dur=4, slide=0.5, slidedelay=0.5) ``` ## Slide from __Keywords: `slidefrom`, `slidedelay = 0`__ Similar to slide, this effect also changes a note’s frequency over time, but you specify where the slide starts. The frequency "slides" from `#!supercollider (1 + n) * freq` where n is the value supplied to the `slidefrom` keyword and finishes at the note’s frequency. For example, a `slidefrom` value of 1 will slide the frequency from twice its original value (one octave up). A `slidefrom` value of -1 will `slide` from a frequency of 0. By default the slide effect starts immediately after the note begins. To delay the start of the slide, you can use the `slidedelay` keyword. This should be a value between 0 (the start of the note) and 1 (the end of the note). ``` python # Slide from one octave up p1 >> pluck(dur=4, slidefrom=1) # Slide from 0 p1 >> pluck(dur=4, slidefrom=-1) # Delay the slide effect to start half way through the note p1 >> pluck(dur=4, slidefrom=0.5, slidedelay=0.5) ``` ## Pitch bend __Keywords: `bend`, `benddelay = 0`__ Another effect similar to slide, pitch bend changes the frequency of a note over a time but also returns to its original frequency by the end of the note. Other than that it works exactly the same as slide. ``` python # Bends one octave up and back again p1 >> pluck(dur=4, bend=1) # Bend to 0 and back again p1 >> pluck(dur=4, bend=-1) # Delay the bend effect to start half way through the note p1 >> pluck(dur=4, slide=0.5, bend=0.5) ``` ## Chop __Keyword: `chop`__ This "chops" the audio signal into "n" parts, where "n" is the value you supply to the keyword argument. It uses the sustain of the note (set using `sus`) to determine the size of the parts, so you can also combine `chop` and `sus` to create interesting effects. ``` python # Chop a sound into 4 parts p1 >> pluck([0,1,2,3], dur=4, chop=4) # If the duration varies, the sizes of chop will vary too p1 >> pluck([0,[4,6,7]], dur=PDur(3,8), chop=4) # Changing a single value for "sus" evens out the sizes and creates a nice overlapping echo effect p1 >> pluck([0,[4,6,7]], dur=PDur(3,8), chop=4, sus=2) ``` ## Coarse __Keyword: `coarse`__ This is similar to "chop" but differs in that the audio signal isn’t being "chopped" up, the control rate (the frequency of notes / the playback rate for samples) is. This can be useful in several situations. The first is when playing samples using the play synth: Using chop essentially only plays half the audio as the other half is being muted by the “chop” effect. Using coarse will essentially pause the sound and resume it after a slight delay. It does this by setting the playback rate to 0 whereas chop would set the amplitude to 0. Listen to the difference by running the code below in FoxDot: ``` python # Using chop c1 >> play("C", dur=4, chop=16, coarse=0) # Using coarse c1 >> play("C", dur=4, coarse=16, chop=0) ``` Another use for coarse would be for when you get "clipping" sounds when using chop. This occurs when an amplitude goes to 0 very quickly and sounds like a tiny "pop". Run these lines of code in FoxDot and listen to the differences: ``` python b1 >> bass(dur=2, chop=4, coarse=0) b1 >> bass(dur=2, coarse=4, chop=0) ``` The line using `coarse=4` sounds that little bit cleaner. Unfortunately this doesn’t always happen and the `coarse` effect can’t always be applied to some synths, for example `klank`. ## High-pass filter __Keywords: `hpf`, `hpr = 1`__ A non-trivial sound is made up of a combination of sound waves vibrating at various frequencies and amplitudes, and some of these can be "filtered out" from a signal using a filter. This is often known as subtractive synthesis. A high pass filter will remove parts of a signal that are below a certain frequency i.e. only lets frequencies through that are higher than the threshold. This can be applied in FoxDot simply by setting the `hpf` (short for high-pass filter) value: ``` python # Set the high pass filter cutoff to 2000 Hz d1 >> play("x-o-", hpf=2000) # Set the cutoff to change over time using a linvar d1 >> play("x-o-", hpf=linvar([0,2000],32)) ``` You can also set the high-pass resonance for the filter using the `hpr` keyword. This is sometimes referred to as "rq" or "hpq". As this value decreases, the overtones near the cutoff value are boosted – a value close to 0 will sound like a sine wave oscillating at the value set using `hpf`. Be careful of very small and very large values as you might get very loud sounds! ``` python # Set the high pass filter cutoff to 2000 Hz d1 >> play("x-o-", hpf=2000) # Set the resonance to 0.2 - can you hear the difference? d1 >> play("x-o-", hpf=2000, hpr=0.2) # Set the cutoff *and* resonance to change over time using linvar d1 >> play("x-o-", hpf=linvar([0,2000],32), hpr=linvar([1,0.1],28)) ``` ## Low-pass filter __Keywords: `lpf`, `lpr = 1`__ Just as the high pass filter only allows through frequencies within an audio signal above a certain cutoff, the low pass filter only allows through frequencies within an audio signal below a certain cutoff. The low pass resonance, `lpr`, works in the same way that the high pass resonance does too. ``` python # Set the low pass filter cutoff to 400 Hz d1 >> play("x-o-", lpf=400) # Changing the resonance - can you hear the difference? d1 >> play("x-o-", lpf=400, lpr=0.2) # Use a linvar to vary both values over time d1 >> play("x-o-", lpf=linvar([500,5000],32), lpr=linvar([1,0.1],28)) ``` ## Bitcrush __Keywords: `crush`, `bits = 8`__ Bitcrushing is a distortion effect created by reducing both the sample rate of an audio signal and the bandwidth. A crush value of 1 will reduce the bit-rate of the signal to the value of `bits`, which is 8 by default. Every increment to `crush` thereafter reduces the sample rate of the signal (starting at 44.1 KHz) by half. The bitcrush effect requires the [SC3 Plugins] to be installed to work. ``` python # Apply the bit-crusher effect d1 >> play("X O ", crush=4) # Reduce the number of bits for more distortion d1 >> play("X O ", crush=4, bits=4) # Or reduce the sample rate for a different style of distortion! d1 >> play("X O ", crush=32, bits=8) ``` ## Distortion __Keyword: `dist`__ This requires the [SC3 Plugins] to be installed. This should be a value between 0 and 1 and distorts the audio signal. ``` python # Add distortion to both sample and synth players d1 >> play("x * ", dist=0.2) p1 >> dirt([0,5], dist=0.3, dur=8) + (0,4) ``` ## Wave-shape distortion __Keyword: `shape`__ This is another type of distortion that affects the shape of the audio signal’s waveform. This value should be between 0 and 1, but larger values are also accepted (be careful with headphones!). This distortion effect does not require any extra installation. ``` python # Add distortion to both sample and synth players d1 >> play("x * ", shape=0.5) p1 >> dirt([0,5], shape=0.5, dur=8) + (0,4) ``` ## Overdrive distortion __Keyword: `drive`__ A distortion created by amplifying the sound then clipping it at a much more “normal” amplitude. Values should be between 0 and 1 but larger values are accepted. ``` python # Add overdrive distortion p1 >> dirt(dur=1/2, drive=1) ``` ## Reverb __Keywords: `room`, `mix = 0.1`__ Use the `room` keyword to add reverb to a sound. This emulates the effect of playing the sound in a room and can be on a scale from dry (0% mix of the reverberated sound) to wet (100% mix of the reverberated sound). The `room` keyword sets the size of the room to emulate reverb in, and `mix` is the percent mix as a fraction (i.e. 0.1 is 10%). ``` python # Emulate playing the sounds in a small room p1 >> play("x o ", room=0.25) # Emulate playing the sounds in a larger room p1 >> play("x o ", room=0.8) # Make the signal more 'wet' p1 >> play("x o ", room=0.8, mix=0.8) ``` ## Echo __Keywords: `echo`, `echotime = 1`__ This effect often goes under the name of [Comb Delay](https://en.wikipedia.org/wiki/Comb_filter) but applying it to a single sound will give it the effect of echoing in a room. Use the `echo` keyword to define the duration (in beats) between each repeated sound. The following code plays a single note on repeat but we hear it echoed back to us after 1 beat. ``` python p1 >> blip(dur=4, echo=1) ``` _Note_: You may sometimes have to add reverb using the `room` keyword argument to hear the echo effect. This is because a sound is stopped by SuperCollider once it is detected as being silent. If the echo would occur after a period of silence, you will need to add reverb to keep the sound "alive" as it were. Here is an example: ``` python # We don't hear any echo effect d1 >> play("x-o-", dur=1, echo=0.75) # Add reverb and we do d1 >> play("x-o-", dur=1, echo=0.75, room=0.5) ``` By default you will probably only hear one echo of the original sound. To hear more echoes, increase the `echotime` duration: ``` python # Only hear one echo p1 >> blip(dur=4, echo=1) # Now we hear several p1 >> blip(dur=4, echo=1, echotime=8) # We can use echo to make drum loops more interesting too d1 >> play("(x )( x)o ", room=0.1, echo=0.75/2, echotime=4) ``` Be careful of using too much echo on too many players as it uses a large amount of CPU and can cause SuperCollider to crash. ## Pan spin __Keyword: `spin`__ This effect continually pans the sound from left to right, and back again, 'n' number of times, where 'n' is the value given to the `spin` keyword. This is dependent on the sustain of the note (given using the `sus` keyword). ``` python # Move the pan left to right 4 times across 4 beats p1 >> pads(dur=4, spin=4) # Move the pan left to right 4 times across 1 beat p1 >> pads(dur=4, sus=1, spin=4) ``` ## Cut __Keyword: `cut`__ To stop a sound abruptly (as opposed to just using a shorter `sus`) you can use the `cut` keyword. This is especially useful when playing samples using the `play` SynthDef as `sus` has no effect on the sound itself. The duration at which the sound is stopped is the `cut` value as a proportion of the `sus` value i.e. a `cut` of 0.5 will stop the sound half way through. ``` python # Stop a sound immediately instead of it's natural decay p1 >> pads(dur=4, cut=0.75) # Shorten samples to a tenth of their normal length d1 >> play("x-o-", cut=0.1) ``` ## Formant filtter __Keyword: `formant`__ This uses SuperCollider’s [Formlet](http://doc.sccode.org/Classes/Formlet.html) class to add a very simple resonance filter to the sound, not dissimilar to [TidalCycles](https://tidalcycles.org) "vowel" effect. The values should be between 1 and 7. ``` python # Loop through the different levels we can apply the filter p1 >> pluck(formant=P[:8]) ``` ## Tremolo __Keyword: `tremolo`__ [Tremolo](https://en.wikipedia.org/wiki/Tremolo) is the modulation of amplitude, which is done in FoxDot using a sine wave. This oscillates a note's amplitude "n" times per beat, where "n" is the input given to the `tremolo` argument. ``` python p1 >> pads(dur=4, tremolo=2) ``` ## Pitch shift __Keyword: `pshift`__ The shifts the pitch of a note by `pshift` number of semitones up or down. This also works for samples being used by the `play` SynthDef. ``` python # Shift a synth's pitch p1 >> pads(pshift=[0,1,2,3]) # Shift a sample's pitch p2 >> play("C", dur=2, pshift=[0,1,2,3]) # Can be used to make chords p2 >> play("C", dur=2, pshift=[0, (0,4,7)], sample=3) ``` ## Glide __Keywords: `glide`, `glidedelay = 0.5`__ Glide, often known as [glissando](https://en.wikipedia.org/wiki/Glissando), is very similar to the `slide` effect except that you specify the number of semitones to slide instead of the frequency multiplier. In future this may be replaced by the number of steps in the scale for consistency. ``` python # Glide to and from the 5th note in the scale (7th semitone) p1 >> pluck([0, 4], dur=4, glide=[7,-7]) ``` [SC3 Plugins]: ../install.md#installing-sc3-plugins-optional