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
|
#ifndef UDO_TRANSIENTDETECT
#define UDO_TRANSIENTDETECT ##
/*
Transient detection
This file is part of the SONICS UDO collection by Richard Knight 2021
License: GPL-2.0-or-later
http://1bpm.net
*/
/*
Internal transient detection base
*/
opcode _transientdetect, kk,kikkki
kin, iresponse, ktthresh, klowThresh, kdecThresh, idoubleLimit xin
kinDel delayk kin, iresponse / 1000
ktrig = ((kin > kinDel + ktthresh) ? 1 : 0)
klowGate = (kin < klowThresh ? 0 : 1)
ktrig = ktrig * klowGate
ktransLev init 0
ktransLev samphold kin, 1-ktrig
kreGate init 1
ktrig = ktrig * kreGate
kmaxAmp init -99999
kmaxAmp max kmaxAmp, kin
kdiff = kmaxAmp-kin
kreGate limit kreGate-ktrig, 0, 1
kreGate = (kdiff > kdecThresh ? 1 : kreGate)
kmaxAmp = (kreGate == 1 ? -99999 : kmaxAmp)
xout ktrig, kdiff
endop
opcode transientdetect, k, akkiikkk
ain, kattack, krelease, iresponse, idoublelimit, ktthresh, klowthresh, kdecthresh xin
afollow follow2 ain, kattack, krelease
kfollow downsamp afollow
kfollowdb = dbfsamp(kfollow)
ktrig, kdiff _transientdetect kfollowdb, iresponse, ktthresh, klowthresh, kdecthresh, idoublelimit
xout ktrig
endop
/*
Default transient detection
ktrigger transientdetect ainput
ktrigger fires when a transient has been detected
ainput the audio signal to track
*/
opcode transientdetect, k, a
ain xin
kattack init 0.05
krelease init 0.06
iresponse = 10
ktthresh = 9
klowthresh = -50
idoublelimit = 0.1
kdecthresh = 6
ktrig transientdetect ain, kattack, krelease, iresponse, idoublelimit, ktthresh, klowthresh, kdecthresh
xout ktrig
endop
/*
opcode transientdetect, k, a
ain xin
kattack init 0.05
krelease init 0.06
afollow follow2 ain, kattack, krelease
kfollow downsamp afollow
kfollowdb = dbfsamp(kfollow)
iresponse = 10
ktthresh = 9
klowthresh = -50
idoublelimit = 0.1
kdecthresh = 6
ktrig, kdiff _transientdetect kfollowdb, iresponse, ktthresh, klowthresh, kdecthresh, idoublelimit
xout ktrig
endop
*/
/*
Detect transients in audio ftable; count or output to ftable
p4 ftable to read sound from
p5 instrument name to invoke when complete, ftable contaqining transients is passed as p4
p6 0 = stage 1, count and recall; 1 = stage 2, write to ftable
p7 number of transients for ftable initialisation as used with stage 2
*/
instr _transientdetect_tofn_inner
ifnsound = p4
SonComplete = p5
istate = p6
itransientnum = p7
if (istate == 0) then
ifntransients = -1
else
ifntransients ftgen 0, 0, itransientnum, 7, 0
endif
kdone init 0
ktransientnum init 0
ktimek timeinstk
if (ktimek == 1) then
inputduration = ftlen(ifnsound) / ftsr(ifnsound)
kcycles = inputduration * kr
kcount init 0
while (kcount < kcycles) do
if (ftchnls(ifnsound) == 1) then
asound loscil 1, 1, ifnsound, 1
else
aL, aR loscil 1, 1, ifnsound, 1
asound = (aL + aR) / 2
endif
;ktransient, kdiff _transientdetectinner asound
ktransient transientdetect asound
if (ktransient == 1) then
if (ifntransients != -1) then
tablew (inputduration / kcycles) * kcount, ktransientnum, ifntransients
endif
ktransientnum += 1
endif
kcount += 1
od
else
if (istate == 0) then
if (ktransientnum == 0) then
schedulek(SonComplete, 0, 3600, -1)
else
schedulek(p1, 0, 1, ifnsound, SonComplete, 1, ktransientnum)
endif
else
schedulek(SonComplete, 0, 3600, ifntransients)
endif
turnoff
endif
endin
opcode transientdetect_tofn, 0, iS
ifn, SonComplete xin
schedule("_transientdetect_tofn_inner", 0, 600, ifn, SonComplete, 0, 0)
endop
opcode randomtransient, ii, i
ifntransients xin
iftlen = ftlen(ifntransients)
if (iftlen < 2) then
istart = tab_i(0, ifntransients)
ilen = 0.1
else
istartindex = round(random(0, iftlen - 2))
istart = tab_i(istartindex, ifntransients)
iend = tab_i(istartindex + 1, ifntransients)
ilen = iend - istart
endif
if (ilen > 1) then
ilen = 1
endif
xout istart, ilen
endop
/*
By Brandtsegg, I think; tweaked by RK
*/
opcode onsetdetect, k, aiiiiii
ain, iMinFreq, iMaxFreq, iAboveMed, iOffset, iMinSec, iMedLen xin
ifftsize = 1024
iIndexStart limit int(iMinFreq*(ifftsize/sr))*2,0,sr/2
iIndexEnd limit int(iMaxFreq*(ifftsize/sr))*2,0,sr/2
fsrc pvsanal ain,ifftsize,ifftsize/4,ifftsize,1
kArr[] init ifftsize+2
kflag pvs2array kArr, fsrc
ksumold init 0
kMedIndex init 0
kMedSum init 0
kMedian[] init iMedLen
kMinDist init 0
iMinDist = iMinSec*(sr/ksmps)
kMinDist limit kMinDist-1,0,100000
if changed(kflag) == 1 && kMinDist == 0 then
ksum = 0
kIndex = iIndexStart
until kIndex = iIndexEnd do
ksum = ksum+kArr[kIndex]
kIndex += 2
od
kFLUX = ksum-ksumold
ksumold = ksum
kOnset = 0
if kFLUX > (kMedSum*iAboveMed)+iOffset then
kOnset = 1
kMinDist = iMinDist
endif
kMedian[kMedIndex] = (kFLUX>=0?kFLUX:0)
kMedSum = sumarray(kMedian)/iMedLen
kMedIndex = (kMedIndex+1)%iMedLen
endif
xout changed(kOnset)==1 && kOnset==1 ? 1 : 0
endop
#end
|