Snake Jazz - also is there an fx stack?

My first creation. :trophy:

As in title: is there an FX stack so I don’t have to have this nested structure?

live_loop :snake_jazz do
  with_fx :compressor do
    with_fx :flanger, mix: rrand(0, 0.2) do
      with_fx :reverb, amp: rrand(0, 0.6) do
        with_fx :tanh, krunch: 2, mix: rrand(0, 0.2) do
          with_fx :hpf, cutoff: 130 - rrand(0, 20), mix: rrand(0.9, 1) do
            sample :drum_cymbal_open
            sleep 0.75
            sample :drum_cymbal_pedal
            sleep 0.5
            sample :drum_cymbal_pedal, sustain: 0.1
            sleep 0.25
          end
        end
      end
    end
  end
end

I picture something like this. Apologies for the syntax errors, I’m a bit rusty with Ruby. I’m not even sure if this is Ruby. :slight_smile:

chain = [
  { fx: :compressor },
  { fx: :flanger, mix: rrand(0, 0.2) },
  { fx: :reverb, amp: rrand(0, 0.6) },
  { fx: :tanh, krunch: 2, mix: rrand(0, 0.2) },
  { fx: :hpf, cutoff: 130 - rrand(0, 20), mix: rrand(0.9, 1) }
]

with_fx :chain, chain: chain do
    play :c
end

The fx variable could be reversed, not sure which is more intuitive.

Above code is in a gist here https://gist.github.com/datashaman/e4cc432516dbe6c923c3390af2d6a52a

Short answer: Not possible or easy.

Long answer: I tried a recursive call passing a diminishing array of fx definitions, but then ran into an issue with random number generators creating the same results on every run (even when using lambda calls). it gets messy quickly, messier than nested definitions.

I’v used this sort of block function for randomizing the effects. Works with randomized parameters as well when using lambda:

def with_effects(x,&block)
  x = x.dup
  if x.length>0 then
    n = x.shift
    if n[:with_fx] then
      with_fx n[:with_fx], n do
        with_effects(x,&block)
      end
    end
  else
    yield
  end
end

live_loop :random_effects do
  
  chain = lambda do
    [               #<- Remove ":" to see parameter autosuggestion for fx
      {with_fx: :echo, phase: rrand(0,0.5) },
      {with_fx: :whammy, grainsize: rrand(0,2.0)},
      {with_fx: :flanger, feedback: rrand(0,0.5)},
      {with_fx: :tremolo, phase: rrand(0,0.5)},
      {with_fx: :bitcrusher, bits: rand_i(3..5)}
    ].pick(3) # Use all or pick some randomly
  end
  
  with_effects chain.call do # lambda call here randomizes the params and effects
    play (scale :C, :ahirbhairav).pick
  end
  
  sleep 1
end