diff options
author | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
---|---|---|
committer | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
commit | 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch) | |
tree | 291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/udo/scss/mixer/base.udo | |
download | apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2 apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip |
initial
Diffstat (limited to 'site/udo/scss/mixer/base.udo')
-rwxr-xr-x | site/udo/scss/mixer/base.udo | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/site/udo/scss/mixer/base.udo b/site/udo/scss/mixer/base.udo new file mode 100755 index 0000000..9721357 --- /dev/null +++ b/site/udo/scss/mixer/base.udo @@ -0,0 +1,253 @@ +#ifndef UDO_SCSS_MIXER_BASE
+#define UDO_SCSS_MIXER_BASE ##
+/*
+ SCSS mixer and dynamic insert system
+
+ This file is part of the SONICS UDO collection by Richard Knight 2022
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+
+#include "/bussing.udo"
+#include "/interop.udo"
+
+
+
+gSchannelHeader = {{
+ ichannelindex = p4
+ kamp chnget sprintf("mxamp%d", ichannelindex)
+ kpan chnget sprintf("mxpan%d", ichannelindex)
+ aL, aR bus_read sprintf("mxchan%d", ichannelindex)
+ kenv linsegr 0, 0.05, 1, p3, 1, 0.1, 0
+}}
+
+
+gSchannelFooter = {{
+ bus_masterout(aL*kenv*(1-kpan)*kamp, aR*kenv*kpan*kamp)
+endin
+}}
+
+
+; default globals: set in mx_boot
+gichannelnumber = -1
+gisendchannels = -1
+gimixermaxinserts = -1
+giinserts[][] init 1, 1
+gimxinitialised[] init 1, 1
+
+
+; actual effects and definitions
+#include "/scss/mixer/_effects.udo"
+/*
+ Set insert for channel and insert index ; apply defaults
+*/
+opcode apply_insert, 0, iii
+ iinsertdefindex, ichannelindex, iinsertindex xin
+
+ giinserts[ichannelindex][iinsertindex] = iinsertdefindex
+
+ ; set defaults
+ iJparams = jsonptr(giJinsertDefs, sprintf("/effects/%d/parameters", iinsertdefindex))
+ index = 0
+ while (index < jsonsize(iJparams)) do
+ iJparam jsonget iJparams, index ;jsonptr(iJparams, sprintf("/%d", index))
+ SparameterName jsongetval iJparam, "name"
+ idefault jsongetval iJparam, "default"
+ chnset idefault, sprintf("fxi_%s_%d_%d", SparameterName, ichannelindex, iinsertindex)
+ jsondestroy(iJparam)
+ index += 1
+ od
+ jsondestroy(iJparams)
+
+ ; initial state is on
+ chnset 1, sprintf("fxi_on_%d_%d", ichannelindex, iinsertindex)
+endop
+
+
+
+instr mx_effect_definitions_get
+ icbid = p4
+ iJson = jsonloads(gSeffectDefs)
+ jsoninsertval iJson, "cbid", icbid
+ io_sendstring("callback", jsondumps(iJson, 0))
+ turnoff
+endin
+
+instr mx_insert_info_get
+ icbid = p4
+ indexchan = p5
+
+ inserts[] init gimixermaxinserts
+ indexinsert = 0
+ while (indexinsert < gimixermaxinserts) do
+ inserts[indexinsert] = giinserts[indexchan][indexinsert]
+ indexinsert += 1
+ od
+ iJson = jsoninit()
+ jsoninsertval iJson, "cbid", icbid
+ jsoninsertval iJson, "inserts", inserts
+ io_sendstring("callback", jsondumps(iJson, 0))
+ turnoff
+endin
+
+
+/*
+ recompile channel instrument, inserting insert effects as specified
+*/
+instr mx_recompile_channel
+ ichannelindex = p4
+ SinstrName = sprintf("mixer_channel%d", ichannelindex)
+ Sinstr = sprintf("instr %s\n%s", SinstrName, gSchannelHeader)
+ index = 0
+ while (index < gimixermaxinserts) do
+ iinsert = giinserts[ichannelindex][index]
+ if (iinsert != -1) then
+ Sopcode jsonptrval giJinsertDefs, sprintf("/effects/%d/opcode", iinsert)
+ Sinstr = strcat(Sinstr, sprintf("aL, aR %s aL, aR, ichannelindex, %d\n", Sopcode, index))
+ endif
+ index += 1
+ od
+
+ ; initial amps and pans if not initialised
+ if (gimxinitialised[ichannelindex] == 0) then
+ gimxinitialised[ichannelindex] = 1
+ chnset 0.8, sprintf("mxamp%d", ichannelindex)
+ chnset 0.5, sprintf("mxpan%d", ichannelindex)
+ endif
+
+ ; channel footer with global sends
+ SchannelFooter = ""
+ isendindex = 0
+ if (gisendchannels != 0 && ichannelindex < gichannelnumber - 1) then
+ SchannelFooter = ""
+ while (isendindex < gisendchannels) do
+ SchannelFooter = strcat(SchannelFooter, sprintf("ksend%d chnget sprintf(\"mxsend%%d_%d\", ichannelindex)\nbus_mix \"mxchan%d\", aL*ksend%d, aR*ksend%d\n", isendindex, isendindex, gichannelnumber + isendindex, isendindex, isendindex))
+ isendindex += 1
+ od
+ Sinstr = strcat(Sinstr, SchannelFooter)
+ endif
+ Sinstr = strcat(Sinstr, gSchannelFooter)
+ ires compilestr Sinstr
+ turnoff2 SinstrName, 0, 1
+ schedule SinstrName, 0.02, 3600, ichannelindex
+ turnoff
+endin
+
+
+instr mx_setstate
+ Sjson = p4
+ iJson = jsonloads(Sjson)
+
+endin
+
+
+instr mx_getstate
+ iJsonCSChannels = jsoninit()
+ iJsonBlankArray = jsonloads("[]")
+ iJsonInserts = jsonloads("[]")
+ ichannelindex = 0
+ SchanDefaults[] fillarray "mxamp", "mxpan"
+ while (ichannelindex < gichannelnumber + gisendchannels) do
+ ichandefaultindex = 0
+ while (ichandefaultindex < lenarray(SchanDefaults)) do
+ jsoninsertval iJsonCSChannels, sprintf("%s%d", SchanDefaults[ichandefaultindex], ichannelindex), chnget:i(sprintf("%s%d", SchanDefaults[ichandefaultindex], ichannelindex))
+ ichandefaultindex += 1
+ od
+
+ jsonptradd iJsonInserts, sprintf("/%d", ichannelindex), iJsonBlankArray
+
+ indexinsert = 0
+ while (indexinsert < gimixermaxinserts) do
+ iinsert = giinserts[ichannelindex][indexinsert]
+ jsonptraddval iJsonInserts, sprintf("/%d/%d", ichannelindex, indexinsert), iinsert
+ if (iinsert != -1) then
+ iJparams = jsonptr(giJinsertDefs, sprintf("/effects/%d/parameters", iinsert))
+ index = 0
+ while (index < jsonsize(iJparams)) do
+ iJparam jsonget iJparams, index
+ SparameterName jsongetval iJparam, "name"
+ SparameterChan = sprintf("fxi_%s_%d_%d", SparameterName, ichannelindex, indexinsert)
+ jsoninsertval iJsonCSChannels, SparameterChan, chnget:i(SparameterChan)
+ jsondestroy(iJparam)
+ index += 1
+ od
+ jsondestroy(iJparams)
+
+ endif
+ indexinsert += 1
+ od
+
+ ichannelindex += 1
+ od
+ iJson = jsoninit()
+ jsoninsertval iJson, "channelnumber", gichannelnumber
+ jsoninsertval iJson, "sendchannels", gisendchannels
+ jsoninsertval iJson, "maxinserts", gimixermaxinserts
+ jsoninsert iJson, "cschannels", iJsonCSChannels
+ jsoninsert iJson, "inserts", iJsonInserts
+
+ prints jsondumps(iJson, 1)
+
+ jsondestroy(iJsonBlankArray)
+ jsondestroy(iJsonCSChannels)
+ jsondestroy(iJsonInserts)
+ jsondestroy(iJson)
+ turnoff
+
+endin
+
+
+instr mx_alter_insert
+ ichannelindex = p4
+ iinsertindex = p5
+ iinsertdefindex = p6
+
+ apply_insert iinsertdefindex, ichannelindex, iinsertindex
+
+ ;schedule "mx_sendstate", 0, 1
+ schedule "mx_recompile_channel", 0, 1, ichannelindex
+ turnoff
+endin
+
+instr mx_move_insert
+ ichannelindex = p4
+ iinsertindex_from = p5
+ iinsertindex_to = p6
+
+ ; keep state...
+endin
+
+
+/*
+ set up channels
+*/
+instr mx_boot
+ gichannelnumber = (p4 == 0) ? 12 : p4
+ gisendchannels = (p5 == 0) ? 2 : p5
+ gimixermaxinserts = (p6 == 0) ? 6 : p6
+
+ giinserts[][] init gichannelnumber + gisendchannels, gimixermaxinserts
+
+ ; set all to -1 as 0 is a valid entry
+ index1 = 0
+ while (index1 < lenarray(giinserts, 1)) do
+ index2 = 0
+ while (index2 < lenarray(giinserts, 2)) do
+ giinserts[index1][index2] = -1
+ index2 += 1
+ od
+ index1 += 1
+ od
+
+ ; if initialised, don't reset amp/pan etc
+ gimxinitialised[] init gichannelnumber + gisendchannels
+
+ ichannelindex = 0
+ while (ichannelindex < gichannelnumber + gisendchannels) do
+ schedule "mx_recompile_channel", 0, 1, ichannelindex
+ ichannelindex += 1
+ od
+ turnoff
+endin
+
+#end
|