Change parameters of a synth with MIDI CC from controller

I’ve managed to get a MIDI controller sending CC messages to control fx in realtime. Here’s an example where CC0 is used to change the reverb mix on the whole track:

# Example to send to forum

# Midi CC in
cc_in = "/midi:arduino_leonardo_*:1/control_change"

with_fx :reverb, room: 0.5, mix: 0 do |fx|
  
  live_loop :midiccin do
    use_real_time
    n,v=sync cc_in
    if n==0
      control fx, mix: v/127.00
    end
  end
  
  # Simple beat
  live_loop :beat do
    tick
    sample :bd_ada, amp: 1 if bools(1,0,0,0, 1,1,0,0).look
    sample :sn_dolf, amp: 1 if bools(0,0,1,0, 0,0,0,1).look
    sleep 0.25
  end
  
  # bassline
  live_loop :bass do
    s = synth :bass_foundation, note: 40, sustain: 2, release: 0, cutoff:80
    sleep 1
    control s, note: 28
    sleep 0.2
    control s, note: 31
    sleep 0.8
  end
  
end

However, I just can’t find any way around reading CC input in realtime to control, say, the parameters of the bass synth above. How can I get use the same CC value to change the cutoff of the synth above while it is playing?

I’ve been trying to achieve this for days and would really appreciate some help :sweat_smile:

This seem’s to work OK.
I’ve modified it so I could use my keyboard “knobs” to provide the cc input,
I used 20 and 72 instead of your 0 cc
You can control them togehter on the same midi_cc (eg your 0) which gives an interesting result.

# Example to send to forum

#Midi CC in
#cc_in = "/midi:arduino_leonardo_*:1/control_change"
cc_in = "/midi*/control_change" #so that it would respond to my keyboard


with_fx :reverb, room: 0.5, mix: 0 do |fx|
  
  live_loop :midiccin do
    use_real_time
    n,v=sync cc_in
    if n== 72 #I used 72, but could be 0 for your midi input
      control fx, mix: v/127.00
    end
  end
  
  #Simple beat
  live_loop :beat do
    tick
    sample :bd_ada, amp: 1 if bools(1,0,0,0, 1,1,0,0).look
    sample :sn_dolf, amp: 1 if bools(0,0,1,0, 0,0,0,1).look
    sleep 0.25
  end
  set :startCO,80 #used from when program runs until cc changes it
  
  live_loop :contCutoff do
    use_real_time
    n,v = sync "/midi*/control_change"
    if n==20 #I used cc 20 from my keyboard controller
      co=10+100*v/127.0
      set :startCO,co
      control get(:s),cutoff: co
    end
  end
  
  
  
  #bassline
  live_loop :bass do
    s = synth :bass_foundation, note: 40, sustain: 2, release: 0, cutoff: get(:startCO)
    set :s,s
    sleep 1
    control s, note: 28
    sleep 0.2
    control s, note: 31
    sleep 0.8
  end
  
end
2 Likes

Robin, I’ve literally been watching your videos and reading your articles about MIDI input for the past few hours! I really appreciate your help - I can’t believe this is working for me now :star2:

These are the crucial things I was missing:

  • set :s,s in the loop with the synth itself
  • control get(:s),cutoff: co in the MIDI/CC listening loop, to send parameter info to the synth
  • Keeping a separate record of the starting value is great too

Is this method the best way to proceed? I’ve got a controller full of potentiometers just itching to be mapped :hugs:

No Problem. Glad to help. I use this sort of technique quite a lot, although mainly with OSC cues rather than midi. But it is essentially the same. The tricky bit here was that you already were using a control to alter the note value (which works well in your example), so it took a bit of thought to add the cutoff change.

1 Like

Ah I see! Would any of the steps be redundant if I wasn’t already using a control to change the note? Take this stripped-down version:

#Midi CC in
#cc_in = "/midi:arduino_leonardo_*:1/control_change"
cc_in = "/midi*/control_change" #so that it would respond to my keyboard

set :startCO,80 #used from when program runs until cc changes it

live_loop :contCutoff do
  use_real_time
  n,v = sync cc_in
  if n==20 #I used cc 20 from my keyboard controller
    co=10+100*v/127.0
    set :startCO,co
    control get(:s),cutoff: co
  end
end

#bassline
live_loop :bass do
  s = synth :bass_foundation, note: 40, sustain: 2, release: 0, cutoff: get(:startCO)
  set :s,s
  sleep 2
end

Are there are any parts of the syntax that are no longer needed, or a cleaner way to do this? I’m just trying to make sure I understand what each bit does before I let loose and start making a big template for my controller!

No I think its all necessary here. (apart from scaling the val which may not be necesary depending on the range you want). If you don’t want to retain the previous cutoff value for each new note (when the loop restarts), then you could just start each note at cutoff: 80, and you wouldn’t need to use :startCO

The important mechanism is saving s each time a new note starts (using set :s,s) and then accessing the value using get(;s) in the separate live loop which responds to changes in your midi_cc, and then using that to control the cutoff. That’s what allows the two to link together.

2 Likes

This is amazing Robin - and exactly what I’ve been trying to figure out all day!