Control MasterFX with code – MIDI works great

Hi!
I want to control the values of my master FX using code. I managed to do it using a MIDI mapping and that works fine. As coder I’m firm with code and threads, still, I could not manage to solve my problem using this forum. Here is what I’ve got:

with_fx :lpf, cutoff: 127 do |lpf|
  set :lpf, lpf
    live_loop :foo do

The LowPass Filter wraps around everything. Now on the top level I’ve got this MIDI mapping and it works like a breeze, using control and get I can simply update the LowPass cutoff value:

live_loop :midi_debug do
  use_real_time
  data = sync "/midi:grid:1/control_change"
  control get(:lpf), cutoff: 127 - data[1] if data[0] == 37

BUT when I remove the MIDI mapping and try to control the cutoff value e.g. in a live_loop or in_thread it only works the first time, after changing the value once the reference returned by get seems to be messed up:

live_loop :ctrl1 do
  control get(:hpf), cutoff: 0
  sleep 0.0125
end

Changing the cutoff in the code above works once, e.g. I can set it to 80 and it is applied once, but setting it back to 0 again does not work. When I try to debug using puts get(:hpf) I can see that the reference changed. Not sure why. Thought that set and get where thread safe.

Taking that one step further I want of course to e.g. have a smooth line automation or and LFO mapped to the value (instead of hard coding it).

Any ideas on how to solve that are welcome!

Thanks, BR toovy

This will work

use_debug false
use_synth :tb303
with_fx :lpf, cutoff: 100 do |fx1|
  with_fx :hpf,cutoff: 30 do |fx2|
    set :fx1,fx1;set:fx2,fx2 #only allow this to execute ONCE: use comment
    notes=scale(:e2, :major,num_octaves: 2).mirror
    live_loop :play_notes do
      notes.length.times do |i|
        play notes[i],release: 0.2
        sleep 0.2
      end
    end
  end
end
control get(:fx1),cutoff: 100
control get(:fx2),cutoff: 30

What you have to to do is to make sure that the references to the fx calls are stored only on the FIRST run. YOu then comment out the line indicated and you can rerun having altered the valuies in the last two lines to adjust the filters.
You need to reeanble the line that stores the pointers each time you press STOP and then want to run again.

Essentially a new fxs wrapper is generated each time you press run. If you store (and use) the first value it uses the innermost wrappwer which will affect ths sound,. The additional ones are geeranted but not used. It is kludgy but it works.

Thansk a lot! That did the trick, played around using a variable fx_alive to maintain the state. That removes the issue that you have to remember to comment it out, and if you ever need to re-initialize one can comment in # set :fx_alive, nil. In my tests it worked flawlessly.

# set :fx_alive, nil

with_fx :reverb, room: 1, mix: 0 do |reverb|
  with_fx :bitcrusher, sample_rate: 3000, bits: 8, mix: 0 do |bitcrusher|
    with_fx :hpf, cutoff: 0 do |hpf|
      with_fx :lpf, cutoff: 127 do |lpf|
        with_fx :ixi_techno, mix: 0 do |ixi_techno|
          if get(:fx_alive) == nil
            set :fx_alive, true
            set :reverb, reverb
            set :bitcrusher, bitcrusher
            set :hpf, hpf
            set :lpf, lpf
            set :ixi_techno, ixi_techno
          end