aboutsummaryrefslogtreecommitdiff
path: root/site/udo/sequencing_table.udo
blob: 8ef40dc663b4c31c0adb90e9680dc1ccfb72f162 (plain)
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
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#ifndef UDO_SEQUENCING_TABLE
#define UDO_SEQUENCING_TABLE ##
/*
	Table sequencing

	This file is part of the SONICS UDO collection by Richard Knight 2022
		License: GPL-2.0-or-later
		http://1bpm.net
*/


#include "sequencing.udo"


gifn_tabseq_all = ftgen(0, 0, -4, -2, 1, 1, 1, 1) ; 4 quarter notes to allow for swing

/*

TODO: write to database

gistfn_kick1 ftgen 0, 0, -16, -2, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0
gistfn_kick2 ftgen 0, 0, -16, -2, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0
gistfn_kick3 ftgen 0, 0, -16, -2, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0

*/


/*
	Fill a table with random boolean values, generating the table if ifn is -1

	ifnout _seq_randtable_bool ilen, ifn, ichance

	ifnout		the resulting table
	ilen		length of table to create, if generating
	ifn			existing table or -1 to generate
	ichance		chance of random assignment: -1 defaults to 0.5, 1 is fill all values, 0 is fill no values
*/
opcode _seq_randtable_bool, i, iii
	ilen, ifn, ichance xin
	ichance = (ichance == -1) ? 0.5 : ichance
	if (ifn == -1) then
		ifn ftgen 0, 0, -ilen, -2, 0
	endif
	index = 0
	while (index < ftlen(ifn)) do
		ivalue = (random(0, 1) <= ichance) ? 1 : 0
		tableiw ivalue, index, ifn
		index += 1
	od
	xout ifn
endop


/*
	Fill a table with random numeric values, generating the table if ifn is -1

	ifnout _seq_randtable_bool ilen, ifn, ichance

	ifnout		the resulting table
	ilen		length of table to create, if generating
	ifn			existing table or -1 to generate
	iminvalue	minimuma value to assign
	imaxvalue	maximum value to assign
	irounded	1 = integer values, 0 = float values
*/
opcode _seq_randtable_numeric, i, iiiii
	ilen, ifn, iminvalue, imaxvalue, irounded xin
	if (ifn == -1) then
		ifn ftgen 0, 0, -ilen, -2, 0
	endif
	index = 0
	while (index < ftlen(ifn)) do
		ivalue = random(iminvalue, imaxvalue)
		tableiw ((irounded == 1) ? round(ivalue) : ivalue), index, ifn
		index += 1
	od
	xout ifn
endop


/*
	Generate a table with random boolean values
	
	ifn seq_randtablegen ilen, ichance

	ifn			the resulting table
	ilen		length of table to create
	ichance		chance of random assignment: -1 defaults to 0.5, 1 is fill all values, 0 is fill no values
*/
opcode seq_randtablegen, i, ij
	ilen, ichance xin
	ifn _seq_randtable_bool ilen, -1, ichance
	xout ifn
endop


/*
	Fill an existing table with random boolean values

	seq_randtable ifn, ichance

	ifn			the table to fill
	ichance		chance of random assignment: -1 defaults to 0.5, 1 is fill all values, 0 is fill no values
*/
opcode seq_randtable, 0, ij
	ifn, ichance xin
	ifn _seq_randtable_bool -1, ifn, ichance
endop



/*
	Generate a table with random numeric values

	ifn seq_randtablegen_numeric ilen, iminvalue, imaxvalue, irounded

	ifnout		the resulting table
	ilen		length of table to create
	iminvalue	minimuma value to assign
	imaxvalue	maximum value to assign
	irounded	1 = integer values, 0 = float values
*/
opcode seq_randtablegen_numeric, i, iiii
	ilen, iminvalue, imaxvalue, irounded xin
	ifn _seq_randtable_numeric ilen, -1, iminvalue, imaxvalue, irounded
	xout ifn
endop



/*
	Fill an existing table with random numeric values

	seq_randtable_numeric ifn, iminvalue, imaxvalue, irounded

	ifn			the table to fill
	iminvalue	minimuma value to assign
	imaxvalue	maximum value to assign
	irounded	1 = integer values, 0 = float values
*/
opcode seq_randtable_numeric, 0, iiii
	ifn, iminvalue, imaxvalue, irounded xin
	ifn _seq_randtable_numeric -1, ifn, iminvalue, imaxvalue, irounded
endop


/*
	Fill an existing table with random boolean values at k-rate on receipt of a trigger

	seq_randtable kfn, ktrig, kchance

	kfn			the table to fill
	ktrig		repopulate the table when 1
	kchance		chance of random assignment: -1 defaults to 0.5, 1 is fill all values, 0 is fill no values
*/
opcode seq_randtable, 0, kkV
	kfn, ktrig, kchance xin
	kchance = (kchance == -1) ? 0.5 : kchance
	if (ktrig == 1) then ; && changed:k(ktrig) == 1) then
		kindex = 0
		while (kindex < tableng:k(kfn)) do
			kvalue = (random:k(0, 1) <= kchance) ? 1 : 0
			tablewkt kvalue, kindex, kfn
			kindex += 1
		od
	endif
endop


/*
opcode seq_table_numeric, k, i
	ifn xin
	ilen tableng ifn
	kindex init 0
	as, a_ syncphasor gkseq_beathz*4, a(gkseq_beat)
	kt trigger k(as), 0.05, 0 ; was 0.005.. works?
	if (kt == 1) then
		koutvalue table kindex, ifn

		if (kindex < klength - 1) then
			kindex += 1
		else
			kindex = 0
		endif
	endif
	koutvalue 
endop
*/




/*
	Trigger and index output table sequencer

	ktrig, kindex seq_table ifn [, kreset=0, kdivisions=4, kchanceon=1, kchanceoff=1, klength=ftlen(ifn), kswing=gkseq_swing, kbeathz=gkseq_beathz, inosync=0]
	ktrig seq_table ifn [, kreset=0, kdivisions=4, kchanceon=1, kchanceoff=1, klength=ftlen(ifn), kswing=gkseq_swing, kbeathz=gkseq_beathz, inosync=0]

	ktrig 			the sequence trigger
	kindex			current index (max = klength-1)

	ifn				the table containing boolean positions
	kreset			if above 0 and changed since last value, then reset sequence index to 0
	kdivisions		how many points feature in one beat
	kchanceon		chance of an on point being on (1 = always, 0 = never)
	kchanceoff		chance of an off point being off (1 = always, 0 = never)
	klength			the maximum number of points in the table to use
	kswing			the swing amount to apply
	kbeathz			trigger rate in Hz
	inosync			do not sync to the sequencer beat clock
*/
opcode seq_table, kk, iOJPPJJJo
	ifn, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing, kbeathz, inosync xin
	ilen = ftlen(ifn)

	kdivisions = (kdivisions == -1) ? 4 : kdivisions
	klength = (klength == -1) ? ilen : min(ilen, klength)
	kswing = (kswing == -1) ? gkseq_swing : kswing
	kbeathz = (kbeathz == -1) ? gkseq_beathz : kbeathz

	kindex init 0
	klaunchindex init 0

	if (kreset >= 0 && changed:k(kreset) == 1) then
		kindex = 0
	endif

	if (inosync == 1) then
		kt metro kbeathz * kdivisions
	else
		as, a_ syncphasor kbeathz * kdivisions, a(gkseq_beat) 
		kt trigger k(as), 0.05, 0 ; was 0.005.. works?
	endif
	ktrigout = 0
	if (kt == 1) then
		ktrigout tab kindex, ifn
		if (ktrigout == 1 && kchanceon < 1) then
			if (random:k(0, 1) > kchanceon) then
				ktrigout = 0
			endif
		elseif (ktrigout == 0 && kchanceoff < 1) then
			if (random:k(0, 1) > kchanceoff) then
				ktrigout = 1
			endif
		endif
		klaunchindex = kindex
		if (kindex < klength - 1) then
			kindex += 1
		else
			kindex = 0
		endif
	endif

	ktrigout = vdel_k(ktrigout, seq_swingtime(0, ((kindex-1)/kdivisions)*4, kswing), 1)
	xout ktrigout, klaunchindex
endop

; override for single output
opcode seq_table, k, iOJPPJJJ
	ifn, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing, kbeathz xin
	ktrig, kindex seq_table ifn, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing, kbeathz
	xout ktrig
endop


/*
	Numeric output table sequencer 

	kvalout seq_table_numeric ifntrig, ifnval [, kreset=0, kdivisions=4, kchanceon=1, kchanceoff=1, klength=ftlen(ifn), kswing=gkseq_swing]

	kvalout 		the numeric output

	ifntrig			table containing boolean positions
	ifnval			table containing values to return
	kreset			if above 0 and changed since last value, then reset sequence index to 0
	kdivisions		how many points feature in one beat
	kchanceon		chance of an on point being on (1 = always, 0 = never)
	kchanceoff		chance of an off point being off (1 = always, 0 = never)
	klength			the maximum number of points in the table to use
	kswing			the swing amount to apply
*/
opcode seq_table_numeric, k, iiOJPPJJ
	ifntrig, ifnval, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing xin

	if (ftlen(ifnval) != ftlen(ifntrig)) then
		prints "seq_table_numeric: ifntrig and ifnval are not the same length\n\n"
		exitnow
	endif

	kvalout = -1
	ktrig, kindex seq_table ifntrig, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing

	if (ktrig == 1) then
		kvalout tab kindex, ifnval
	endif

	xout kvalout
endop


/*
	Table sequencer which calls the instrument with number instrnum when ifntrig is 1 for the current index.
	The instrument is passed the following parameters:
		p4		index of playback
		p5		value of kp5 from opcode parameters

	seq_table_scheduler instrnum, ifntrig, [ifnstart=-1, ifndur=-1, kp5=0, kreset=0, kdivisions=4, kchanceon=1, kchanceoff=1, klength=ftlen(ifn), kswing=gkseq_swing]

	instrnum		instrument number to schedule
	ifntrig			table containing boolean triggers per position. 
	ifnstart		table containing start times (offset from current position). If -1, all instances have the start time 0
	ifndur			table containing durations per position. If -1, all instances have the duration 1
	kp5				value to be passed to instrument as p5 if required
	kreset			if above 0 and changed since last value, then reset sequence index to 0
	kdivisions		how many points feature in one beat
	kchanceon		chance of an on point being on (1 = always, 0 = never)
	kchanceoff		chance of an off point being off (1 = always, 0 = never)
	klength			the maximum number of points in the table to use
	kswing			the swing amount to apply
*/
opcode seq_table_scheduler, 0, iijjOOJPPJJ
	instrnum, ifntrig, ifnstart, ifndur, kp5, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing xin

	if (ifnstart != -1 && ftlen(ifnstart) != ftlen(ifntrig)) then
		prints "seq_table_scheduler: ifntrig and ifnstart are not the same length\n\n"
		exitnow
	endif

	if (ifndur != -1 && ftlen(ifndur) != ftlen(ifntrig)) then
		prints "seq_table_scheduler: ifntrig and ifndur are not the same length\n\n"
		exitnow
	endif

	ktrig, kindex seq_table ifntrig, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing
	
	if (ktrig == 1) then
		schedulek instrnum,\ 
			(ifnstart == -1) ? 0 : tab:k(kindex, ifnstart),\
			(ifndur == -1) ? 1 : tab:k(kindex, ifndur),\
			kindex, kp5
	endif
endop


/*
	Table sequencer which calls the instrument with name Sinstrument when ifntrig is 1 for the current index.
	The instrument is passed the following parameters:
		p4		index of playback
		p5		value of kp5 from opcode parameters

	seq_table_scheduler instrnum, ifntrig, [ifnstart=-1, ifndur=-1, kp5=0, kreset=0, kdivisions=4, kchanceon=1, kchanceoff=1, klength=ftlen(ifn), kswing=gkseq_swing]

	Sinstrument		instrument name to schedule
	ifntrig			table containing boolean triggers per position. 
	ifnstart		table containing start times (offset from current position). If -1, all instances have the start time 0
	ifndur			table containing durations per position. If -1, all instances have the duration 1
	kp5				value to be passed to instrument as p5 if required
	kreset			if above 0 and changed since last value, then reset sequence index to 0
	kdivisions		how many points feature in one beat
	kchanceon		chance of an on point being on (1 = always, 0 = never)
	kchanceoff		chance of an off point being off (1 = always, 0 = never)
	klength			the maximum number of points in the table to use
	kswing			the swing amount to apply
*/
opcode seq_table_scheduler, 0, SijjOOJPPJJ
	Sinstrument, ifntrig, ifnstart, ifndur, kp5, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing xin
	seq_table_scheduler nstrnum(Sinstrument), ifntrig, ifnstart, ifndur, kp5, kreset, kdivisions, kchanceon, kchanceoff, klength, kswing
endop

#end