#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