aboutsummaryrefslogtreecommitdiff
path: root/site/udo/pvs_fsegproc.udo
blob: 984be8673ec73024fa0e5795371864022e527839 (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
#ifndef UDO_PVSFSEGPROC
#define UDO_PVSFSEGPROC ##
/*
	Segmented multiband frequency processing

	Instruments passed to fsegproc should begin with $FSEGPROCINPUT which will 
		provide the segment audio as aL and aR, and the segment group as igroupindex


	This file is part of the SONICS UDO collection by Richard Knight 2025
		License: GPL-2.0-or-later
		http://1bpm.net
*/

#include "bussing.udo"

gifsegproc_maxsessionindex = 0

opcode _fsegproc_channels, SS, ii
	isessionindex, igroupindex xin
	Ssend = sprintf("bp%d_%d_%d", isessionindex, igroupindex, 1)
	Sreturn = sprintf("bp%d_%d_%d", isessionindex, igroupindex, 0)
	xout Ssend, Sreturn
endop

opcode _fsegproc_send, 0, ffiio
	fL, fR, isessionindex, ifnsegbins, isegindex xin
	ifnmap = tab_i(isegindex, ifnsegbins)
	fmL pvsmaska fL, ifnmap, 1
	fmR pvsmaska fR, ifnmap, 1

	aL pvsynth fmL
	aR pvsynth fmR
	bus_mix sprintf("bp%d_%d", isessionindex, isegindex), aL, aR
	
	if (isegindex + 1 < ftlen(ifnsegbins)) then
		_fsegproc_send fL, fR, isessionindex, ifnsegbins, isegindex + 1
	endif
endop


opcode _fsegproc_receive, aa, iiS[]o
	isegments, isessionindex, Sinstrs[], igroupindex xin
	ilen = lenarray(Sinstrs)
	if (ilen == 1) then
		Sinstr = Sinstrs[0]
	elseif (ilen == isegments) then
		Sinstr = Sinstrs[igroupindex]
	else
		index = min(round((ilen / isegments) * igroupindex), isegments - 1)
		Sinstr = Sinstrs[index]
	endif
	aL, aR subinstr Sinstr, igroupindex, sprintf("bp%d_%d", isessionindex, igroupindex)
	if (igroupindex + 1 < isegments) then
		arL, arR _fsegproc_receive isegments, isessionindex, Sinstrs, igroupindex + 1
		aL += arL
		aR += arR
	endif
	xout aL, aR
endop


opcode _fsegproc_inner, aa, ffS[]jpj
	fL, fR, Sinstrs[], isegments, imode, ifnmap xin
	if (isegments == -1) then
		isegments = lenarray(Sinstrs)
	endif
	isessionindex = gifsegproc_maxsessionindex
	gifsegproc_maxsessionindex += 1
	aL, aR _fsegproc_receive isegments, isessionindex, Sinstrs

	i_, ibins, i_, i_ pvsinfo fL
	isegmentsize = 0
	icursegment = 0
	if (imode == 0) then
		isegmentsize = round(ibins / isegments)
	endif
	if (ifnmap == -1) then
		ifnmap ftgentmp 0, 0, ibins, 2, 0
		index = 0
		indexsegment = 0
		while (index < ftlen(ifnmap)) do
			if (imode == 0) then
				isegment = icursegment
				if (indexsegment + 1 >= isegmentsize  && icursegment + 1 < isegments) then
					icursegment += 1
					indexsegment = 0
				else
					indexsegment += 1
				endif
			else
				isegment = round(random(0, isegments - 1))
			endif
			tabw_i isegment, index, ifnmap
			index += 1
		od
	endif
	ifnsegbins ftgentmp 0, 0, -isegments, -2, 0
	index = 0
	while (index < isegments) do
		tabw_i ftgentmp(0, 0, -ibins, -2, 0), index, ifnsegbins
		index += 1
	od
	index = 0
	while (index < ftlen(ifnmap)) do
		tabw_i 1, index, tab_i(tab_i(index, ifnmap), ifnsegbins)
		index += 1
	od
	_fsegproc_send fL, fR, isessionindex, ifnsegbins
	xout aL, aR
endop

/*
	mode 0 = sequential, 1 = randomised
*/
opcode fsegproc, aa, ffS[]jpj
	fL, fR, Sinstrs[], isegments, imode, ifnmap xin
	aL, aR _fsegproc_inner fL, fR, Sinstrs, isegments, imode, ifnmap
	xout aL, aR
endop

opcode fsegproc, aa, ffSjpj
	fL, fR, Sinstr, isegments, imode, ifnmap xin
	Sinstrs[] fillarray Sinstr
	aL, aR _fsegproc_inner fL, fR, Sinstrs, isegments, imode, ifnmap
	xout aL, aR
endop

#define FSEGPROCINPUT #
igroupindex = p4
Sbus = p5
aL, aR bus_read Sbus
#

#end