-
Notifications
You must be signed in to change notification settings - Fork 0
/
Mordule.sc
215 lines (190 loc) · 5.74 KB
/
Mordule.sc
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/**
* Virtual analog modulation model.
* Mordule represents a buffer and a list of symbols which correlate to indices
* of that buffer, along with helper methods to model classic modulations,
* including modulation matrices. Is also able to create circular modulation
* graphs.
*
* @TODO Values may be delayed one control cycle. How to solve this? Is this something I should even worry about?
* @TODO Make this work audio-rate
* @TODO Make some of these methods private.
*/
Mordule {
var <sourceBuffer;
var <targetBuffer;
var <channels;
var <includeNilIndex;
/**
* Symbols in sources and destinations that overlap will be added as both
* sources and destinations.
* @param Collection sources
* A collection of Symbols that will be registered as sources.
* @param Collection destinations
* A collection of Symbols that will be registered as destinations.
* @param integer channels
* The number of channels to create in the buffer. Useful for stereo
* LFO's, etc. This number is universal across the whole Mordule instance.
* @param Buffer buffer
* Explicitly pass in a Buffer. An error will be thrown if it's not the * same size as the number of keys (@TODO)! @TODO also test to make sure
* it's a buffer or nil.
* @param Boolean includeNilIndex
* Whether to include a location in the buffer that does not act as a
* modulator. Useful for selectInsert, selectWrite, etc methods, when one * of the options should do nothing.
* @return Mordule
* The new Mordule instance.
*/
*new {
arg sources, targets, channels = 1, buffer = nil, includeNilIndex = true;
^ super.new.init(sources, targets, channels, buffer, includeNilIndex);
}
*kr {
arg sources, targets, channels = 1, buffer = nil, includeNilIndex = true;
^ super.new.init(sources, targets, channels, buffer, includeNilIndex);
}
*ar {
arg sources, targets, channels = 1, buffer = nil, includeNilIndex = true;
^ super.new.initAr(sources, targets, channels, buffer, includeNilIndex);
}
init {
arg a_sources, a_targets, a_channels, a_buffer, a_includeNilIndex;
// Don't worry about channels or nilIndex in constructors, they're re-set
// immediately below.
sourceBuffer = MorduleBuffer(a_sources);
targetBuffer = MorduleBuffer(a_targets);
this.includeNilIndex = a_includeNilIndex.asBoolean;
this.channels = a_channels;
^ this;
}
initAr {
arg a_sources, a_targets, a_channels, a_buffer, a_includeNilIndex;
// Don't worry about channels or nilIndex in constructors, they're re-set
// immediately below.
sourceBuffer = MorduleBufferAr(a_sources, a_channels);
targetBuffer = MorduleBufferAr(a_targets, a_channels);
this.includeNilIndex = a_includeNilIndex.asBoolean;
this.channels = a_channels;
^ this;
}
sources {
^ sourceBuffer;
}
targets {
^ targetBuffer;
}
sources_ {
arg a_sources;
sourceBuffer.keys = a_sources;
^ this;
}
targets_ {
arg a_targets;
targetBuffer.keys = a_targets;
^ this;
}
channels_ {
arg a_channels;
sourceBuffer.channels = a_channels;
targetBuffer.channels = a_channels;
^ this;
}
includeNilIndex_ {
arg a_include;
sourceBuffer.nilIndex = a_include;
targetBuffer.nilIndex = a_include;
includeNilIndex = a_include;
^ this;
}
/**
* Sets a source value.
*/
writeSource {
arg key, value;
^ sourceBuffer.writeKey(key, value);
}
/**
* Gets a source value.
*/
readSource {
arg key, mul = 1, add = 0;
^ sourceBuffer.readKey(key, mul, add);
}
/**
* Gets a target value.
*/
readTarget {
arg key, value, mul = 1, add = 0;
^ targetBuffer.readKey(key, value, mul, add);
}
/**
* Tap the accumulated values of this target.
* Resets the target back to zero.
*/
tapTarget {
arg key, mul = 1, add = 0;
^ targetBuffer.tapKey(key, mul, add);
}
tapTargetExponential {
arg key, power;
^ pow(power, this.tapTarget(key));
}
/**
* Accumulate values for this target.
*/
insertTarget {
arg key, value, mul = 1;
targetBuffer.insertKey(key, value, mul);
^ this;
}
/**
* Connect a named source to a named target.
*/
connect {
arg source, target, mul = 1, add = 0;
this.insertTarget(target, this.readSource(source, mul, add));
^ this;
}
/**
* Insert a value into a selectable target.
* @param Array subkeys
* An array of keys which are available to be chosen between. All keys by
* default.
*/
insertSelectTarget {
arg index, value, subkeys = nil, mul = 1;
var targetIndex = targetBuffer.selectIndex(index, subkeys);
targetBuffer.insert(targetIndex, value * mul);
^ this;
}
readSelectSource {
arg index, subkeys = nil, mul = 1, add = 0;
var sourceIndex = sourceBuffer.selectIndex(index, subkeys);
^ sourceBuffer.read(sourceIndex, mul, add);
}
/**
* Connect a named source to a selectable target.
*/
connectSelectTarget {
arg source, index, subkeys = nil, mul = 1;
var value = this.readSource(source);
this.insertSelectTarget(index, value, subkeys, mul);
^ this;
}
/**
* Connect a selectable source to a named target.
*/
connectSelectSource {
arg sourceIndex, target, subkeys = nil, mul = 1, add = 0;
var value = this.readSelectSource(sourceIndex, subkeys, mul, add);
this.insertTarget(target, value, mul);
^ this;
}
/**
* Connect a selectable source to a selectable target.
*/
connectDoubleSelect {
arg sourceIndex, targetIndex, sourceSubKeys = nil, targetSubkeys = nil, mul = 1, add = 0;
var value = this.readSelectSource(sourceIndex, sourceSubKeys);
this.insertSelectTarget(targetIndex, value.madd(mul, add), targetSubkeys)
^ this;
}
}