In Dittytoy, each loop runs in a separate thread/worker. All filters chained to the loop run, by default, in the same thread.
Sometimes, however, you want to run a filter in a separate thread. The most likely situation is that you want to process the output of multiple loops through the same filter. You can enforce this by creating a filter with the createShared() method (instead of create()).
You can connect a (shared) filter to other (shared) filters using the connect method.
dittytoy.net/syntax#filters
#dittytoy #tutorial
Log in to post a comment.
// #12 Shared Filters. DittyToy 2022. // The MIT License. // // https://dittytoy.net/ditty/ccd086456e // // In Dittytoy, each loop runs in a separate thread/worker. All filters chained to the loop run, by default, // in the same thread. // // Sometimes, however, you want to run a filter in a separate thread. This can be for performance reasons // (although each additional thread also gives additional overhead). However, the most likely situation is // that you want to process the output of multiple loops through the same filter. You can enforce this by // creating a filter with the createShared() method (instead of create()). // // You can connect a (shared) filter to other (shared) filters using the connect method. // // Note 1! After you connect a loop to a shared filter, you cannot connect it to subsequent filters. // Note 2! Using shared filters will increase latency a bit. // // https://dittytoy.net/syntax#filters // // Compressor by athibaul - https://dittytoy.net/ditty/9d16ed4102 const compressor = filter.def(class { constructor(options) { this.gain = 1; } process(input, options) { let sigdb = 10 * Math.log10(input[0]**2 + input[1]**2); let overdb = sigdb - options.threshold; if(overdb < 0) { overdb = 0; } let target_gaindb = overdb * (1 - options.ratio)/options.ratio; let target_gain = 10 ** (target_gaindb / 20); let time = this.gain > target_gain ? options.attack : options.release; let a0 = clamp01(2.3 * ditty.dt / time); // 'time' to go to within 10% of the final value this.gain = lerp(this.gain, target_gain, a0); let gr = 20 * Math.log10(this.gain); return [input[0] * this.gain, input[1] * this.gain]; } }, {threshold:-18, ratio:2, attack:0.005, release:0.2}); // create a shared filter let sharedCompressor = compressor.createShared(); // synth and loops const kick = synth.def( (phase, env, tick, options) => Math.sin(phase * 2 * Math.PI * (1.5 - tick * 4)) * env.value, { amp: 4 } ); const tri = synth.def( (phase, env, tick, options) => { const v = (phase % 1) * 4; return (v < 2 ? v - 1 : 3 - v) * env.value }, { attack: 0.0125, release: 0.25 }); ditty.bpm = 140; loop( (loopCount) => { kick.play(c3, { attack: 0.025, release: 0.05 }); }, { sync: 1, name: 'kick' }) .connect( sharedCompressor ); // connect loop to shared filter loop( (loopCount) => { scale(c3, scales.minor_pentatonic, 1).forEach( note => { tri.play(note, { pan: Math.random() * 2 - 1 }); sleep(0.25); }); }, { name: 'melody' }) .connect( sharedCompressor ); // connect another loop to the same shared filter