Arduino interface to sonic pi

thank you for the info.
I have a Uno setup with touch sensitive keypad so I just want to be able to use those to trigger the sonic pi.
I have this working with Yoshimi and have assigned each touch-pad to a keyboard note on the synth which works well.

in my arduino i have code:
midi.sendNoteOn(note1, velocity);
where note1 will change depending on the sensor - ranging from any note on a keyboard ie middle c :60

How is your arduino connected physically to your Pi? is it via usb or via the gpio pins? How are you connecting the midi input from it to Yoshimi?

I usually run qjackctl and use this to to the various audio and midi connections with respect to Sonic Pi on my RPi.
It may be that it appears in the list of midi connections in the Sonic Pi IO preference window. If not it may appear in the alsa windo in the qjackctl connections tab, in which case it can be connected to midi-through-port-0 which Sonic Pi can see.

its via usb ,
i send the midi command using arduino USBMIDI_Interface midi;
midi.sendNoteOn(note1, velocity);
on the pi I run qjackctl and connect arduino to yoshimi there.
i dont see sonic pi in qjackctl

i see supercollider in qjackctl in audiom but not alsa or midi tabs in qjackctl

Im seeing midi in the cue - awesome!
:smiley:

1 Like

So its working alright?

yes it is thank you :+1:

Hi what is the sonic pi code to use to change buffer when receiving a midi program change command?
How do I stop the current buffer and ensure the next buffer is running on change?

i think we can’t handle the stop and run buttons with code.

Please can someone assist

maybe others consider that my answer is clear and there is no way to get what you try to reach ?

I think you can have all the buffers you want running by waiting for a midi signal to start playing. You could use midi control change signals to set flags to control operations. Something like this.

set :flag,false
set :flag2,false
live_loop :metro do
  sleep 1
end

live_loop :test1,sync: :metro do
  if get(:flag) #only plays of :flag is true
    play scale(:c4,:major).choose,release: 0.1
  end
  sleep 0.1
end

live_loop :test2 do
  sync :metro
  if get(:flag2) #only plays if flag2 is true
    sample :loop_amen,beat_stretch: 2
    sleep 1.9 #make sleep less than 2 so sync :metro keeps it in time
  end
end

 #next loop detects midi controllers 24 and 25 
#and uses them to toggle value of flag and flag2 between false and true
live_loop :midicontrol do
  use_real_time
  r,v = sync "/midi*/control_change"
  if r==24 and v==127
    f=get(:flag)
    set :flag, !(get(:flag))
  end
  if r==25 and v==127
    f=get(:flag2)
    set :flag2, !(get(:flag2))
  end
end

You can have the live loops in different buffers if you wish. Just make the buffers are running before you use the midicontrol.

Thanks, that kinda helps, but that only toggles between test1 and test2 in same buffer. You have buffer 0 to 9 or the way i understand it as 10 programs, how then can on control_chnage event can I call up buffer 1 if Im in buffer 0 and run buffer 1 and stop buffer 0?

You can move the live_loops to any buffer you want. They don’t have to be in the same one. Provided you just communicate between them by set/get then it doesn’t matter. so you could have the midicontrol live_loop (and the initial set :flag and set :flag2) in buffer 0, and put the other live loops in any other combination of buffers you want. All you have to do is to make sure that the buffers are all running.

thanks Robin, an issue Im having now is how do I stop a sample wav song from playing when sending the control_change as I need to start a new wav song playing on this event change?

Here’s one way to kill a sample using this function

define :killablesample do |s,flagname|
  set flagname,false
  in_thread do
    k=sample s
    t =sample_duration s
    (t/0.1).to_i.times do
      if get(flagname)
        kill k
        stop
      end
      sleep 0.1 #loop polled every 0.1 beats
    end
  end
end


killablesample :loop_compus,:f1 #start sample with name of kill flag
sleep 1.2 #wait some time
set :f1,true #set kill flag to true. This could be done by midi signal
1 Like

Thank you, this will help.
How do I pass the parameter of the wav file if Im using
t = sample “/home/pi/music/song.wav” in place of the :loop_compus

Does the buffer stop or get disabled after the kill or stop command is run? I need the buffer to always remain active so it awaits the next midi control

adapt this :


samples_path = "/home/nlb/audio/samples/Reverb Hammond Auto-Vari 64 Ableto Project_Audio Files/"
sample_01 = load_sample samples_path, "Loop1"
sample_02 = load_sample samples_path, "Loop2"



define :killablesample do |s,flagname|
  set flagname,false
  in_thread do
    k=sample s
    t =sample_duration s
    (t/0.1).to_i.times do
      if get(flagname)
        kill k
        stop
      end
      sleep 0.1 #loop polled every 0.1 beats
    end
  end
end




killablesample sample_01,:kill1 #start sample with name of kill flag
killablesample sample_02,:kill2 #start sample with name of kill flag
sleep 1 #wait some time
set :kill1,true #set kill flag to true.
sleep 2 #wait some time
set :kill2,true #set kill flag to true.

getting a undefined local variable sample_01 at line ```
killablesample sample_01,:kill1 #start sample with name of kill flag