├── 0. Start Here.sc ├── 1. Oscillators.sc ├── 2. Filters.sc ├── 3. Envelopes.sc ├── README.md └── Safety Notes.sc /0. Start Here.sc: -------------------------------------------------------------------------------- 1 | /* 2 | ------------- 3 | 0. START HERE 4 | ------------- 5 | 6 | This file is intended to help you get started! You will probably 7 | want to read this file before you start the first chapter, but 8 | you will also probably want to refer back here each time you 9 | start a new SuperCollider session. 10 | 11 | If anything in this file doesn't make sense, or if you don't know 12 | what 'the cookbook' is, go check out the README. 13 | 14 | In this file: 15 | ============ 16 | 1. The most helpful key combinations for the SuperCollider IDE 17 | 2. A test tone to ensure your sound is working 18 | 3. A test plot to get you used to visualizing waveforms 19 | 4. A codeblock and instructions to launch Oscilloscope and 20 | Frequency Analysis windows, to match the cookbook 21 | */ 22 | 23 | /* ============================================================== 24 | 1. The most helpful key combinations for the SuperCollider IDE 25 | ============================================================== 26 | 27 | ----------- 28 | Shift-Cmd-B 29 | ----------- 30 | Position your cursor to the right of the open bracket '(' in the 31 | last codeblock below. Now press Shift-Cmd-B. Notice how all the 32 | code inside the brackets is highlighted? 33 | 34 | ----------- 35 | Shift-Enter 36 | ----------- 37 | Once you have a codeblock selected, use Shift-Enter to evaluate 38 | the selected code. You should hear sound playing, OR see some 39 | response in the Post window. 40 | 41 | Note that you can also place your cursor anywhere on a single line 42 | of code and press Shift-Enter to execute only that line of code. 43 | 44 | ----- 45 | Cmd-. 46 | ----- 47 | Stop all playback. 48 | 49 | ----- 50 | Cmd-D 51 | ----- 52 | With your cursor on some evaluable code element, like SinOsc or 53 | scope, using Cmd-D will display the relevant help file in the 54 | Help Browser window. 55 | 56 | ------- 57 | Cmd -/+ 58 | ------- 59 | Adjust text size in the code editor or Post window. Note that you 60 | can default text size in Preferences > Editor > Font & Colors 61 | 62 | */ 63 | 64 | /* ============================================== 65 | 2. A test tone to ensure your sound is working 66 | ============================================== 67 | Place your cursor at the end of the line of code below, after 68 | play. Press Shift-Enter. This should make sound. 69 | - ALWAYS start with the volume LOW, then start the sound, then 70 | creep the volume up. 71 | - If you can't hear anything, check your speakers and your 72 | audio configuration. */ 73 | { SinOsc.ar(440)!2 }.play 74 | 75 | /* ======================================================= 76 | 3. A test plot to get you used to visualizing waveforms 77 | ======================================================= 78 | To visualize any sound function block like the one above, 79 | switch play for plot. 80 | - The argument is the number of seconds of playback to plot. 81 | When you evaluate these lines you have to wait that number 82 | of seconds before the results appear in the window. */ 83 | { SinOsc.ar(440)!2 }.plot(0.01) 84 | { SinOsc.ar(440)!2 }.plot(2) 85 | 86 | /* ========================================================== 87 | 4. A codeblock and instructions to launch Oscilloscope and 88 | Frequency Analysis windows, to match the cookbook 89 | ========================================================== 90 | Position your cursor to the right of the open bracket '(' below, 91 | and use Shift-Cmd-B and Shift-Enter to execute the codeblock as 92 | described above. 93 | - Once you run the codeblock the Oscilloscope window will jump 94 | to the front. Press Cmd-Tab twice to bring the FFT window to 95 | the front too. 96 | - Arrange the windows on your screen so that you can see both 97 | these windows while you work. 98 | - To make the FFT window match the cookbook, switch the FrcScl 99 | drop-down to 'lin' for linear. If you do this after you have 100 | sounds playing, you will need to stop the playback and 101 | restart the sound to see the change. */ 102 | ( 103 | /* FFT Window */ 104 | Server.quitAll; 105 | s = FreqScope.server.boot; 106 | FreqScope.new(800, 400, 0); 107 | 108 | /* Oscilloscope window */ 109 | w = Window.new("cookbook", Rect(20, 20, 262, 262)); 110 | w.view.decorator = FlowLayout(w.view.bounds); 111 | c = Stethoscope.new(s, view:w.view, zoom:8); 112 | w.onClose = { c.free }; //don't forget this 113 | w.front; 114 | ) -------------------------------------------------------------------------------- /1. Oscillators.sc: -------------------------------------------------------------------------------- 1 | /* 2 | -------------- 3 | 1. OSCILLATORS 4 | -------------- 5 | 6 | The cookbook says... 7 | ==================== 8 | "The process of adding sine waves together to create sounds is known as 9 | additive synthesis. This method is used on a few digital synthesizers 10 | and has also been used by pipe organs for hundreds of years..." 11 | 12 | But the real aim of this chapter is to teach building blocks for later 13 | ====================================================================== 14 | "Analog synthesizers use a process called subtractive synthesis which 15 | is simply additive synthesis in reverse. Here's some terminology for 16 | you: Sounds created by synthesizers are referred to as patches..." 17 | 18 | "Patches created using subtractive synthesis start with waveforms that 19 | are already rich in harmonics such as sawtooth, square, and triangle 20 | waves. These waveforms are then passed to a filter which removes 21 | harmonics from the waveforms in order to produce the desired sounds." 22 | 23 | "The harmonics are subtracted out, hence the process is known as 24 | subtractive synthesis." 25 | */ 26 | 27 | /* Figure 2. A 440Hz sine wave. 28 | =========================== */ 29 | ( 30 | x = { 31 | SinOsc.ar(freq: 440) !2 32 | }; 33 | x.plot(0.005); 34 | x.play; 35 | ) 36 | 37 | /* Figure 3. A 440Hz sine wave added to an 880Hz sine wave. 38 | ======================================================= 39 | - Notice the change in phase to position the two waves relative to each 40 | other. */ 41 | ( 42 | x = { 43 | SinOsc.ar(440, phase: pi, mul: 2/3) + 44 | SinOsc.ar(880, phase: -pi, mul: 1/3) !2 45 | }; 46 | x.plot(0.005); 47 | x.play; 48 | ) 49 | 50 | /* Figure 3 rewritten. 51 | ================== 52 | - Figure 3 can be written another way by modifying the multiplier only 53 | instead of the phase. 54 | - Notice the use of a negative value for the 880Hz SinOsc. 55 | - Ref: http://www.sussex.ac.uk/Users/nc81/modules/cm1/scfiles/2.1 Subtractive and Additive Synthesis.html */ 56 | ( 57 | ~peak = 0.75; 58 | x = { 59 | SinOsc.ar(440, mul: 1 * (~peak/1)) + 60 | SinOsc.ar(880, mul: -1 * (~peak/2)) !2 61 | }; 62 | x.plot(0.005); 63 | x.play; 64 | ) 65 | 66 | /* Figure 4. Three sine waves of frequency 440Hz, 880Hz, and 1320Hz. 67 | ================================================================ 68 | - Notice we had to adjust the peak, and a pattern is starting to emerge 69 | for multiplying by positive and negative numbers. 70 | - Ref: http://www.sussex.ac.uk/Users/nc81/modules/cm1/scfiles/2.1 Subtractive and Additive Synthesis.html */ 71 | ( 72 | ~peak = 0.65; 73 | x = { 74 | SinOsc.ar(440, mul: 1 * (~peak/1)) + 75 | SinOsc.ar(880, mul: -1 * (~peak/2)) + 76 | SinOsc.ar(1320, mul: 1 * (~peak/3)) !2 77 | //if we had another SinOsc here it would need a negative multiplier 78 | }; 79 | x.plot(0.005); 80 | x.play; 81 | ) 82 | 83 | /* Figure 5. A sawtooth. 84 | ==================== 85 | - Similar to brass and string instruments. 86 | - Now we are using Mix.fill to automate the process of extending the 87 | pattern above. Try adjusting ~numPartials to 50. 88 | - Note that ** is an exponent operator. The code '-1 ** i' produces 89 | the following pattern: 90 | -1 ** 0 == 1 91 | -1 ** 1 == -1 92 | -1 ** 2 == 1 93 | -1 ** 3 == -1 etc. 94 | - Ref: http://www.sussex.ac.uk/Users/nc81/modules/cm1/scfiles/2.1 Subtractive and Additive Synthesis.html */ 95 | ( 96 | ~peak = 0.5; 97 | ~numPartials = 15; 98 | ~fundamental = 440; 99 | 100 | x = { 101 | Mix.fill(~numPartials, {|i| 102 | var j = i + 1; 103 | var mul = (-1 ** i) * (~peak / j); 104 | SinOsc.ar(~fundamental * j, mul: mul); 105 | }) !2; 106 | }; 107 | x.plot(0.005); 108 | x.play; 109 | ) 110 | 111 | /* Figure 7. A square wave. 112 | ======================= 113 | - Similar to woodwind instruments. 114 | - Only odd numbered partials. 115 | - Since we are now only dealing with every other partial, and dropping 116 | the in-between partials, we no longer have to keep switching from 117 | positive to negative multiplier values. 118 | - Ref: http://www.sussex.ac.uk/Users/nc81/modules/cm1/scfiles/2.1 Subtractive and Additive Synthesis.html */ 119 | ( 120 | ~peak = 0.5; 121 | ~numPartials = 50; 122 | ~fundamental = 440; 123 | 124 | x = { 125 | Mix.fill(~numPartials, {|i| 126 | var j = (2 * i) + 1; //1, 3, 5 etc 127 | var mul = ~peak / j; 128 | SinOsc.ar(~fundamental * j, mul: mul); 129 | }) !2; 130 | }; 131 | x.plot(0.005); 132 | x.play; 133 | ) 134 | 135 | /* Figure 8. A triangle wave. 136 | ========================= 137 | - With their diminished higher harmonics, triangle waves are good for 138 | mixing together to produce inharmonic sounds (bells, chimes etc) as 139 | well as adding the occasional rogue harmonic to saw and pulse forms. 140 | - Only odd numbered partials. 141 | - We are back to alternating between -1 and 1 which I don't really get 142 | since we are still using only odd-numbered harmonics. 143 | - Ref: http://www.sussex.ac.uk/Users/nc81/modules/cm1/scfiles/2.1 Subtractive and Additive Synthesis.html */ 144 | ( 145 | ~peak = 0.8; 146 | ~numPartials = 20; 147 | ~fundamental = 440; 148 | 149 | x = { 150 | Mix.fill(~numPartials, {|i| 151 | var j = (2 * i) + 1; 152 | var mul = (-1 ** i) * (~peak / (j ** 2)); 153 | SinOsc.ar(~fundamental * j, mul: mul); 154 | }) !2; 155 | }; 156 | 157 | x.plot(0.005); 158 | x.play; 159 | ) 160 | 161 | /* Figure 12. Two triangle waves make a more harmonically rich sound. 162 | ================================================================= 163 | - This synthesis approximates a marimba 164 | - Ref: http://en.wikipedia.org/wiki/Piano_key_frequencies */ 165 | ( 166 | x = { 167 | LFTri.ar(440, mul: 0.4) + LFTri.ar(1760, mul: 0.15) !2; 168 | }; 169 | 170 | x.plot(0.005); 171 | x.play; 172 | ) 173 | 174 | /* Figure 13. Narrower pulse widths on square waves. 175 | ================================================ 176 | - Narrowing the width of the pulse means introducing even numbered 177 | partials alongside the odd ones. 178 | - Therefore, narrowing the pulse width creates a brighter, edgier 179 | sound similar to a sawtooth. 180 | - However, the harmonics don't die out as quickly or with the same 181 | uniformity as a sawtooth. 182 | - Narrow pulses have a crisp, metallic sound. Undulating pattern 183 | similar to many acoustic instruments. 184 | - Ref: http://en.wikipedia.org/wiki/Pulse_wave */ 185 | x = {Pulse.ar(440, width: 0.5) !2}; x.plot(0.01); x.play; 186 | x = {Pulse.ar(440, width: 0.6) !2}; x.plot(0.01); x.play; 187 | x = {Pulse.ar(440, width: 0.7) !2}; x.plot(0.01); x.play; 188 | x = {Pulse.ar(440, width: 0.8) !2}; x.plot(0.01); x.play; 189 | x = {Pulse.ar(440, width: 0.9) !2}; x.plot(0.01); x.play; 190 | 191 | x = {Pulse.ar(440, width: MouseX.kr(0.1, 0.5)) !2}; x.plot(0.01); x.play; 192 | x = {Pulse.ar(440, width: MouseX.kr(0.5, 0.9)) !2}; x.plot(0.01); x.play; 193 | 194 | /* Figures 16, 17, 18. White, Pink and Brown noise. 195 | =============================================== 196 | - White noise: maintains uniform power over all frequencies 197 | - Pink noise: diminishes in power by 3dB per octave 198 | - Brown noise: diminishes in power by 6dB per octave 199 | - White noise sounds brighter than pink noise, and pink noise sounds 200 | brighter than brown noise.*/ 201 | x = {WhiteNoise.ar(0.4) !2}; x.plot(0.1); x.play; 202 | x = {PinkNoise.ar(0.4) !2}; x.plot(0.1); x.play; 203 | x = {BrownNoise.ar(0.4) !2}; x.plot(0.1); x.play; 204 | 205 | /* Figure 19. Unison broadens the harmonics of a waveform. 206 | ====================================================== 207 | - True analog oscillators cannot keep exactly the same tuning, 208 | varying by a few cents at a time. This means that when several 209 | are played in unision, a 'thick', harmonically rich sound is 210 | created. 211 | - With the 'perfectness' of the constituent tones in digital 212 | oscillators, we have several options for how to implement 213 | unison. A couple are sketched out below. 214 | - Ref: http://music.tutsplus.com/articles/the-low-down-on-chorus-and-unison-effects--audio-3628 */ 215 | 216 | /* - A saw on it's own, for reference. */ 217 | {Saw.ar(220) !2}.play; 218 | 219 | /* - Multiple saws at slightly different frequencies. Because the 220 | frequencies are slightly different we get a phasing effect as 221 | the tones pass over each other. */ 222 | ( 223 | ~numVoices = 5; 224 | ~offset = floor(~numVoices/2); 225 | ~freq = 220; 226 | ~distance = 0.3; 227 | 228 | x = { 229 | ~freq.post; "Hz in ".post; ~numVoices.post; " voices, distribued:".postln; 230 | 231 | m = Mix.fill(~numVoices, {|i| 232 | var detuneAmount = (i - ~offset) * ~distance; 233 | var thisFreq = ~freq + detuneAmount; 234 | thisFreq.post; " ".postln; 235 | LFSaw.ar(thisFreq); 236 | }); 237 | m / ~numVoices !2; 238 | }; 239 | x.plot(0.005); 240 | x.play; 241 | ) 242 | 243 | /* - Multiple saws, this time at the same frequency but at slightly 244 | different phases. No phasing, and a thicker sound. */ 245 | ( 246 | ~numVoices = 5; 247 | ~freq = 220; 248 | ~distance = pi * 0.05; 249 | 250 | x = { 251 | ~freq.post; "Hz in ".post; ~numVoices.post; " voices, distanced:".postln; 252 | 253 | m = Mix.fill(~numVoices, {|i| 254 | var thisDistance = i * ~distance; 255 | thisDistance.post; " ".postln; 256 | LFSaw.ar(~freq, thisDistance); 257 | }); 258 | m / ~numVoices !2; 259 | }; 260 | x.plot(0.005); 261 | x.play; 262 | ) -------------------------------------------------------------------------------- /2. Filters.sc: -------------------------------------------------------------------------------- 1 | /* 2 | ---------- 3 | 2. FILTERS 4 | ---------- 5 | 6 | The cookbook says... 7 | ==================== 8 | "The incorporation of filters was the first great revolution in early 9 | electronic music after the oscillator. There are only a few distinct 10 | sounds that can be created using unfiltered waveforms. Synthesizers 11 | were born with the introduction of the filter. Of all the components 12 | on a synthesizer it is the most responsible for shaping sound. 13 | Filters are used to change the timbre or tone color of these basic 14 | waveforms." 15 | */ 16 | 17 | /* Figure 20. Unfiltered white noise, for reference. 18 | ================================================ */ 19 | x = { WhiteNoise.ar(0.4) !2 }; x.plot(0.1); x.play; 20 | 21 | /* Figure 21. White noise routed through a low-pass filter. 22 | ======================================================= 23 | - The argument 'freq' represents the cutoff frequency. 24 | - Frequencies above the cutoff are attenuated. */ 25 | ( 26 | //with a fixed cutoff frequency 27 | x = { 28 | LPF.ar( 29 | in: WhiteNoise.ar(0.4), 30 | freq: 4000 31 | )!2}; 32 | x.plot(0.1); 33 | x.play; 34 | ) 35 | ( 36 | //the same but you can vary the cutoff with your mouse 37 | x = { 38 | LPF.ar( 39 | in: WhiteNoise.ar(0.4), 40 | freq: MouseY.kr(110, 16000) 41 | )!2}; 42 | x.plot(0.1); 43 | x.play; 44 | ) 45 | 46 | /* Figure 22. White noise routed through a high-pass filter. 47 | ======================================================== 48 | - The argument 'freq' represents the cutoff frequency. 49 | - Frequencies below the cutoff are attenuated. */ 50 | ( 51 | //with a fixed cutoff frequency 52 | x = { 53 | HPF.ar( 54 | in: WhiteNoise.ar(0.4), 55 | freq: 4000 56 | )!2}; 57 | x.plot(0.1); 58 | x.play; 59 | ) 60 | ( 61 | //the same but you can vary the cutoff with your mouse 62 | x = { 63 | HPF.ar( 64 | in: WhiteNoise.ar(0.4), 65 | freq: MouseY.kr(110, 16000) 66 | )!2}; 67 | x.plot(0.1); 68 | x.play; 69 | ) 70 | 71 | /* Figure 23. White noise routed through a band-pass filter. 72 | ======================================================== 73 | - The argument 'freq' represents the center frequency. 74 | - Frequencies either side of the center are attenuated. 75 | - The argument 'rq' just describes the slopes either side of the center 76 | frequency. Higher values amplify the slopes, lower values attenuate 77 | them. */ 78 | ( 79 | //with a fixed center frequency and rq 80 | x = { 81 | BPF.ar( 82 | in: WhiteNoise.ar(0.4), 83 | freq: 4000, 84 | rq: 0.01 85 | )!2}; 86 | x.plot(0.1); 87 | x.play; 88 | ) 89 | ( 90 | /* === WARNING - READ THE SAFETY NOTES === */ 91 | //with a mouse-adjustable center frequency and rq... 92 | x = { 93 | BPF.ar( 94 | in: WhiteNoise.ar(0.4), 95 | freq: MouseY.kr(110, 23000), 96 | rq: MouseX.kr(0.01, 0.99) 97 | )!2}; 98 | x.plot(0.1); 99 | x.play; 100 | ) 101 | 102 | /* Figure 24. White noise routed through a band-reject/notch filter. 103 | ================================================================ 104 | - The argument 'freq' represents the center frequency. 105 | - Frequencies close to the center are attenuated. 106 | - The argument 'rq' just describes the slopes either side of the center 107 | frequency. Higher values attenuate the slopes, lower values amplify 108 | them. */ 109 | ( 110 | //with a fixed center frequency and rq 111 | x = { 112 | BRF.ar( 113 | in: WhiteNoise.ar(0.4), 114 | freq: 4000, 115 | rq: 0.99 116 | )!2}; 117 | x.plot(0.1); 118 | x.play; 119 | ) 120 | ( 121 | /* === WARNING - READ THE SAFETY NOTES === */ 122 | //with a mouse-adjustable center frequency and rq... 123 | x = { 124 | BRF.ar( 125 | in: WhiteNoise.ar(0.4), 126 | freq: MouseY.kr(110, 23000), 127 | rq: MouseX.kr(0.01, 0.99) 128 | )!2}; 129 | x.plot(0.1); 130 | x.play; 131 | ) 132 | 133 | /* Figure 25. White noise through an LPF with a 6kHz cutoff frequency. 134 | ================================================================== */ 135 | ( 136 | x = { 137 | LPF.ar( 138 | in: WhiteNoise.ar(0.4), 139 | freq: 6000 140 | )!2}; 141 | x.plot(0.1); 142 | x.play; 143 | ) 144 | 145 | /* Figure 26. Slope of a 4-pole filter. 146 | =================================== 147 | - A 4-pole filter is one that gives 24dB of attenuation per octave. 148 | - 'Octave' is a relative term, and when we talk about filters, by 149 | convention our first octave is at 4kHz. 150 | - So as the cookbook says: 151 | "Material at 8kHz is attenuated 24dB more than material at 4kHz 152 | since these frequencies are one octave apart." 153 | - You can check this in the frequency analyzer! */ 154 | ( 155 | x = { 156 | LPF.ar( 157 | in: WhiteNoise.ar(0.4), 158 | freq: 4000 159 | )!2}; 160 | x.plot(0.1); 161 | x.play; 162 | ) 163 | 164 | /* Figure 27. Slope of a 2-pole filter. 165 | =================================== 166 | - A 2-pole filter is one that gives 12dB of attenuation per octave. */ 167 | ( 168 | x = { 169 | TwoPole.ar( 170 | in: WhiteNoise.ar(0.4), 171 | freq: 4000 172 | )!2}; 173 | x.plot(0.1); 174 | x.play; 175 | ) 176 | 177 | /* Figure 29. A resonant LPF. 178 | ========================= */ 179 | ( 180 | //with a fixed cutoff frequency... 181 | x = { 182 | RLPF.ar( 183 | in: WhiteNoise.ar(0.4), 184 | freq: 4000, 185 | rq: 0.05 186 | )!2}; 187 | x.plot(0.1); 188 | x.play; 189 | ) 190 | ( 191 | //with a mouse-adjustable cutoff frequency... 192 | x = { 193 | RLPF.ar( 194 | in: WhiteNoise.ar(0.1), 195 | freq: MouseX.kr(0,1600), 196 | rq: 0.005 197 | )!2}; 198 | x.plot(0.5); 199 | x.play; 200 | ) 201 | ( 202 | //using Resonz, a stronger RLPF 203 | /* Ref: "http://danielnouri.org/docs/SuperColliderHelp/Tutorials/Mark_Polishook_tutorial/Synthesis/10_Subtractive_synthesis.html" 204 | Note that 'bwr' appears to be equivalent to 'rq'. But with 205 | explanation: 206 | "The reciprocal of Q is used rather than Q because it saves a 207 | divide operation inside the unit generator." */ 208 | x = { 209 | Resonz.ar( 210 | in: WhiteNoise.ar(1), 211 | freq: MouseX.kr(0,1600), 212 | bwr: 0.005 213 | )!2}; 214 | x.plot(0.1); 215 | x.play; 216 | ) 217 | 218 | /* A first stab at the acid track synthesizer example cited at the end 219 | of the Filters chapter. */ 220 | ( 221 | SynthDef(\acid, { |freq = 440, sustain = 1, amp = 0.5| 222 | var sig; 223 | 224 | //lead line 225 | sig = LFSaw.ar(freq, 0, amp) * 226 | EnvGen.kr(Env.linen(0.1, sustain, 0.1), doneAction: 2); 227 | 228 | //bass line 229 | sig = sig + LFSaw.ar(freq * 0.25, 0, amp) * 230 | EnvGen.kr(Env.linen(0.01, sustain, 0.01), doneAction: 2); 231 | 232 | //resonant filter over each note 233 | sig = RLPF.ar(sig, Line.kr(freq, freq * 2.5, sustain * 0.8), 0.25); 234 | 235 | //resonant filter over whole thing 236 | sig = RLPF.ar(sig, MouseX.kr(100, 1600), 0.25); 237 | 238 | //out 239 | Out.ar(0, sig!2) 240 | }).add; 241 | 242 | p = Pbind( 243 | \instrument, \acid, 244 | \midinote, Pseq([50, 62, 61, 57, 62, 62, 57], inf), 245 | \dur, Pseq([0.5, 0.5, 0.1, 0.1, 0.45, 0.25, 0.1], inf) 246 | ).play; 247 | ) -------------------------------------------------------------------------------- /3. Envelopes.sc: -------------------------------------------------------------------------------- 1 | /* 2 | ------------ 3 | 3. ENVELOPES 4 | ------------ 5 | 6 | The cookbook says... 7 | ==================== 8 | "If we want a patch to start loud and die out slowly like a cymbal or 9 | start out quiet and slowly become louder like a violin an envelope 10 | could be used to control the amplitude." 11 | 12 | Not just amplitude 13 | ================== 14 | Note that although amplitude is the most obvious application of 15 | envelopes, you can really control anything with them. For example in 16 | this chapter there are some great examples using ADSR envelopes to 17 | control a filter's cutoff frequency. 18 | */ 19 | 20 | /* Figure 32. An ADSR envelope controlling amplitude. 21 | ================================================= 22 | - I'm not sure why the plot doesn't release correctly 23 | - Ref: http://www.youtube.com/watch?v=-wDAPo9hpCg */ 24 | ( 25 | x = { |gate = 1| 26 | 27 | var sig, env; 28 | sig = SinOsc.ar(220); 29 | env = EnvGen.kr( 30 | Env.adsr(1.5, 1.5, 0.5, 4), 31 | gate: gate, 32 | doneAction: 2 33 | ); 34 | sig * env !2; 35 | }; 36 | 37 | y = x.play; 38 | x.plot(10); 39 | SystemClock.sched(6, { y.set(\gate, 0); }); 40 | ) 41 | 42 | /* An ADSR envelope controlling filter cutoff frequency. 43 | ==================================================== 44 | - I'm not sure why the plot doesn't release correctly 45 | - I'm not sure why the whole sound cuts out 46 | - Ref: http://www.youtube.com/watch?v=-wDAPo9hpCg */ 47 | ( 48 | x = { |gate = 1| 49 | var sig, env; 50 | env = EnvGen.kr( 51 | Env.adsr(0.3, 0.3, 0.9, 1.2), 52 | gate: gate 53 | ); 54 | 55 | sig = RLPF.ar( 56 | in: LFSaw.ar(220), 57 | freq: 220 + (220 * env), 58 | rq: 0.005 59 | ); 60 | sig * env !2; 61 | }; 62 | 63 | y = x.play; 64 | x.plot(10); 65 | SystemClock.sched(6, { y.set(\gate, 0); }); 66 | ) 67 | 68 | /* Note: there is a final example on this page that is 69 | worth adding once the above two examples are fixed! */ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welsh's Synthesizer Cookbook in SuperCollider 2 | 3 | ## What is this repo? 4 | 5 | This repo is designed to help you learn **synthesizer fundamentals** at the same time as learning **SuperCollider**. Inside you will find runnable code examples for all the figures from the foundational synthesis chapters of **Welsh's Synthesizer Cookbook**. 6 | 7 | The code is labelled with figure numbers and explanatory notes to make it easy to cross-reference, and to hear how the figures sound in the SuperCollider synthesis environment. 8 | 9 | - Note: Newbies check out the section below: 10 | **I'm new to computer music, what should I do?** 11 | 12 | - Note: All accompanying notes in code comments are based on or inspired by the book, unless otherwise quoted. 13 | 14 | ## What is SuperCollider? 15 | 16 | SuperCollider is a software audio synthesis engine and [domain-specific language](http://en.wikipedia.org/wiki/Domain-specific_language) for sound artists, musicians, programmers and academics. It allows you to program (code) sound and music. 17 | 18 | Read more [here](http://jahya.net/blog/?2012-05-getting-started-with-supercollider) and [here](http://en.wikipedia.org/wiki/SuperCollider). 19 | 20 | ## What is Welsh's Synthesizer Cookbook? 21 | 22 | The first few chapters are a quick, hands-on introduction to synthesis fundamentals. The rest of the book is a catalog of ingredient recipes for using what you have learned to build snythesizers. 23 | 24 | [ ![Welsh's Synthesizer Cookbook](http://3.bp.blogspot.com/-Kllf8JcKhcM/UpLsxkKci6I/AAAAAAAAC64/oFjvvJr74is/s400/cookbook.jpg) ](http://www.amazon.com/Welshs-Synthesizer-Cookbook-Programming-Universal/dp/B000ERHA4S) 25 | 26 | ## What topics are covered? 27 | 28 | There is an introductory code file that will get you off the ground with SuperCollider, to make sure you can hear sound, and see the oscilloscope and frequency analysis views. It also provides keyboard shortcuts and advice. 29 | 30 | Then, the meat: 31 | 32 | 1. Additive synthesis 33 | - Sine, sawtooth, square and triangle waves 34 | - White, pink and brown noise 35 | 2. Subtractive synthesis 36 | - Low-pass & high-pass filters 37 | - Band-pass & band-reject/notch filters 38 | - Slopes & poles 39 | - Resonant filters 40 | 3. Envelopes 41 | - Attack, decay, sustain and release 42 | 43 | Finally there is a safety file to make sure you don't blow your speakers, or your ears in the process! SuperCollider will let you pipe literally anything to your sound card. Make sure you know about common mistakes! 44 | 45 | ## OK, got it, can I get started? 46 | 47 | Sure, dive in. The code is all sclang ready. 48 | 49 | Be sure to get back to me with comments and improvements. Better still, fork the repo and submit pull requests with your contributions! 50 | 51 | ## I'm new to computer music, what should I do? 52 | 53 | When I was new to computer music I was already familiar with programming. That's one reason that SuperCollider was an appealing option for me. It is about code + sound, and so I get all the benefits of being able to program, for example being able to hook up my sounds to ad-hoc [sensors](https://www.adafruit.com/), or other [custom software environments](http://www.openframeworks.cc/) and so on. 54 | 55 | If you are not familiar with programming, SuperCollider may not be the option for you. I would suggest you go and check out some of the many awesome GUI-driven synthesis engines out there. 56 | 57 | However, if you are still interested, I left a trail behind me while I learned. Some blog posts and references really helped, others I wrote because I wanted them and they weren't there. This is the route that worked for me: 58 | 59 | 1. **To get a grounding in what SuperCollider is and if it will work for you**, check out my article: [Getting Started with SuperCollider](http://jahya.net/blog/?2012-05-getting-started-with-supercollider) 60 | 61 | 2. **To plough ahead and learn the SuperCollider environment hands-on**, read [Scott Wilson's tutorial](http://supercollider.svn.sourceforge.net/viewvc/supercollider/trunk/common/build/Help/Tutorials/Getting-Started/Getting%20Started%20With%20SC.html). This will give you an understanding of the tools and building blocks SuperCollider puts at your fingertips. 62 | 63 | 3. **As you go forward and start making sounds**, use my one-page [Quick Reference for SuperCollider](http://jahya.net/blog/?2012-06-quickref-for-supercollider) to refresh your memory. It gives you concise versions of all the examples you learned from Scott Wilson's tutorial (above), and saves you having to dig back through to find what you were looking for. 64 | 65 | 4. Now that you understand the SuperCollider environment and how to create synths, you need a **crash course in audio synthesis** - that's what this repo is for. Grab your copy of [the cookbook](http://www.amazon.com/Welshs-Synthesizer-Cookbook-Programming-Universal/dp/B000ERHA4S) and dig in! 66 | 67 | P.S. For ad-hoc help along the way, check out this amazing array of quick tutorial videos by WickieMedia, [here](http://www.youtube.com/user/wickiemedia) or [here](http://www.wickiemedia.net/audio-tutorials.html). 68 | 69 | Also, drop me a message to tell how you got on. Better still, fork the repo and submit pull requests with your contributions! 70 | 71 | ## Why did you create this repo? 72 | 73 | I wanted a hands-on guide that would give me whirlwind explanation of synthesis at a basic level. I wanted a reference that did this in the context of SuperCollider, but I couldn't find one. So I read the book and wrote the best SuperCollider examples I could think of at the time. -------------------------------------------------------------------------------- /Safety Notes.sc: -------------------------------------------------------------------------------- 1 | /* 2 | Safety Notes 3 | ============ 4 | This issue cost my speakers and my ears a jolt. Nothing dangerous in 5 | the long run, just a loud spike in sound. But still you want to know 6 | about this issue to avoid it. So learn from my mistake! 7 | 8 | What's the problem? 9 | ================== 10 | SuperCollider gives you low-level access to sound objects (UGens). 11 | This means you have lots of power, you are playing with the nuts and 12 | bolts. It also means there are no safety systems to protect you from 13 | doing something crazy. 14 | 15 | Sometimes we want to use the values from one UGen as inputs to some 16 | other UGen: */ 17 | { SinOsc.ar(MouseX.kr(0, 1000)) !2 }.play; 18 | 19 | /* We need to be 100% sure of the possible range of values we pass into 20 | a UGen. Some UGens will respond really badly to the wrong values. 21 | 22 | For example, the 'rq' argument to the BPF UGen works happily with 23 | positive arguments. But any negative value causes the amplitude to 24 | shoot up to ridiculous levels: */ 25 | 26 | /* === WARNING! NEVER PLAY THIS, ONLY PLOT IT ==== */ 27 | { BPF.ar(WhiteNoise.ar(0.4), rq: -1) }.plot(0.05); 28 | 29 | /* How to avoid it 30 | =============== 31 | 1) Whenever you are working with a new UGen or a new parameter for a 32 | UGen that you don't understand, PLOT IT BEFORE YOU PLAY IT! 33 | 34 | 2) Be aware of the values you are passing around. Some of them are 35 | are known and cannot extend beyond certain bounds, and so are 36 | safe. However, some can surprise you, for example, the mouse / 37 | dual screen problem described below. 38 | 39 | Using dual monitors with MouseX and MouseY 40 | ========================================== 41 | When we use MouseX and MouseY, we specify the range of values we 42 | expect. In the example from earlier, the range is (0 - 1000): */ 43 | { SinOsc.ar(MouseX.kr(0, 1000)) !2 }.play; 44 | 45 | /* Most operating systems allow you to use multiple displays, and to 46 | choose whichever display you like to be the primary display. 47 | 48 | The problem is, SC's MouseX and MouseY will map the given range 49 | to the boundaries of the primary display, so that if you have a 50 | display configuration like this... 51 | 52 | X X 53 | -1000 <------> 0 0 <-------> 1000 54 | ------------- ------------- 55 | | | | | 56 | | Secondary | | Primary | 57 | | display | | display | 58 | | | | | 59 | ------------- ------------- 60 | 61 | ...your mouse cursor can easily venture into negative numbers by 62 | moving into the secondary display. Negative numbers drive some UGens 63 | crazy - like BPF in the example above. 64 | 65 | How to avoid it 66 | =============== 67 | Know the possible range of values that you can get from MouseX and 68 | MouseY given your display configuration and the value ranges you 69 | specify. Use the code below. 70 | 71 | Also, don't forget to make sure that the value range you specify 72 | when testing - i.e. (1, 1000) below - is the same range you specify 73 | in your UGens for real. 74 | */ 75 | { MouseX.kr(0, 1000).poll(label: \MouseX) }.play; 76 | { MouseY.kr(0, 1000).poll(label: \MouseY) }.play; --------------------------------------------------------------------------------