aboutsummaryrefslogtreecommitdiff
path: root/site/udo/fx_autoglitchbeat.udo
blob: a39988c81d0cb6ed64e6061ed899d8aa0a0d3d37 (plain)
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
#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