From 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 13 Apr 2025 18:48:02 +0100 Subject: initial --- site/udo/transient_detect.udo | 216 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100755 site/udo/transient_detect.udo (limited to 'site/udo/transient_detect.udo') 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 -- cgit v1.2.3