-
Notifications
You must be signed in to change notification settings - Fork 5
/
04-further-soundmaking.html
125 lines (106 loc) · 7.49 KB
/
04-further-soundmaking.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 2019-03-12 Tue 19:47 -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Further Soundmaking</title>
<meta name="generator" content="Org mode">
</head>
<body>
<div id="content">
<header>
<h1 class="title">Further Soundmaking</h1>
</header><nav id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orge9fc312">1. <code>defsynth</code></a></li>
<li><a href="#org89808df">2. Best Practices</a></li>
<li><a href="#org3ca65cc">3. More UGens</a></li>
</ul>
</div>
</nav>
<div id="outline-container-orge9fc312" class="outline-2">
<h2 id="orge9fc312"><span class="section-number-2">1</span> <code>defsynth</code></h2>
<div class="outline-text-2" id="text-1">
<p>
We've been using the <code>proxy</code> macro to define and redefine sounds, but this limits us to sounds that play continuously. Most music is made from sounds that are temporal and periodic, so we need a way to define a sound that can be re-triggered.
</p>
<p>
<code>proxy</code> is good for testing out sounds, but once we've made something that we want to use, we define it with <code>defsynth</code>. Here's a basic example:
</p>
<div class="org-src-container">
<pre class="src src-lisp">(defsynth drum ((freq 3000))
(<span style="color: #859900;">let*</span> ((env (env-gen.ar (perc 0.001 0.1) <span style="color: #859900;">:act</span> <span style="color: #859900;">:free</span>))
(sig (lpf.ar (white-noise.ar) (* freq env))))
(out.ar 0 (pan2.ar sig 0 0.2))))
</pre>
</div>
<p>
It's not the most exciting drum sound of all time, but now at least you can re-trigger it. To do so, just evaluate <code>(synth 'drum :freq 3000)</code>.
</p>
<p>
Notice that <code>defsynth</code> is very similar to <code>defun</code>. With <code>defsynth</code> you provide the name of the synth (<code>drum</code>), its parameters (<code>(freq 3000)</code>), and the body, which describes how it generates its sound.
</p>
<p>
In the case of this synth, we create two variables, <code>env</code> and <code>sig</code>. <code>env</code> is bound to an envelope generator UGen, <code>env-gen.ar</code>, which takes an envelope specification and generates an audio signal from that specification. <code>(perc 0.001 0.1)</code> is the function generating the specification; its first parameter is the time in seconds to rise from <code>0</code> to <code>1</code>, and the second parameter is the time to fall back to <code>0</code>. The <code>:act :free</code> keywords for <code>env-gen</code> specify that once the envelope has reached its end, the synth will be removed from the server, freeing up CPU resources.
</p>
<p>
The signal (<code>sig</code>) being generated is white noise (<code>white-noise.ar</code>) with its high frequencies dampened by the <code>lpf</code> low pass filter. The filter's frequency (<code>lpf</code>'s second argument) is the envelope generator multiplied by the synth's <code>freq</code> argument. Since the <code>perc</code> function generates an envelope that goes from <code>0</code> to <code>1</code> and then to <code>0</code> again, multiplying it by frequency is a simple way to change the brightness of the sound. Try the <code>synth</code> function with different values for its <code>:freq</code> key, from <code>20</code> to <code>10000</code> to get a feel for how it affects the sound.
</p>
<p>
The last line of the synth definition contains the <code>out.ar</code> UGen. When we use the <code>proxy</code> function, this UGen is automatically inserted for us for convenience, but when we define a synth manually, we have to specify it. <code>out</code>'s first argument is the index of the bus that you want to write to–in this case we just use <code>0</code> since we want the sound to go to our speakers. <code>out</code>'s second argument is a UGen or list of UGens that are generating the sound. Up to this point, we've only been generating mono (single channel) sounds. The <code>pan2</code> UGen accepts a mono signal as input (<code>sig</code> in our case) and converts it into a stereo signal based on its second argument, which specifies the panning position (here we use <code>0</code> to position it centrally). Finally, <code>pan2</code>'s third argument is an amplitude input, so we multiply the overall volume of the synth by <code>0.2</code>.
</p>
</div>
</div>
<div id="outline-container-org89808df" class="outline-2">
<h2 id="org89808df"><span class="section-number-2">2</span> Best Practices</h2>
<div class="outline-text-2" id="text-2">
<p>
If you're going to make music with cl-collider, you're likely to end up writing a lot of ~defsynth~s. Because of this, it may be a good idea to use a template system for your editor. For example, Emacs users can use skeleton or yasnippet. Both of these allow you to create a template and easily insert it into a file so you don't have to do as much manual typing.
</p>
<p>
You may want to use something like the following as your basic template synth:
</p>
<div class="org-src-container">
<pre class="src src-lisp">(defsynth newsynth ((gate 1) (freq 440) (amp 0.5) (pan 0) (out 0))
(<span style="color: #859900;">let*</span> ((env (env-gen.kr (adsr 0.001 0.1 0.5 0.1) <span style="color: #859900;">:gate</span> gate <span style="color: #859900;">:act</span> <span style="color: #859900;">:free</span>))
(sig (saw.ar freq)))
(out.ar out (pan2.ar sig pan (* amp env)))))
</pre>
</div>
<p>
This is a good synthdef to start from because it includes most of what you'll need to get started: standard arguments, an envelope that frees the synth when complete, and of course, UGens to generate and output sound.
</p>
<p>
<code>gate</code>, <code>freq</code>, <code>amp</code>, <code>pan</code>, and <code>out</code> are all fairly common and standard arguments for synthdefs. <code>gate</code> is used to tell the synth whether it should play or release. If you were playing on a piano, <code>gate</code> would be <code>1</code> when you press a key, and would become <code>0</code> when you release the key. Because we provide <code>gate</code> to the <code>env-gen</code>, the envelope will start when the gate is 1 and will proceed to the release section when the gate becomes 0. Then, when the release section ends, the envelope will free itself.
</p>
<p>
<code>freq</code> is the standard argument name for sending pitch information to a synthdef. If you want to control the pitch of a synth using a midi note number instead, you can use the <code>midicps</code> function to convert the midi note number to a frequency. Like so:
</p>
<div class="org-src-container">
<pre class="src src-lisp">(<span style="color: #859900;">defparameter</span> <span style="color: #268bd2;">*ns*</span> (synth 'newsynth <span style="color: #859900;">:freq</span> (midicps 40)))
</pre>
</div>
<p>
We don't have to specify all of the arguments to <code>newsynth</code> since they all have default values.
</p>
<p>
Since the synth will sustain until we specifically tell it to release, we save the result of calling the <code>synth</code> function to the <code>*ns*</code> variable. When we want to release it, we can just call <code>release</code> on <code>*ns*</code>, like so:
</p>
<div class="org-src-container">
<pre class="src src-lisp">(release *ns*)
</pre>
</div>
</div>
</div>
<div id="outline-container-org3ca65cc" class="outline-2">
<h2 id="org3ca65cc"><span class="section-number-2">3</span> More UGens</h2>
</div>
</div>
<div id="postamble" class="status">
<p class="date">Last updated: 2019-03-12 Tue 19:47</p>
</div>
</body>
</html>