aboutsummaryrefslogtreecommitdiff
path: root/site/udo/twist/transform_api.udo
blob: 9b916e32dcda1188f4479988edc987aaff5871d0 (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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#ifndef UDO_TWIST_TRANSFORMAPI
#define UDO_TWIST_TRANSFORMAPI ##

#define TWST_TRANSFORM #i_ = p4#

opcode twst_param, k, S
	Sname xin
	Schannel = sprintf("%s_%s%d", nstrstr(p1), Sname, p4)
	kvalue chnget Schannel
	xout kvalue
endop

opcode twst_parami, i, S
	Sname xin
	Schannel = sprintf("%s_%s%d", nstrstr(p1), Sname, p4)
	ivalue chnget Schannel
	xout ivalue
endop

opcode twst_getinput, aaii, 0
	aL chnget "twstfeedL"
	aR chnget "twstfeedR"
	xout aL, aR, gitwst_tf_state[0], gitwst_tf_state[1]
endop

opcode twst_setlatencysamples, 0, i
	isamples xin
	gitwst_tf_state[5] = isamples
endop

opcode twst_setlatencyseconds, 0, i
	iseconds xin
	twst_setlatencysamples iseconds * sr
endop

opcode twst_getlatencyseconds, i, 0
	xout gitwst_tf_state[5] / sr
endop

opcode twst_tf_pitchscale_custom, k, S
	SchanPrepend xin
	if (twst_param(strcat(SchanPrepend, "pitchscalemode")) == 1) then
		ksemitones = twst_param(strcat(SchanPrepend, "pitchsemitones"))
		kscale = pow:k(2, ksemitones / 12)
	else
		kscale = twst_param(strcat(SchanPrepend, "pitchscale"))
	endif
	xout kscale
endop

opcode twst_tf_pitchscale, k, 0
	xout twst_tf_pitchscale_custom("")
endop

opcode twst_tf_freq_custom, k, S
	SchanPrepend xin
	if (twst_param(strcat(SchanPrepend, "freqmode")) == 1) then
		kfreq = cpsmidinn:k(twst_param(strcat(SchanPrepend, "note")))
	else
		kfreq = twst_param(strcat(SchanPrepend, "freq"))
	endif
	xout kfreq
endop

opcode twst_tf_freq, k, 0
	xout twst_tf_freq_custom("")
endop

opcode twst_tf_freqi_custom, i, S
	SchanPrepend xin
	if (twst_parami(strcat(SchanPrepend, "freqmode")) == 1) then
		ifreq = cpsmidinn:i(twst_parami(strcat(SchanPrepend,"note")))
	else
		ifreq = twst_parami(strcat(SchanPrepend,"freq"))
	endif
	xout ifreq
endop

opcode twst_tf_freqi, i, 0
	xout twst_tf_freqi_custom("")
endop

opcode twst_tf_setplayposition, 0, k
	kplayposratio xin
	chnset kplayposratio, "twst_tfplayposratio"
endop

opcode twst_tf_getwintype, i, j
	iwintype xin
	if (iwintype == -1) then
		iwintype = twst_parami("wintype")
	endif
	ifnWindow = gifnHanning
	if (iwintype == 1) then
		ifnWindow = gifnHamming
	elseif (iwintype == 2) then
		ifnWindow = gifnHalfSine
	endif
	xout ifnWindow
endop

opcode twst_tf_getwintypek, k, 0
	kwintype = twst_param("wintype")
	kfnWindow = gifnHanning
	if (kwintype == 1) then
		kfnWindow = gifnHamming
	elseif (kwintype == 2) then
		kfnWindow = gifnHalfSine
	endif
	xout kfnWindow
endop

opcode twst_tf_getwaveform, i, j
	iwave xin
	if (iwave == -1) then
		iwave = twst_parami("wave")
	endif	
	ifn = gifnSine
	if (iwave == 1) then
		ifn = gifnSquare
	elseif (iwave == 2) then
		ifn = gifnSaw
	elseif (iwave == 3) then
		ifn = gifnPulse
	elseif (iwave == 4) then
		ifn = gifnTriangle
	endif
	xout ifn
endop

opcode twst_tf_getwaveformk, k, J
	kwave xin
	kwave = (kwave == -1) ? twst_param("wave") : kwave
	kfn = gifnSine
	if (kwave == 1) then
		kfn = gifnSquare
	elseif (kwave == 2) then
		kfn = gifnSaw
	elseif (kwave == 3) then
		kfn = gifnPulse
	elseif (kwave == 4) then
		kfn = gifnTriangle
	endif
	xout kfn
endop

opcode twst_getfinput, ffaaii, jJ
	ifftsize, kpvslock xin
	ifftsize = (ifftsize == -1) ? twst_parami("fftsize") : ifftsize
	kpvslock = (kpvslock == -1) ? twst_param("pvslock") : kpvslock
	iwintype = twst_parami("pvswintype")
	idecimation = twst_parami("pvsdecimation")
	iwinsizem = twst_parami("pvswinsizem")
	
	iwinsize = ifftsize * iwinsizem
	twst_setlatencysamples(iwinsize) ;idecimation)
	aL, aR, ileft, iright twst_getinput
	
	if (ileft == 0) then
		fL pvsinit ifftsize
	else
		fLbase pvsanal aL, ifftsize, ifftsize / idecimation, iwinsize, 1
		fL pvslock fLbase, kpvslock
	endif

	if (iright == 0) then
		fR pvsinit ifftsize
	else
		fRbase pvsanal aR, ifftsize, ifftsize / idecimation, iwinsize, 1
		fR pvslock fRbase, kpvslock
	endif
	xout fL, fR, aL, aR, ileft, iright
endop

/* TODO: LPC unstable with WASM
opcode twst_getfinput, ffaaii, jJ
	ifftsize, kpvslock xin
	ifftsize = (ifftsize == -1) ? twst_parami("fftsize") : ifftsize
	kpvslock = (kpvslock == -1) ? twst_param:k("pvslock") : kpvslock
	ipvstype = twst_parami("pvstype")
	iwintype = twst_parami("pvswintype")
	iwinlpcfn = twst_tf_getwintype(twst_parami("pvswintypelpc"))
	idecimation = twst_parami("pvsdecimation")
	iwinsizem = twst_parami("pvswinsizem")
	iorderm = twst_parami("pvsorderm")
	
	if (ipvstype == 1) then
		ifftsize = min(ifftsize, 1024) ; crashes in WASM with high FFT size and LPC
	endif

	iorder = min(max(1, round(ifftsize * iorderm)), ifftsize)
	iwinsize = ifftsize * iwinsizem
	twst_setlatencysamples(iwinsize) ;idecimation)
	aL, aR, ileft, iright twst_getinput
	
	if (ileft == 0) then
		fL pvsinit ifftsize
	else
		if (ipvstype == 0) then
			fLbase pvsanal aL, ifftsize, ifftsize / idecimation, iwinsize, 1
		else
			fLbase pvslpc aL, ifftsize, ifftsize / idecimation, iorder, iwinlpcfn
		endif
		fL pvslock fLbase, kpvslock
	endif

	if (iright == 0) then
		fR pvsinit ifftsize
	else
		if (ipvstype == 0) then
			fRbase pvsanal aR, ifftsize, ifftsize / idecimation, iwinsize, 1
		else
			fRbase pvslpc aR, ifftsize, ifftsize / idecimation, iorder, iwinlpcfn
		endif
		fR pvslock fRbase, kpvslock
	endif
	xout fL, fR, aL, aR, ileft, iright
endop
*/


; ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate
opcode twst_tf_getstate, iiiiii, 0
	ilengths = ((gitwst_tf_state[3] - gitwst_tf_state[2]) / sr)
	xout gitwst_tf_state[0], gitwst_tf_state[1], gitwst_tf_state[2], gitwst_tf_state[3], gitwst_tf_state[4], ilengths
endop

opcode twst_tf_isoffline, i, 0
	xout gitwst_tf_state[6] 
endop

opcode twst_tfi_getfn, ii, jjjjjj
	instanceindex, ileft, iright, istartsamp, iendsamp, idocut xin
	instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
	ileft = (ileft == -1) ? gitwst_tf_state[0] : ileft
	iright = (iright == -1) ? gitwst_tf_state[1] : iright
	istartsamp = (istartsamp == -1) ? gitwst_tf_state[2] : istartsamp
	iendsamp = (iendsamp == -1) ? gitwst_tf_state[3] : iendsamp
	idocut = (idocut == -1) ? gitwst_tf_state[4] : idocut
	if (idocut == 1) then
		itargetlen = iendsamp - istartsamp ;int(p3 * sr)
		if (ileft == 1) then
			ifnL ftgentmp 0, 0, -itargetlen, -2, 0
			ftslicei gitwst_bufferL[instanceindex], ifnL, istartsamp, iendsamp, 1 
		else
			ifnL = 0
		endif
		if (iright == 1) then
			ifnR ftgentmp 0, 0, -itargetlen, -2, 0
			ftslicei gitwst_bufferR[instanceindex], ifnR, istartsamp, iendsamp, 1
		else
			ifnR = 0
		endif		
	else
		ifnL = gitwst_bufferL[instanceindex]
		ifnR = gitwst_bufferR[instanceindex]
	endif
	xout ifnL, ifnR
endop

opcode _twst_getcrossdata, iiiiiii, S
	SchannelPrefix xin
	if (strcmp(SchannelPrefix, "") == 0) then
		ichannel = twst_parami("instchan")
		instanceindex = twst_parami("instance")
		istart = twst_parami("inststart")
		iend = twst_parami("instend")
	else
		ichannel chnget strcat(SchannelPrefix, sprintf("instchan%d", p4))
		instanceindex chnget strcat(SchannelPrefix, sprintf("instance%d", p4))
		istart chnget strcat(SchannelPrefix, sprintf("inststart%d", p4))
		iend chnget strcat(SchannelPrefix, sprintf("instend%d", p4))
	endif
	idoleft = 1
	idoright = 1
	if (ichannel == 0 || gitwst_channels[instanceindex] == 1) then
		idoright = 0
	elseif (ichannel == 1 && gitwst_channels[instanceindex] == 2) then
		idoleft = 0
	endif
	if (istart == iend) then
		istart = 0
		iend = 1
	endif
	istart, ilen twst_getstartend istart, iend, instanceindex
	ifnL = gitwst_bufferL[instanceindex]
	ifnR = gitwst_bufferR[instanceindex]
	
	xout idoleft, idoright, ifnL, ifnR, instanceindex, istart, ilen
endop

opcode _twst_getcrossdata, iiiiii, S
	SchannelPrefix xin
	ileft, iright, ifnL, ifnR, instanceindex, istart, iend _twst_getcrossdata SchannelPrefix
	xout ifnL, ifnR, istart, iend - istart, ileft, iright
endop

opcode twst_getcrossdata, iiiiii, 0
	ifnL, ifnR, istart, ilen, idoleft, idoright _twst_getcrossdata ""
	xout ifnL, ifnR, istart, ilen, idoleft, idoright
endop

opcode twst_tfi_getcrossfn, ii, 0
	ileft, iright, ifnL, ifnR, instanceindex, istart, ilen _twst_getcrossdata ""
	idocut = (ftlen(ifnL) == ilen) ? 0 : 1
	ifnLtemp, ifnRtemp twst_tfi_getfn instanceindex, ileft, iright, istart, istart + ilen, idocut
	if (gitwst_channels[instanceindex] == 1) then
		ifnRtemp = ifnLtemp
	endif
	xout ifnLtemp, ifnRtemp
endop

opcode _twst_getcrossinput, aaii, S
	SchannelPrefix xin
	ifnL, ifnR, istart, ilen, idoleft, idoright _twst_getcrossdata SchannelPrefix
	if (strcmp(SchannelPrefix, "") == 0) then
		ilooptype = twst_parami("otlooptype")
	else
		ichannel chnget strcat(SchannelPrefix, sprintf("looptype%d", p4))
	endif
	apos lphasor 1, 0, ilen, ilooptype
	apos += istart
	
	if (idoleft == 1) then
		aL table3 apos, ifnL
	endif
	if (idoright == 1) then
		aR table3 apos, ifnR
	endif

	if (idoright == 0) then
		aR = aL
	endif
	if (idoleft == 0) then
		aL = aR
	endif
	xout aL, aR, idoleft, idoright
endop

opcode twst_getcrossinput, aaii, 0
	aL, aR, idoleft, idoright _twst_getcrossinput ""
	xout aL, aR, idoleft, idoright
endop

opcode twst_getfcrossinput, ffii, 0
	aL, aR, ileft, iright twst_getcrossinput
	ifftsize = twst_parami("fftsize")
	kpvslock = twst_param("pvslock")
	idecimation = twst_parami("pvsdecimation")
	iwinsizem = twst_parami("pvswinsizem")
	iwinsize = ifftsize * iwinsizem
	
	if (ileft == 0) then
		fL pvsinit ifftsize
	else
		fLbase pvsanal aL, ifftsize, ifftsize / idecimation, iwinsize, 1
		fL pvslock fLbase, kpvslock
	endif

	if (iright == 0) then
		fR pvsinit ifftsize
	else
		fRbase pvsanal aR, ifftsize, ifftsize / idecimation, iwinsize, 1
		fR pvslock fRbase, kpvslock
	endif
	xout fL, fR, ileft, iright
endop

opcode twst_tf_fresynth, a, f
	fsig xin
	imode = twst_parami("pvresmode")
	if (imode == 0) then
		aout pvsynth fsig
	else
		ifftsize = twst_parami("fftsize")
		ioscnum = max(round((ifftsize * 0.5) * twst_parami("pvaoscnum")) - 1, 1)
		kfmod = twst_param("pvafreqmod")
		ibinoffset = round(ifftsize * 0.5 * twst_parami("pvabinoffset"))
		ibinincr = twst_parami("pvabinincr")
		ioscnum = ioscnum  - ibinoffset
		ioscnum = min(((ifftsize * 0.5) / ibinincr), ioscnum)
		aout pvsadsyn fsig, ioscnum, kfmod, ibinoffset, ibinincr
	endif
	xout aout
endop

opcode twst_getrandombuffers, kk, k
	kstereounique xin
	kfnL = -1
	kfnR = -1

	if (kstereounique == 0) then
		while (kfnL == -1) do
			kindex = round:k(random:k(0, lenarray(gitwst_bufferL) - 1))
			if (ftexists(gitwst_bufferL[kindex]) == 1) then
				kfnL = gitwst_bufferL[kindex]
				if (ftexists(gitwst_bufferR[kindex]) == 1) then
					kfnR = gitwst_bufferR[kindex]
				else
					kfnR = kfnL
				endif
			endif
		od
	else
		while (kfnL == -1) do
			kfn = gitwst_bufferL[round:k(random:k(0, lenarray(gitwst_bufferL) - 1))]
			if (ftexists(kfn) == 1) then
				kfnL = kfn
			endif
		od
		while (kfnR == -1) do
			kfn = gitwst_bufferR[round:k(random:k(0, lenarray(gitwst_bufferR) - 1))]
			if (ftexists(kfn) == 1) then
				kfnR = kfn
			endif
		od
	endif
	xout kfnL, kfnR
endop

#end