diff options
author | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
---|---|---|
committer | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
commit | 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch) | |
tree | 291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/udo/transient_detect.udo | |
download | apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2 apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip |
initial
Diffstat (limited to 'site/udo/transient_detect.udo')
-rwxr-xr-x | site/udo/transient_detect.udo | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/site/udo/transient_detect.udo b/site/udo/transient_detect.udo new file mode 100755 index 0000000..4acf1d3 --- /dev/null +++ b/site/udo/transient_detect.udo @@ -0,0 +1,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
|