#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