// mod-pool.lib — Shared modulation pool (ADSRs + LFOs) for the "Modular" mode. // // Provides 16 ADSR slots + 32 LFO slots that can be routed through a // per-engine modulation matrix to any parameter in the host .dsp. // Engines import this via: // // mp = library("mod-pool.lib"); // sources = mp.sources(gate); // 48-wide parallel bus // mod_x = sum(s, 48, sources : ba.selector(s, 48) * amount(s)); // // PUBLIC API // ---------- // // mp.N_ADSR integer — 16 // mp.N_LFO integer — 32 // mp.N_SOURCES integer — 48 (= N_ADSR + N_LFO) // // mp.adsrs(gate) bus — 16-wide parallel bus, each element [0,1] // mp.lfos bus — 32-wide parallel bus, each element [-1,+1] // mp.sources(gate) bus — 48-wide parallel bus (adsrs(gate), lfos) // // PARAMETER NAMESPACE CONVENTION // ------------------------------ // All mod-pool sliders live under groups prefixed with "MM_" so that the // paramMeta parser can segregate them from engine sound params: // // MM_ADSR/NN_adsrNN_{attack,decay,sustain,release,enable} (16 slots) // MM_LFO /NN_lfoNN_{rate,morph,enable} (32 slots) // // Engine-side matrix sliders (declared in the engine .dsp, not in this file) // should follow: // // MM_Matrix/sNN_dNN_ (48 * n_dst) // // where sNN = source index (0..47; 0..15 = ADSRs, 16..47 = LFOs), // dNN = destination index, and = short destination label. // // MUTING // ------ // Each slot has an "enable" hslider (0 or 1). The slot's output is multiplied // by the enable value so a muted slot contributes 0 at the matrix input. This // is cheap but does NOT let Faust eliminate the underlying env/LFO compute. // Compile-time dead-code elimination of unused slots is a future concern. // // LFO WAVEMORPH // ------------- // A single "morph" slider (0..1) crossfades through four shapes: // // [0.000, 0.333) : sine -> triangle // [0.333, 0.666) : triangle -> square // [0.666, 1.000] : square -> saw // // Implemented via nested ba.if so the chosen pair is a linear crossfade. // The output is always in [-1,+1]. // // --------------------------------------------------------------------------- import("stdfaust.lib"); // Counts (engine code can reference mp.N_SOURCES etc.) N_ADSR = 16; N_LFO = 32; N_SOURCES = 48; // --------------------------------------------------------------------------- // Per-slot hslider helpers. Unique label per slot index. // Slot indices are 1-based in labels (adsr01..adsr16, lfo01..lfo32) to keep // alphabetical ordering stable in the Faust JSON output. // --------------------------------------------------------------------------- // ADSR param factories — declared per-slot because Faust slider labels must // be string literals known at compile time. One function per slot index. adsr01_a = hslider("MM_ADSR/00_adsr01_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr01_d = hslider("MM_ADSR/00_adsr01_decay", 0.200, 0.001, 10.0, 0.001); adsr01_s = hslider("MM_ADSR/00_adsr01_sustain", 0.700, 0.0, 1.0, 0.001); adsr01_r = hslider("MM_ADSR/00_adsr01_release", 0.300, 0.01, 10.0, 0.001); adsr01_e = hslider("MM_ADSR/00_adsr01_enable", 1.0, 0.0, 1.0, 1.0); adsr02_a = hslider("MM_ADSR/01_adsr02_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr02_d = hslider("MM_ADSR/01_adsr02_decay", 0.200, 0.001, 10.0, 0.001); adsr02_s = hslider("MM_ADSR/01_adsr02_sustain", 0.700, 0.0, 1.0, 0.001); adsr02_r = hslider("MM_ADSR/01_adsr02_release", 0.300, 0.01, 10.0, 0.001); adsr02_e = hslider("MM_ADSR/01_adsr02_enable", 0.0, 0.0, 1.0, 1.0); adsr03_a = hslider("MM_ADSR/02_adsr03_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr03_d = hslider("MM_ADSR/02_adsr03_decay", 0.200, 0.001, 10.0, 0.001); adsr03_s = hslider("MM_ADSR/02_adsr03_sustain", 0.700, 0.0, 1.0, 0.001); adsr03_r = hslider("MM_ADSR/02_adsr03_release", 0.300, 0.01, 10.0, 0.001); adsr03_e = hslider("MM_ADSR/02_adsr03_enable", 0.0, 0.0, 1.0, 1.0); adsr04_a = hslider("MM_ADSR/03_adsr04_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr04_d = hslider("MM_ADSR/03_adsr04_decay", 0.200, 0.001, 10.0, 0.001); adsr04_s = hslider("MM_ADSR/03_adsr04_sustain", 0.700, 0.0, 1.0, 0.001); adsr04_r = hslider("MM_ADSR/03_adsr04_release", 0.300, 0.01, 10.0, 0.001); adsr04_e = hslider("MM_ADSR/03_adsr04_enable", 0.0, 0.0, 1.0, 1.0); adsr05_a = hslider("MM_ADSR/04_adsr05_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr05_d = hslider("MM_ADSR/04_adsr05_decay", 0.200, 0.001, 10.0, 0.001); adsr05_s = hslider("MM_ADSR/04_adsr05_sustain", 0.700, 0.0, 1.0, 0.001); adsr05_r = hslider("MM_ADSR/04_adsr05_release", 0.300, 0.01, 10.0, 0.001); adsr05_e = hslider("MM_ADSR/04_adsr05_enable", 0.0, 0.0, 1.0, 1.0); adsr06_a = hslider("MM_ADSR/05_adsr06_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr06_d = hslider("MM_ADSR/05_adsr06_decay", 0.200, 0.001, 10.0, 0.001); adsr06_s = hslider("MM_ADSR/05_adsr06_sustain", 0.700, 0.0, 1.0, 0.001); adsr06_r = hslider("MM_ADSR/05_adsr06_release", 0.300, 0.01, 10.0, 0.001); adsr06_e = hslider("MM_ADSR/05_adsr06_enable", 0.0, 0.0, 1.0, 1.0); adsr07_a = hslider("MM_ADSR/06_adsr07_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr07_d = hslider("MM_ADSR/06_adsr07_decay", 0.200, 0.001, 10.0, 0.001); adsr07_s = hslider("MM_ADSR/06_adsr07_sustain", 0.700, 0.0, 1.0, 0.001); adsr07_r = hslider("MM_ADSR/06_adsr07_release", 0.300, 0.01, 10.0, 0.001); adsr07_e = hslider("MM_ADSR/06_adsr07_enable", 0.0, 0.0, 1.0, 1.0); adsr08_a = hslider("MM_ADSR/07_adsr08_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr08_d = hslider("MM_ADSR/07_adsr08_decay", 0.200, 0.001, 10.0, 0.001); adsr08_s = hslider("MM_ADSR/07_adsr08_sustain", 0.700, 0.0, 1.0, 0.001); adsr08_r = hslider("MM_ADSR/07_adsr08_release", 0.300, 0.01, 10.0, 0.001); adsr08_e = hslider("MM_ADSR/07_adsr08_enable", 0.0, 0.0, 1.0, 1.0); adsr09_a = hslider("MM_ADSR/08_adsr09_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr09_d = hslider("MM_ADSR/08_adsr09_decay", 0.200, 0.001, 10.0, 0.001); adsr09_s = hslider("MM_ADSR/08_adsr09_sustain", 0.700, 0.0, 1.0, 0.001); adsr09_r = hslider("MM_ADSR/08_adsr09_release", 0.300, 0.01, 10.0, 0.001); adsr09_e = hslider("MM_ADSR/08_adsr09_enable", 0.0, 0.0, 1.0, 1.0); adsr10_a = hslider("MM_ADSR/09_adsr10_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr10_d = hslider("MM_ADSR/09_adsr10_decay", 0.200, 0.001, 10.0, 0.001); adsr10_s = hslider("MM_ADSR/09_adsr10_sustain", 0.700, 0.0, 1.0, 0.001); adsr10_r = hslider("MM_ADSR/09_adsr10_release", 0.300, 0.01, 10.0, 0.001); adsr10_e = hslider("MM_ADSR/09_adsr10_enable", 0.0, 0.0, 1.0, 1.0); adsr11_a = hslider("MM_ADSR/10_adsr11_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr11_d = hslider("MM_ADSR/10_adsr11_decay", 0.200, 0.001, 10.0, 0.001); adsr11_s = hslider("MM_ADSR/10_adsr11_sustain", 0.700, 0.0, 1.0, 0.001); adsr11_r = hslider("MM_ADSR/10_adsr11_release", 0.300, 0.01, 10.0, 0.001); adsr11_e = hslider("MM_ADSR/10_adsr11_enable", 0.0, 0.0, 1.0, 1.0); adsr12_a = hslider("MM_ADSR/11_adsr12_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr12_d = hslider("MM_ADSR/11_adsr12_decay", 0.200, 0.001, 10.0, 0.001); adsr12_s = hslider("MM_ADSR/11_adsr12_sustain", 0.700, 0.0, 1.0, 0.001); adsr12_r = hslider("MM_ADSR/11_adsr12_release", 0.300, 0.01, 10.0, 0.001); adsr12_e = hslider("MM_ADSR/11_adsr12_enable", 0.0, 0.0, 1.0, 1.0); adsr13_a = hslider("MM_ADSR/12_adsr13_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr13_d = hslider("MM_ADSR/12_adsr13_decay", 0.200, 0.001, 10.0, 0.001); adsr13_s = hslider("MM_ADSR/12_adsr13_sustain", 0.700, 0.0, 1.0, 0.001); adsr13_r = hslider("MM_ADSR/12_adsr13_release", 0.300, 0.01, 10.0, 0.001); adsr13_e = hslider("MM_ADSR/12_adsr13_enable", 0.0, 0.0, 1.0, 1.0); adsr14_a = hslider("MM_ADSR/13_adsr14_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr14_d = hslider("MM_ADSR/13_adsr14_decay", 0.200, 0.001, 10.0, 0.001); adsr14_s = hslider("MM_ADSR/13_adsr14_sustain", 0.700, 0.0, 1.0, 0.001); adsr14_r = hslider("MM_ADSR/13_adsr14_release", 0.300, 0.01, 10.0, 0.001); adsr14_e = hslider("MM_ADSR/13_adsr14_enable", 0.0, 0.0, 1.0, 1.0); adsr15_a = hslider("MM_ADSR/14_adsr15_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr15_d = hslider("MM_ADSR/14_adsr15_decay", 0.200, 0.001, 10.0, 0.001); adsr15_s = hslider("MM_ADSR/14_adsr15_sustain", 0.700, 0.0, 1.0, 0.001); adsr15_r = hslider("MM_ADSR/14_adsr15_release", 0.300, 0.01, 10.0, 0.001); adsr15_e = hslider("MM_ADSR/14_adsr15_enable", 0.0, 0.0, 1.0, 1.0); adsr16_a = hslider("MM_ADSR/15_adsr16_attack[scale:log]", 0.010, 0.001, 5.0, 0.001); adsr16_d = hslider("MM_ADSR/15_adsr16_decay", 0.200, 0.001, 10.0, 0.001); adsr16_s = hslider("MM_ADSR/15_adsr16_sustain", 0.700, 0.0, 1.0, 0.001); adsr16_r = hslider("MM_ADSR/15_adsr16_release", 0.300, 0.01, 10.0, 0.001); adsr16_e = hslider("MM_ADSR/15_adsr16_enable", 0.0, 0.0, 1.0, 1.0); // Single-slot ADSR expression. The enable multiplier zeros muted slots. adsr_slot(a, d, s, r, e, gate) = en.adsr(a, d, s, r, gate) : *(e); // 16-wide parallel bus of ADSR outputs. Takes the global gate as an argument // so engines can bind their own gate signal (noteOn/noteOff). adsrs(gate) = adsr_slot(adsr01_a, adsr01_d, adsr01_s, adsr01_r, adsr01_e, gate), adsr_slot(adsr02_a, adsr02_d, adsr02_s, adsr02_r, adsr02_e, gate), adsr_slot(adsr03_a, adsr03_d, adsr03_s, adsr03_r, adsr03_e, gate), adsr_slot(adsr04_a, adsr04_d, adsr04_s, adsr04_r, adsr04_e, gate), adsr_slot(adsr05_a, adsr05_d, adsr05_s, adsr05_r, adsr05_e, gate), adsr_slot(adsr06_a, adsr06_d, adsr06_s, adsr06_r, adsr06_e, gate), adsr_slot(adsr07_a, adsr07_d, adsr07_s, adsr07_r, adsr07_e, gate), adsr_slot(adsr08_a, adsr08_d, adsr08_s, adsr08_r, adsr08_e, gate), adsr_slot(adsr09_a, adsr09_d, adsr09_s, adsr09_r, adsr09_e, gate), adsr_slot(adsr10_a, adsr10_d, adsr10_s, adsr10_r, adsr10_e, gate), adsr_slot(adsr11_a, adsr11_d, adsr11_s, adsr11_r, adsr11_e, gate), adsr_slot(adsr12_a, adsr12_d, adsr12_s, adsr12_r, adsr12_e, gate), adsr_slot(adsr13_a, adsr13_d, adsr13_s, adsr13_r, adsr13_e, gate), adsr_slot(adsr14_a, adsr14_d, adsr14_s, adsr14_r, adsr14_e, gate), adsr_slot(adsr15_a, adsr15_d, adsr15_s, adsr15_r, adsr15_e, gate), adsr_slot(adsr16_a, adsr16_d, adsr16_s, adsr16_r, adsr16_e, gate); // --------------------------------------------------------------------------- // LFO slots (32) // --------------------------------------------------------------------------- lfo01_r = hslider("MM_LFO/00_lfo01_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo01_m = hslider("MM_LFO/00_lfo01_morph", 0.0, 0.0, 1.0, 0.001); lfo01_e = hslider("MM_LFO/00_lfo01_enable", 0.0, 0.0, 1.0, 1.0); lfo02_r = hslider("MM_LFO/01_lfo02_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo02_m = hslider("MM_LFO/01_lfo02_morph", 0.0, 0.0, 1.0, 0.001); lfo02_e = hslider("MM_LFO/01_lfo02_enable", 0.0, 0.0, 1.0, 1.0); lfo03_r = hslider("MM_LFO/02_lfo03_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo03_m = hslider("MM_LFO/02_lfo03_morph", 0.0, 0.0, 1.0, 0.001); lfo03_e = hslider("MM_LFO/02_lfo03_enable", 0.0, 0.0, 1.0, 1.0); lfo04_r = hslider("MM_LFO/03_lfo04_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo04_m = hslider("MM_LFO/03_lfo04_morph", 0.0, 0.0, 1.0, 0.001); lfo04_e = hslider("MM_LFO/03_lfo04_enable", 0.0, 0.0, 1.0, 1.0); lfo05_r = hslider("MM_LFO/04_lfo05_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo05_m = hslider("MM_LFO/04_lfo05_morph", 0.0, 0.0, 1.0, 0.001); lfo05_e = hslider("MM_LFO/04_lfo05_enable", 0.0, 0.0, 1.0, 1.0); lfo06_r = hslider("MM_LFO/05_lfo06_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo06_m = hslider("MM_LFO/05_lfo06_morph", 0.0, 0.0, 1.0, 0.001); lfo06_e = hslider("MM_LFO/05_lfo06_enable", 0.0, 0.0, 1.0, 1.0); lfo07_r = hslider("MM_LFO/06_lfo07_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo07_m = hslider("MM_LFO/06_lfo07_morph", 0.0, 0.0, 1.0, 0.001); lfo07_e = hslider("MM_LFO/06_lfo07_enable", 0.0, 0.0, 1.0, 1.0); lfo08_r = hslider("MM_LFO/07_lfo08_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo08_m = hslider("MM_LFO/07_lfo08_morph", 0.0, 0.0, 1.0, 0.001); lfo08_e = hslider("MM_LFO/07_lfo08_enable", 0.0, 0.0, 1.0, 1.0); lfo09_r = hslider("MM_LFO/08_lfo09_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo09_m = hslider("MM_LFO/08_lfo09_morph", 0.0, 0.0, 1.0, 0.001); lfo09_e = hslider("MM_LFO/08_lfo09_enable", 0.0, 0.0, 1.0, 1.0); lfo10_r = hslider("MM_LFO/09_lfo10_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo10_m = hslider("MM_LFO/09_lfo10_morph", 0.0, 0.0, 1.0, 0.001); lfo10_e = hslider("MM_LFO/09_lfo10_enable", 0.0, 0.0, 1.0, 1.0); lfo11_r = hslider("MM_LFO/10_lfo11_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo11_m = hslider("MM_LFO/10_lfo11_morph", 0.0, 0.0, 1.0, 0.001); lfo11_e = hslider("MM_LFO/10_lfo11_enable", 0.0, 0.0, 1.0, 1.0); lfo12_r = hslider("MM_LFO/11_lfo12_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo12_m = hslider("MM_LFO/11_lfo12_morph", 0.0, 0.0, 1.0, 0.001); lfo12_e = hslider("MM_LFO/11_lfo12_enable", 0.0, 0.0, 1.0, 1.0); lfo13_r = hslider("MM_LFO/12_lfo13_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo13_m = hslider("MM_LFO/12_lfo13_morph", 0.0, 0.0, 1.0, 0.001); lfo13_e = hslider("MM_LFO/12_lfo13_enable", 0.0, 0.0, 1.0, 1.0); lfo14_r = hslider("MM_LFO/13_lfo14_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo14_m = hslider("MM_LFO/13_lfo14_morph", 0.0, 0.0, 1.0, 0.001); lfo14_e = hslider("MM_LFO/13_lfo14_enable", 0.0, 0.0, 1.0, 1.0); lfo15_r = hslider("MM_LFO/14_lfo15_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo15_m = hslider("MM_LFO/14_lfo15_morph", 0.0, 0.0, 1.0, 0.001); lfo15_e = hslider("MM_LFO/14_lfo15_enable", 0.0, 0.0, 1.0, 1.0); lfo16_r = hslider("MM_LFO/15_lfo16_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo16_m = hslider("MM_LFO/15_lfo16_morph", 0.0, 0.0, 1.0, 0.001); lfo16_e = hslider("MM_LFO/15_lfo16_enable", 0.0, 0.0, 1.0, 1.0); lfo17_r = hslider("MM_LFO/16_lfo17_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo17_m = hslider("MM_LFO/16_lfo17_morph", 0.0, 0.0, 1.0, 0.001); lfo17_e = hslider("MM_LFO/16_lfo17_enable", 0.0, 0.0, 1.0, 1.0); lfo18_r = hslider("MM_LFO/17_lfo18_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo18_m = hslider("MM_LFO/17_lfo18_morph", 0.0, 0.0, 1.0, 0.001); lfo18_e = hslider("MM_LFO/17_lfo18_enable", 0.0, 0.0, 1.0, 1.0); lfo19_r = hslider("MM_LFO/18_lfo19_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo19_m = hslider("MM_LFO/18_lfo19_morph", 0.0, 0.0, 1.0, 0.001); lfo19_e = hslider("MM_LFO/18_lfo19_enable", 0.0, 0.0, 1.0, 1.0); lfo20_r = hslider("MM_LFO/19_lfo20_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo20_m = hslider("MM_LFO/19_lfo20_morph", 0.0, 0.0, 1.0, 0.001); lfo20_e = hslider("MM_LFO/19_lfo20_enable", 0.0, 0.0, 1.0, 1.0); lfo21_r = hslider("MM_LFO/20_lfo21_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo21_m = hslider("MM_LFO/20_lfo21_morph", 0.0, 0.0, 1.0, 0.001); lfo21_e = hslider("MM_LFO/20_lfo21_enable", 0.0, 0.0, 1.0, 1.0); lfo22_r = hslider("MM_LFO/21_lfo22_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo22_m = hslider("MM_LFO/21_lfo22_morph", 0.0, 0.0, 1.0, 0.001); lfo22_e = hslider("MM_LFO/21_lfo22_enable", 0.0, 0.0, 1.0, 1.0); lfo23_r = hslider("MM_LFO/22_lfo23_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo23_m = hslider("MM_LFO/22_lfo23_morph", 0.0, 0.0, 1.0, 0.001); lfo23_e = hslider("MM_LFO/22_lfo23_enable", 0.0, 0.0, 1.0, 1.0); lfo24_r = hslider("MM_LFO/23_lfo24_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo24_m = hslider("MM_LFO/23_lfo24_morph", 0.0, 0.0, 1.0, 0.001); lfo24_e = hslider("MM_LFO/23_lfo24_enable", 0.0, 0.0, 1.0, 1.0); lfo25_r = hslider("MM_LFO/24_lfo25_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo25_m = hslider("MM_LFO/24_lfo25_morph", 0.0, 0.0, 1.0, 0.001); lfo25_e = hslider("MM_LFO/24_lfo25_enable", 0.0, 0.0, 1.0, 1.0); lfo26_r = hslider("MM_LFO/25_lfo26_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo26_m = hslider("MM_LFO/25_lfo26_morph", 0.0, 0.0, 1.0, 0.001); lfo26_e = hslider("MM_LFO/25_lfo26_enable", 0.0, 0.0, 1.0, 1.0); lfo27_r = hslider("MM_LFO/26_lfo27_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo27_m = hslider("MM_LFO/26_lfo27_morph", 0.0, 0.0, 1.0, 0.001); lfo27_e = hslider("MM_LFO/26_lfo27_enable", 0.0, 0.0, 1.0, 1.0); lfo28_r = hslider("MM_LFO/27_lfo28_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo28_m = hslider("MM_LFO/27_lfo28_morph", 0.0, 0.0, 1.0, 0.001); lfo28_e = hslider("MM_LFO/27_lfo28_enable", 0.0, 0.0, 1.0, 1.0); lfo29_r = hslider("MM_LFO/28_lfo29_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo29_m = hslider("MM_LFO/28_lfo29_morph", 0.0, 0.0, 1.0, 0.001); lfo29_e = hslider("MM_LFO/28_lfo29_enable", 0.0, 0.0, 1.0, 1.0); lfo30_r = hslider("MM_LFO/29_lfo30_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo30_m = hslider("MM_LFO/29_lfo30_morph", 0.0, 0.0, 1.0, 0.001); lfo30_e = hslider("MM_LFO/29_lfo30_enable", 0.0, 0.0, 1.0, 1.0); lfo31_r = hslider("MM_LFO/30_lfo31_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo31_m = hslider("MM_LFO/30_lfo31_morph", 0.0, 0.0, 1.0, 0.001); lfo31_e = hslider("MM_LFO/30_lfo31_enable", 0.0, 0.0, 1.0, 1.0); lfo32_r = hslider("MM_LFO/31_lfo32_rate[scale:log]", 1.0, 0.01, 20.0, 0.001); lfo32_m = hslider("MM_LFO/31_lfo32_morph", 0.0, 0.0, 1.0, 0.001); lfo32_e = hslider("MM_LFO/31_lfo32_enable", 0.0, 0.0, 1.0, 1.0); // Wavemorph — 0..1 crossfades sine -> triangle -> square -> saw. // Uses nested ba.if. Each shape is already in [-1,+1]. wavemorph(rate, morph) = ba.if(morph < 0.333, (1.0 - morph*3.0) * os.osc(rate) + (morph*3.0) * os.lf_triangle(rate), ba.if(morph < 0.666, (1.0 - (morph-0.333)*3.0) * os.lf_triangle(rate) + ((morph-0.333)*3.0) * os.lf_squarewave(rate), (1.0 - (morph-0.666)*3.0) * os.lf_squarewave(rate) + ((morph-0.666)*3.0) * os.lf_saw(rate))); lfo_slot(rate, morph, en_flag) = wavemorph(rate, morph) : *(en_flag); lfos = lfo_slot(lfo01_r, lfo01_m, lfo01_e), lfo_slot(lfo02_r, lfo02_m, lfo02_e), lfo_slot(lfo03_r, lfo03_m, lfo03_e), lfo_slot(lfo04_r, lfo04_m, lfo04_e), lfo_slot(lfo05_r, lfo05_m, lfo05_e), lfo_slot(lfo06_r, lfo06_m, lfo06_e), lfo_slot(lfo07_r, lfo07_m, lfo07_e), lfo_slot(lfo08_r, lfo08_m, lfo08_e), lfo_slot(lfo09_r, lfo09_m, lfo09_e), lfo_slot(lfo10_r, lfo10_m, lfo10_e), lfo_slot(lfo11_r, lfo11_m, lfo11_e), lfo_slot(lfo12_r, lfo12_m, lfo12_e), lfo_slot(lfo13_r, lfo13_m, lfo13_e), lfo_slot(lfo14_r, lfo14_m, lfo14_e), lfo_slot(lfo15_r, lfo15_m, lfo15_e), lfo_slot(lfo16_r, lfo16_m, lfo16_e), lfo_slot(lfo17_r, lfo17_m, lfo17_e), lfo_slot(lfo18_r, lfo18_m, lfo18_e), lfo_slot(lfo19_r, lfo19_m, lfo19_e), lfo_slot(lfo20_r, lfo20_m, lfo20_e), lfo_slot(lfo21_r, lfo21_m, lfo21_e), lfo_slot(lfo22_r, lfo22_m, lfo22_e), lfo_slot(lfo23_r, lfo23_m, lfo23_e), lfo_slot(lfo24_r, lfo24_m, lfo24_e), lfo_slot(lfo25_r, lfo25_m, lfo25_e), lfo_slot(lfo26_r, lfo26_m, lfo26_e), lfo_slot(lfo27_r, lfo27_m, lfo27_e), lfo_slot(lfo28_r, lfo28_m, lfo28_e), lfo_slot(lfo29_r, lfo29_m, lfo29_e), lfo_slot(lfo30_r, lfo30_m, lfo30_e), lfo_slot(lfo31_r, lfo31_m, lfo31_e), lfo_slot(lfo32_r, lfo32_m, lfo32_e); // --------------------------------------------------------------------------- // sources(gate) — concatenated 48-wide mod-source bus. // Order: adsr01..adsr16, lfo01..lfo32 // --------------------------------------------------------------------------- sources(gate) = adsrs(gate), lfos; // --------------------------------------------------------------------------- // Individual named source functions — 48 total, in canonical order. // Engines can reference these directly in matrix sums, since each hslider // inside a matrix amount must have a unique compile-time label. // // Canonical source ordering (source index 0..47): // 0..15 : adsr01..adsr16 // 16..47 : lfo01..lfo32 // --------------------------------------------------------------------------- src00(gate) = adsr_slot(adsr01_a, adsr01_d, adsr01_s, adsr01_r, adsr01_e, gate); src01(gate) = adsr_slot(adsr02_a, adsr02_d, adsr02_s, adsr02_r, adsr02_e, gate); src02(gate) = adsr_slot(adsr03_a, adsr03_d, adsr03_s, adsr03_r, adsr03_e, gate); src03(gate) = adsr_slot(adsr04_a, adsr04_d, adsr04_s, adsr04_r, adsr04_e, gate); src04(gate) = adsr_slot(adsr05_a, adsr05_d, adsr05_s, adsr05_r, adsr05_e, gate); src05(gate) = adsr_slot(adsr06_a, adsr06_d, adsr06_s, adsr06_r, adsr06_e, gate); src06(gate) = adsr_slot(adsr07_a, adsr07_d, adsr07_s, adsr07_r, adsr07_e, gate); src07(gate) = adsr_slot(adsr08_a, adsr08_d, adsr08_s, adsr08_r, adsr08_e, gate); src08(gate) = adsr_slot(adsr09_a, adsr09_d, adsr09_s, adsr09_r, adsr09_e, gate); src09(gate) = adsr_slot(adsr10_a, adsr10_d, adsr10_s, adsr10_r, adsr10_e, gate); src10(gate) = adsr_slot(adsr11_a, adsr11_d, adsr11_s, adsr11_r, adsr11_e, gate); src11(gate) = adsr_slot(adsr12_a, adsr12_d, adsr12_s, adsr12_r, adsr12_e, gate); src12(gate) = adsr_slot(adsr13_a, adsr13_d, adsr13_s, adsr13_r, adsr13_e, gate); src13(gate) = adsr_slot(adsr14_a, adsr14_d, adsr14_s, adsr14_r, adsr14_e, gate); src14(gate) = adsr_slot(adsr15_a, adsr15_d, adsr15_s, adsr15_r, adsr15_e, gate); src15(gate) = adsr_slot(adsr16_a, adsr16_d, adsr16_s, adsr16_r, adsr16_e, gate); src16(gate) = lfo_slot(lfo01_r, lfo01_m, lfo01_e); src17(gate) = lfo_slot(lfo02_r, lfo02_m, lfo02_e); src18(gate) = lfo_slot(lfo03_r, lfo03_m, lfo03_e); src19(gate) = lfo_slot(lfo04_r, lfo04_m, lfo04_e); src20(gate) = lfo_slot(lfo05_r, lfo05_m, lfo05_e); src21(gate) = lfo_slot(lfo06_r, lfo06_m, lfo06_e); src22(gate) = lfo_slot(lfo07_r, lfo07_m, lfo07_e); src23(gate) = lfo_slot(lfo08_r, lfo08_m, lfo08_e); src24(gate) = lfo_slot(lfo09_r, lfo09_m, lfo09_e); src25(gate) = lfo_slot(lfo10_r, lfo10_m, lfo10_e); src26(gate) = lfo_slot(lfo11_r, lfo11_m, lfo11_e); src27(gate) = lfo_slot(lfo12_r, lfo12_m, lfo12_e); src28(gate) = lfo_slot(lfo13_r, lfo13_m, lfo13_e); src29(gate) = lfo_slot(lfo14_r, lfo14_m, lfo14_e); src30(gate) = lfo_slot(lfo15_r, lfo15_m, lfo15_e); src31(gate) = lfo_slot(lfo16_r, lfo16_m, lfo16_e); src32(gate) = lfo_slot(lfo17_r, lfo17_m, lfo17_e); src33(gate) = lfo_slot(lfo18_r, lfo18_m, lfo18_e); src34(gate) = lfo_slot(lfo19_r, lfo19_m, lfo19_e); src35(gate) = lfo_slot(lfo20_r, lfo20_m, lfo20_e); src36(gate) = lfo_slot(lfo21_r, lfo21_m, lfo21_e); src37(gate) = lfo_slot(lfo22_r, lfo22_m, lfo22_e); src38(gate) = lfo_slot(lfo23_r, lfo23_m, lfo23_e); src39(gate) = lfo_slot(lfo24_r, lfo24_m, lfo24_e); src40(gate) = lfo_slot(lfo25_r, lfo25_m, lfo25_e); src41(gate) = lfo_slot(lfo26_r, lfo26_m, lfo26_e); src42(gate) = lfo_slot(lfo27_r, lfo27_m, lfo27_e); src43(gate) = lfo_slot(lfo28_r, lfo28_m, lfo28_e); src44(gate) = lfo_slot(lfo29_r, lfo29_m, lfo29_e); src45(gate) = lfo_slot(lfo30_r, lfo30_m, lfo30_e); src46(gate) = lfo_slot(lfo31_r, lfo31_m, lfo31_e); src47(gate) = lfo_slot(lfo32_r, lfo32_m, lfo32_e);