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
|
#ifndef UDO_SPECTRALTRANSFORMS
#define UDO_SPECTRALTRANSFORMS ##
/*
Spectral transforms, mostly recursive using pvsbin
This file is part of the SONICS UDO collection by Richard Knight 2024
License: GPL-2.0-or-later
http://1bpm.net
*/
#include "/wavetables.udo"
/*
Validate start and end bins against a f-sig, and check/set common variables
If start and end are <= 1, treat them as ratios and calculate accordingly
istartbin, iendbin, ibin, kportamento, ifnwave _spc_validatebins fsig [, istart=0, iend=1, kportamento=-1, ifnwave=-1]
istartbin resulting bin number
iendbin resulting bin number
ibin initial bin to use
kportamento portamento in/out
ifnwave wave f-table in/out
fsig f-sig to validate maximum bin number against
istart start bin number or ratio
iend end bin number or ratio
*/
opcode _spc_validatebins, iiiki, fopJj
fsig, istart, iend, kportamento, ifnwave xin
ioverlap, inumbins, iwinsize, iformat pvsinfo fsig
if (istart <= 1 && iend <= 1) then ; is ratio
istartbin = max(round(inumbins * istart), 1)
iendbin = round(inumbins * iend)
else ; is absolute bin number
istartbin = max(1, istart)
iendbin = min(inumbins, iend)
endif
ibin = istartbin
kportamento = (kportamento == -1) ? 0.02 : kportamento
ifnwave = (ifnwave == -1) ? gifnSine : ifnwave
xout istartbin, iendbin, ibin, kportamento, ifnwave
endop
/*
Spectral delay
aout spc_delay fsig, kdeltime, kdeladd [, istart=0, iend=1, kfreqmod=1, kportamento=0.01, ifnwave=-1, ibin=-1]
aout audio output
fsig input signal
kdeltime initial delay time in seconds
kdeladd increment delay by this with each bin increment or decrement
istart absolute bin number or ratio of the start bin, top end bins may be quite low, around a ratio of 0.1
iend absolute bin number or ratio of the end bin
kfreqmod frequency modulation ratio in resynthesis
kportamento portamento time for amp and frequency
ifnwave f-table to use for the oscillator, default is sine
ibin bin tracking used internally, should not be set
*/
opcode spc_delay, a, fkkopPJjj
fsig, kdeltime, kdeladd, istart, iend, kfreqmod, kportamento, ifnwave, ibin xin
if (ibin == -1) then
istart, iend, ibin, kportamento, ifnwave _spc_validatebins fsig, istart, iend, kportamento, ifnwave
endif
idirection = (istart < iend) ? 1 : -1
kamp, kfreq pvsbin fsig, ibin
imaxdelay = 1000
aout oscili portk(kamp, kportamento), portk(kfreq, kportamento) * kfreqmod, ifnwave
kdel = min:k(imaxdelay, kdeltime + (kdeladd * (((idirection == 1) ? ibin - istart : istart - ibin) + 1)) * 1000)
aout vdelay aout, a(kdel), imaxdelay
if ((idirection == 1 && ibin + 1 < iend) || (idirection == -1 && ibin - 1 >= iend)) then
arecurse spc_delay fsig, kdeltime, kdeladd, istart, iend, kfreqmod, kportamento, ifnwave, ibin + idirection
aout += arecurse
endif
xout aout
endop
/*
Spectral incremental shift
aout spc_shift fsig, kfreqincr [, istart=0, iend=1, kfreqmod=1, kportamento=0.01, ifnwave=-1, ibin=-1]
aout audio output
fsig input signal
kfreqincr frequency increment for each bin, may be positive or negative
istart absolute bin number or ratio of the start bin, top end bins may be quite low, around a ratio of 0.1
iend absolute bin number or ratio of the end bin
kfreqmod frequency modulation ratio in resynthesis
kportamento portamento time for amp and frequency
ifnwave f-table to use for the oscillator, default is sine
ibin bin tracking used internally, should not be set
*/
opcode spc_shift, a, fkopPJjj
fsig, kfreqincr, istart, iend, kfreqmod, kportamento, ifnwave, ibin xin
if (ibin == -1) then
istart, iend, ibin, kportamento, ifnwave _spc_validatebins fsig, istart, iend, kportamento, ifnwave
endif
idirection = (istart < iend) ? 1 : -1
kamp, kfreq pvsbin fsig, ibin
kfreqadd = (((idirection == 1) ? ibin - istart : istart - ibin) + 1) * kfreqincr
aout oscili portk(kamp, kportamento), portk(kfreq + kfreqadd, kportamento) * kfreqmod, ifnwave
if ((idirection == 1 && ibin + 1 < iend) || (idirection == -1 && ibin - 1 >= iend)) then
arecurse spc_shift fsig, kfreqincr, istart, iend, kfreqmod, kportamento, ifnwave, ibin + idirection
aout += arecurse
endif
xout aout
endop
/*
Spectral gate
aout spc_gate fsig, kthresh [, khold=0, istart=0, iend=1, kfreqmod=1, kportamento=0.01, ifnwave=-1, ibin=-1]
aout audio output
fsig input signal
kthresh threshold amplitude for gating
khold hold amplitudes rather than decaying them
istart absolute bin number or ratio of the start bin, top end bins may be quite low, around a ratio of 0.1
iend absolute bin number or ratio of the end bin
kfreqmod frequency modulation ratio in resynthesis
kportamento portamento time for amp and frequency
ifnwave f-table to use for the oscillator, default is sine
ibin bin tracking used internally, should not be set
*/
opcode spc_gate, a, fkOopPJjj
fsig, kthresh, khold, istart, iend, kfreqmod, kportamento, ifnwave, ibin xin
if (ibin == -1) then
istart, iend, ibin, kportamento, ifnwave _spc_validatebins fsig, istart, iend, kportamento, ifnwave
endif
idirection = (istart < iend) ? 1 : -1
klastamp init 0
klastfreq init 0
kamp, kfreq pvsbin fsig, ibin
if (kamp > kthresh) then
klastamp = kamp
klastfreq = kfreq
else
kamp = (khold == 1) ? klastamp : 0
kfreq = klastfreq
endif
aout oscili portk(kamp, kportamento), portk(kfreq, kportamento) * kfreqmod, ifnwave
if ((idirection == 1 && ibin + 1 < iend) || (idirection == -1 && ibin - 1 >= iend)) then
arecurse spc_gate fsig, kthresh, khold, istart, iend, kfreqmod, kportamento, ifnwave, ibin + idirection
aout += arecurse
endif
xout aout
endop
/*
Spectral granular resynthesis 1
Internal opcode
*/
opcode _spc_grain1_inner, a, ikkpopPJJOJjpp
ipbuf, ktime, kgraindur, ilayers, istart, iend, kfreqmod, kfreqrand, kdurrand, kpitchrand, kportamento, ifnwave, ibin, ibingrain xin
idirection = (istart < iend) ? 1 : -1
kchange metro 1 / kgraindur;/ 1
if (kchange == 1) then
if (kfreqrand > 1) then
kfreqrandv random 1 / kfreqrand, kfreqrand
elseif (kfreqrand == 1) then
kfreqrandv = 1
else
kfreqrandv random 0.5, 2
endif
if (kdurrand > 1) then
kdurrandv random 1 / kdurrand, kdurrand
elseif (kdurrand == 1) then
kdurrandv = 1
else
kdurrandv random 0.5, 2
endif
if (kpitchrand > 1) then
kpitchrandv random 1 / kpitchrand, kpitchrand
else
kpitchrandv = 1
endif
endif
kreadfreq = (1 / kgraindur) * kfreqrandv ;5 + random:k(1, 5) ;random(10, 20) ;10 + random:k(0, 5)
kenv = abs:k(oscili:k(1, kreadfreq, gifnHanning, random(0, 1)))
areadpos phasor kreadfreq, random(0, 1)
kreadtime = ktime + (k(areadpos) * kgraindur * kdurrandv) ;ktime + random(0, 0.6) ;portk(ktime + random:k(0, 0.6), kportamento)
fsig pvsbufread kreadtime, ipbuf
kamp, kfreq pvsbin fsig, ibin
kfreq *= kpitchrandv
kamp *= kenv
aout oscil portk(kamp, kportamento), portk(kfreq, kportamento) * kfreqmod, ifnwave
if (ibingrain < ilayers) then
arecurse _spc_grain1_inner ipbuf, ktime, kgraindur, ilayers, istart, iend, kfreqmod, kfreqrand, kdurrand, kpitchrand, kportamento, ifnwave, ibin, ibingrain + 1
aout += arecurse
elseif ((idirection == 1 && ibin + 1 < iend) || (idirection == -1 && ibin - 1 >= iend)) then
arecurse _spc_grain1_inner ipbuf, ktime, kgraindur, ilayers, istart, iend, kfreqmod, kfreqrand, kdurrand, kpitchrand, kportamento, ifnwave, ibin + idirection
aout += arecurse
endif
xout aout
endop
/*
Spectral granular resynthesis 1
aout spc_grain1 ifn, ktime, kgraindur [, ifftsize=512, ilayers=1, istart=0, iend=1, kfreqmod=1, kfreqrand=1, kdurrand=1, kpitchrand=0, kportamento=0.01, ifnwave=-1]
aout audio output
ifn f-table containing mono source sound
ktime read time in seconds
kgraindur grain duration in seconds
ifftsize fft size for the input
ilayers number of overlapping layers of grains to use
istart absolute bin number or ratio of the start bin, top end bins may be quite low, around a ratio of 0.1
iend absolute bin number or ratio of the end bin
kfreqmod frequency modulation ratio in resynthesis
kfreqrand read frequency random variation ratio
kdurrand grain duration random variation ratio
kpitchrand grain pitch random variation ratio
kportamento portamento time for amp and frequency
ifnwave f-table to use for the oscillator, default is sine
*/
opcode spc_grain1, a, ikkjpopPJJOJj
ifn, ktime, kgraindur, ifftsize, ilayers, istart, iend, kfreqmod, kfreqrand, kdurrand, kpitchrand, kportamento, ifnwave xin
ifftsize = (ifftsize == -1) ? 512 : ifftsize
ktimek timeinstk
ilen = ftlen(ifn) / ftsr(ifn)
ikcycles = ilen * kr
kcount init 0
if (ktimek == 1) then
while (kcount < ikcycles) do
apos linseg 0, ilen, ftlen(ifn)
asig table3 apos, ifn
fsig pvsanal asig, ifftsize, ifftsize/4, ifftsize, 1
ipbuf, k_ pvsbuffer fsig, ilen
kcount += 1
od
else
istartbin, iendbin, ibin, kportamento, ifnwave _spc_validatebins fsig, istart, iend, kportamento, ifnwave
aout _spc_grain1_inner ipbuf, ktime, kgraindur, ilayers, istartbin, iendbin, kfreqmod, kfreqrand, kdurrand, kpitchrand, kportamento, ifnwave, ibin
endif
xout aout
endop
/*
Alter the phase of FFT values
aout spc_phasemash ain, kphasemode, kphasevalue, ifftsize
aout audio output
ain audio input
kphasemode phase mode: 0 = multiply phase with kphasevalue; 1 = replace phase with kphasevalue
kphasevalue phase value, between -pi and +pi
ifftsize fft size
*/
opcode spc_phasemash, a, akkj
ain1, kphasemode, kphasevalue, ifftsize xin
ifftsize = (ifftsize == -1) ? 512 : ifftsize
ihopsize = ksmps
iolaps = (ifftsize / ihopsize)
ibw = (sr / ifftsize)
kcnt init 0
krow init 0
kOla1[] init ifftsize
kIn1[] init ifftsize
kOut[][] init iolaps, ifftsize
if (kcnt == ihopsize) then
kdx = 0
kWin1[] window kIn1, krow * ihopsize
kSpec1[] rfft kWin1
kmags1[] mags kSpec1
kphs1[] phs kSpec1 ;init lenarray(kmags1) ;phs kSpec1
kindex = 0
while (kindex < lenarray(kphs1)) do
if (kindex > 0) then
if (kphasemode == 0) then
kphs1[kindex] = kphs1[kindex] * kphasevalue
else
kphs1[kindex] = kphasevalue
endif
endif
kindex += 1
od
kSpec1 pol2rect kmags1, kphs1
kRow[] rifft kSpec1
kWin1 window kRow, krow * ihopsize
kOut setrow kWin1, krow
kOla1 = 0
ki = 0
until (ki == iolaps) do
kRow getrow kOut, ki
kOla1 = kOla1 + kRow
ki += 1
od
krow = (krow + 1) % iolaps
kcnt = 0
endif
kIn1 shiftin ain1
aout shiftout kOla1
aouter = aout / iolaps
kcnt += ksmps
xout aouter
endop
/*
opcode spc_attack, a, fkOopPJjj
fsig, kthresh, khold, istart, iend, kfreqmod, kportamento, ifnwave, ibin xin
if (ibin == -1) then
istart, iend, ibin, kportamento, ifnwave _spc_validatebins fsig, istart, iend, kportamento, ifnwave
endif
idirection = (istart < iend) ? 1 : -1
klastamp init 0
klastfreq init 0
kamp, kfreq pvsbin fsig, ibin
if (kamp > kthresh) then
klastamp = kamp
klastfreq = kfreq
else
kamp = (khold == 1) ? klastamp : 0
kfreq = klastfreq
endif
aout oscil portk(kamp, kportamento), portk(kfreq, kportamento) * kfreqmod, ifnwave
if ((idirection == 1 && ibin + 1 < iend) || (idirection == -1 && ibin - 1 >= iend)) then
arecurse spc_gate fsig, kthresh, khold, istart, iend, kfreqmod, kportamento, ifnwave, ibin + idirection
aout += arecurse
endif
xout aout
endop
*/
#end
|