#ifndef UDO_FXAUTOGLITCHBEAT #define UDO_FXAUTOGLITCHBEAT ## /* Autoglitch effects, quantised This file is part of the SONICS UDO collection by Richard Knight 2024 License: GPL-2.0-or-later http://1bpm.net */ #include "pvs_tabproc.udo" #include "sequencing.udo" #include "frequency_tools.udo" /* beat based autoglitcher in the style of dBlue Glitch aoutL, aoutR fx_autoglitchbeat aL, aR, krandomisetrig, ipatternlength aoutL, aoutR outputs aL, aR inputs krandomisetrig trigger to randomise the pattern ipatterlength pattern length in semiquavers, defaults to 32 */ opcode fx_autoglitchbeat, aa, aaOj aL, aR, krandomisetrig, ipatternlength xin ipatternlength = (ipatternlength == -1) ? 32 : ipatternlength ifnpatterns = ftgentmp(0, 0, -ipatternlength, -7, 0) ifnparams = ftgentmp(0, 0, -(ipatternlength * 2), -7, 0) ifnbufferL = ftgentmp(0, 0, -44100, -7, 0) ifnbufferR = ftgentmp(0, 0, -44100, -7, 0) imaxeffect = 7; 5 for no tpv kbeat init 0 knexteffect init 0 klasteffect init 0 kinit init 1 kwriting init 1 kparam0 init 0 kparam1 init 0 keffect init 0 if (kwriting == 1) then awritepos, a_ syncphasor 1, a(gkseq_beat) tablew aL, awritepos, ifnbufferL, 1 tablew aR, awritepos, ifnbufferR, 1 endif if (krandomisetrig == 1 || kinit == 1) then kindex = 0 while (kindex < ipatternlength) do ksame = (kindex != 0 && random:k(0, 1) > 0.7) ? 1 : 0 if (ksame == 0) then keffect = round:k(random:k(0, imaxeffect)) if (keffect == 0) then ; freqshift kparam0 = random:k(-1000, 50) elseif (keffect == 1) then ; ring mod kparam0 = random:k(110, 440) elseif (keffect == 2) then ; bit crush kparam0 = random:k(4, 32) elseif (keffect == 3 || keffect == 4 || keffect == 5) then ; retriggers and stretches kparam0 = pow:k(2, round:k(random:k(1, 3))) ; division time ; was up to 4 if (random:k(0, 1) > 0.8) then ; reverse parameter kparam1 = 1 else kparam1 = 0 endif endif endif tabw keffect, kindex, ifnpatterns tabw kparam0, kindex, ifnparams tabw kparam1, kindex + (1 * ftlen(ifnpatterns)), ifnparams kindex += 1 od kinit = 0 endif ktime timeinsts if (gkseq_beat == 1) then kcurrenteffect tab kbeat, ifnpatterns klasteffect tab (kbeat - 1 < 0) ? ipatternlength - 1 : kbeat - 1, ifnpatterns kparam0 tab kbeat, ifnparams kparam1 tab kbeat + (1 * ftlen(ifnpatterns)), ifnparams kbeat = (kbeat + 1 < ipatternlength) ? kbeat + 1 : 0 if (kcurrenteffect != klasteffect) then kwriting = 1 kwritestart = ktime endif endif if (kwriting == 1 && ktime - kwritestart >= gkseq_beattime) then ; record for one beat kwriting = 0 endif if (kcurrenteffect == 0) then ; freqshift aL, aR freqshift1 aL, aR, kparam0 elseif (kcurrenteffect == 1) then ; ring mod aL, aR ringmod1 aL, aR, kparam0 elseif (kcurrenteffect == 2) then ; bit crush aL, aR bitcrush aL, aR, kparam0 elseif (kcurrenteffect == 3 || kcurrenteffect == 4) then ; retriggers kdivisiontime = gkseq_beattime / kparam0 ;kwriting vdel_k 0, kdivisiontime, 1 kwritelength = kdivisiontime if (kparam1 == 0) then aposraw = phasor(gkseq_beathz * kparam0) else aposraw = 1 - phasor(gkseq_beathz * kparam0) endif if (kcurrenteffect == 4) then aposaug = abs:a(oscil:a(1, gkseq_beathz / 8)) apos = aposaug * (aposraw * kdivisiontime * ftsr(ifnbufferL)) else apos = aposraw * kdivisiontime * ftsr(ifnbufferL) endif aL tablei apos, ifnbufferL aR tablei apos, ifnbufferR elseif (kcurrenteffect == 5) then ; stretch kdivisiontime = gkseq_beattime / kparam0 if (kparam1 == 0) then aposraw = phasor(gkseq_beathz / kparam0) else aposraw = 1 - phasor(gkseq_beathz / kparam0) endif atime = aposraw * kdivisiontime kpitch init 1 aL mincer atime, 1, kpitch, ifnbufferL, 1 aR mincer atime, 1, kpitch, ifnbufferL, 1 elseif (kcurrenteffect == 6 || kcurrenteffect == 7) then ir = 512 finputL pvsanal aL * 1.5, ir, ir/4, ir, 1 finputR pvsanal aR * 1.5, ir, ir/4, ir, 1 kready, itpvL tpv_anal finputL kready, itpvR tpv_anal finputR tpv_scramble kready, itpvL, 1 tpv_scramble kready, itpvR, 1 finputL tpv_resynth itpvL, finputL finputR tpv_resynth itpvR, finputR aL pvsynth finputL aR pvsynth finputR endif xout aL, aR endop #end