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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
#ifndef UDO_SEQUENCING
#define UDO_SEQUENCING ##
/*
Sequencing base
This file is part of the SONICS UDO collection by Richard Knight 2021
License: GPL-2.0-or-later
http://1bpm.net
*/
gkseq_tempo init 120 ; tempo BPM
gkseq_beat init 0 ; trigger fired on each beat
gkseq_beattime init 0 ; time in seconds of one beat (read only; set by BPM)
gkseq_quartertime init 0 ; time in seconds of one quarter beat (read only; set by BPM)
gkseq_beathz init 0 ; Hz of one beat (read only; set by BPM)
gkseq_swing init 0.2 ; swing amount
gkseq_on init 1
/*
Instrument to control the main beat metronome and beat time globals
*/
instr _seq_manager
kseq_beat metro gkseq_tempo / 60
if (gkseq_on == 1) then
gkseq_beat = kseq_beat
endif
gkseq_beattime = 60 / gkseq_tempo
gkseq_quartertime = gkseq_beattime / 4
gkseq_beathz = (1 / 60) * gkseq_tempo
endin
;alwayson "_seq_manager" ; not available in web api
schedule("_seq_manager", 0, -1)
/*
Get the swung time for a given time, if appropriate. If the index given is a second 16th, time will be swung
kresult seq_swingtime ktime, kindex, kswing
kresult resulting time
ktime the time to consider
kindex beat index, beginning with 0
kswing the swing amount (0 to 1)
*/
opcode seq_swingtime, k, kkJ
ktime, kindex, kswing xin
kswing = (kswing == -1) ? gkseq_swing : kswing
if ((kindex+1) % 2 == 0) then
ktime = ktime + (gkseq_quartertime*kswing)
endif
xout ktime
endop
/*
Get the swung time for a given time, if appropriate. If the index given is a second 16th, time will be swung
iresult seq_swingtime itime, iindex, iswing
iresult resulting time
itime the time to consider
iindex beat index, beginning with 0
iswing the swing amount (0 to 1)
*/
opcode seq_swingtime, i, iij
itime, index, iswing xin
iswing = (iswing == -1) ? i(gkseq_swing) : iswing
if ((index+1) % 2 == 0) then
itime = itime + (i(gkseq_quartertime)*iswing)
endif
xout itime
endop
/*
Set the tempo in BPM
DEPRECATED: just use init or direct assignment to gkseq_tempo
seq_settempo ktempo
ktempo the tempo in BPM
*/
opcode seq_settempo, 0, k
ktempo xin
gkseq_tempo = ktempo
endop
/*
Set the tempo in BPM; typically for host control
p4 the tempo in BPM
*/
instr seq_settempo
itempo = p4
gkseq_tempo = itempo
turnoff
endin
/*
Basic sequencer: trigger an instrument on each beat
seq_basic SdespatchI
SdespatchI name of the instrument to trigger
*/
opcode seq_basic, 0, S
SdespatchI xin
schedkwhen gkseq_beat, 0, 0, SdespatchI, 0, 1
endop
/*
Basic swung sequencer: trigger an instrument on each 16th beat with
p4 as the cyclical index between 0 and 3
p5 as the total number of beats beginning at one (eg so modulus can be used to determine position etc)
seq_swing SdespatchI, kswing
SdespatchI name of the instrument to trigger
kswing swing amount (0 to 1)
*/
opcode seq_swing, 0, SJ
SdespatchI, kswing xin
kswing = (kswing == -1) ? gkseq_swing : kswing
kbeatnum init 1
if (gkseq_beat == 1) then
kswingamount = gkseq_quartertime*kswing
event "i", SdespatchI, 0, 1, 0, kbeatnum
event "i", SdespatchI, gkseq_quartertime+kswingamount, 1, 1, kbeatnum
event "i", SdespatchI, gkseq_quartertime*2, 1, 2, kbeatnum
event "i", SdespatchI, (gkseq_quartertime*3)+kswingamount, 1, 3, kbeatnum
kbeatnum += 1
endif
endop
/*
Basic array sequencer. Treat each index as a 16th, and if it is 1, trigger the despatch instrument
seq_array SdespatchI, karray[], kswing
SdespatchI name of the instrument to trigger
karray[] array of sequence information
kswing swing amount (0 to 1)
*/
opcode seq_array, 0, Sk[]k
SdespatchI, karray[], kswing xin
kindex init 0
if (gkseq_beat == 1) then
ktime = 0
kcount = 0
while (kcount < 4) do
if (karray[kindex] == 1) then
event "i", SdespatchI, seq_swingtime(ktime, kcount, kswing), 0.1
endif
if (kindex + 1 >= lenarray(karray)) then
kindex = 0
else
kindex += 1
endif
kcount += 1
ktime += gkseq_quartertime
od
endif
endop
/*
Parametric array sequencer. Treat each index of the first dimension as a 16th. The second dimension is as follows:
0 trigger (1 is active)
1 duration in seconds
2 p4 onwards (can be as many p-fields as required to be passed to the despatch instrument)
seq_array2d SdespatchI, karray[][], kswing
SdespatchI name of the instrument to trigger
karray[][] 2D array of sequence information
kswing swing amount (0 to 1)
*/
opcode seq_array2d, 0, Sk[][]k
SdespatchI, karray[][], kswing xin
kindex init 0
if (gkseq_beat == 1) then
ktime = 0
kcount = 0
while (kcount < 4) do
if (karray[kindex][0] == 1) then
krow[] getrow karray, kindex
Scoreline sprintfk "i\"%s\" %f %f ", SdespatchI, seq_swingtime(ktime, kcount, kswing), krow[1]
if (lenarray(krow) > 2) then
kdx = 2
while (kdx < lenarray(krow)) do
Scoreline strcatk Scoreline, sprintfk("%f ", krow[kdx])
kdx += 1
od
endif
scoreline Scoreline, 1
endif
if (kindex + 1 >= lenarray(karray)) then
kindex = 0
else
kindex += 1
endif
kcount += 1
ktime += gkseq_quartertime
od
endif
endop
/*
Freak sequencer. Three iterations of generative triggers sent to despatch instruments
seq_freak SdespatchI1, SdespatchI2, SdespatchI3, kbeatdensity[], kbeatstrength[]
SdespatchI1 name of the primary instrument to trigger
SdespatchI2 name of the secondary instrument to trigger
SdespatchI3 name of the tertiary instrument to trigger
*/
opcode seq_freak, 0, SSSk[]k[]
SdespatchI1, SdespatchI2, SdespatchI3, kbeatdensity[], kbeatstrength[] xin
kbeat init 0
ktrig init 0
if (gkseq_beat == 1) then ; only on every 1st of 4 beats
if (kbeat == 0) then
ktrig = 1
kbeat += 1
elseif (kbeat == 3) then
kbeat = 0
else
kbeat += 1
endif
endif
if (ktrig == 1 && random:k(0, 1) < kbeatdensity[0]) then
ktrig = 0
ktime = 0
event "i", SdespatchI1, ktime, 1, random:k(kbeatstrength[0]*0.2, kbeatstrength[0])
kindex1 = 0
kitems1 random 0, 8
while (kindex1 < kitems1) do
if (random:k(0, 1) < kbeatdensity[1]) then
event "i", SdespatchI2, ktime, 1, random:k(kbeatstrength[1]*0.2, kbeatstrength[1])
endif
ktime2 = ktime + (gkseq_beattime/8/8)
kindex2 = 0
kitems2 random 0, 32
while (kindex2 < kitems2) do
if (random:k(0, 1) < kbeatdensity[2]) then
event "i", SdespatchI3, ktime2, 1, random:k(kbeatstrength[2]*0.2, kbeatstrength[2])
endif
ktime2 += gkseq_beattime/8/8
kindex2 += 1
od
ktime += gkseq_beattime/8
kindex1 += 1
od
endif
endop
/*
Bar and bargroup management
Each beat is counted upon a gkseq_beat trigger.
When the number of beats implies a bar has completed, the trigger gkseq_bar_trig is fired.
The position in the bar (beat number (0 to giseq_barlength - 1)) is available in gkseq_barbeat.
When the number of bars implies a bargroup has completed, the trigger gkseq_bargroup_trig is fired.
The position in the bargroup (bar number (0 to giseq_bargrouplength - 1)) is available in gkseq_bargroup.
*/
gkseq_bar_trig init 0 ; trigger
gkseq_barbeat init -1 ; number
giseq_barlength = 4
gkseq_bargroup_trig init 0 ; trigger
gkseq_bargroup init -1 ; number
giseq_bargrouplength = 4
instr _barmanager
kbarbeat init 0
gkseq_bar_trig = 0
gkseq_bargroup_trig = 0
if (gkseq_beat == 1) then
gkseq_barbeat = (gkseq_barbeat < (giseq_barlength-1) ? gkseq_barbeat + 1 : 0)
if (gkseq_barbeat == 0) then
gkseq_bar_trig = 1
gkseq_bargroup = (gkseq_bargroup < (giseq_bargrouplength-1) ? gkseq_bargroup + 1 : 0)
if (gkseq_bargroup == 0) then
gkseq_bargroup_trig = 1
endif
endif
endif
endin
;alwayson "_barmanager" ; not available in web api
schedule("_barmanager", 0, -1)
/*
metronome; first beat has a higher pitch
aout metronome [iamp=1]
aout metronome output
iamp optional amplitude
*/
opcode metronome, a, p
iamp xin
kamp loopseg gkseq_tempo/60, gkseq_beat, 0, 1, 0.2, 0, 0.8, 0, 0
aout oscil 0.1, (gkseq_barbeat == 0 ? 2000 : 1000)
xout aout * kamp * iamp
endop
#end
|