Sonic Pi Midi Question

I am brand new to sonic pi and I’m requesting some assistance with some code pertaining to midi. I have an external sequencer connected to sonic pi via usb midi. When I press start/stop on my sequencer I see the corresponding messages and know they are connected via midi. I also hear my sequencer audio through my computer so I am good there too. When I run my code in sonic pi it waits for the incoming midi signal and pressing play on my sequencer starts the amen break code (which is the behavior I’m looking for), however pressing stop on my sequencer does not stop playback on sonic pi. Any and all help appreciated! Below is my code:

live_loop :midi_control do
  use_real_time
  
  start_msg = sync "/midi:m8_m8_midi_1_24_0/start"
  if start_msg
    puts "MIDI START RECEIVED"
    run_sequence
  end
  
  stop_msg = sync "/midi:m8_m8_midi_1_24_0/stop"
  if stop_msg
    puts "MIDI STOP RECEIVED"
    stop
  end
end

live_loop :midi_notes do
  use_real_time
  
  
  note, velocity = sync "/midi:m8_m8_midi_1_24_0:1/note_on"
  if note == 36
    puts "Note_on RECEIVED"
    set :sequence_running, true
    run_sequence
  end
  
  note, velocity = sync "/midi:m8_m8_midi_1_24_0:1/note_off"
  if note == 36
    puts "Note_off RECEIVED"
    set :sequence_running, false
  end
end

define :run_sequence do
  in_thread(amen: :my_sequence_thread) do
    while get(:sequence_running) do
      # Jungle
      
      # Coded by Sam Aaron
      use_bpm 50
      
      with_fx :lpf, cutoff: 90 do
      with_fx :reverb, mix: 0.5 do
      with_fx :compressor, pre_amp: 40 do
      with_fx :distortion, distort: 0.4 do
      live_loop :jungle do
      use_random_seed 667
      4.times do
      sample :loop_amen, beat_stretch: 1, rate: [1, 1, 1, -1].choose / 2.0, finish: 0.5, amp: 0.5
      sample :loop_amen, beat_stretch: 1
      sleep 1
    end
  end
end
end
end
end

end
end
end

define :stop_sequence do
  set :sequence_running, false
end

If I’m reading this code right, you’re not calling stop_sequence but just stop the :midi_control loop.

Also, if you format the code as preformatted text it makes it easier to read.

I don’t think it’s possible to stop playback of a sample once it’s started. You can specify start and stop before you launch it but once it’s playing it will run till the end.

That being said it might be possible to mute it when you receive the stop message by setting the amp value of the running sample, I’m not on my pc right now but I think I can make this work.

I have since written new code that responds better, much cleaner too (i’ll post it later when im at my computer) for this use-case with the break as the sample i changed the loop playback to 1 so it would stop quicker.

however id really like to see your mute suggestion as that would come in handy in a variety of use-cases.

currently im having trouble successfully sending a midi note from sonic pi to my sequencer. i need to send a C1 on midi channel 10 from sonic pi to my sequencer to control the sequencer’s start/stop function however no variation of code i’ve written sends the note.

Since initially making my post I’ve made revisions that have accomplished most of what I’m aiming to accomplish, however I’m requesting further assistance with a new problem.

current process: run sonic pi code, code waits for the note_on from my tracker (connected via usb midi), note_on is triggered and the code executes the amen break in sync with my tracker. When a note_off triggers from my tracker the sample ends.

Okay cool that’s exactly what I want to accomplish, however the code cannot be edited live since it isn’t contained within a live_loop. How can I amend this code to accomplish live editing while maintaining note_on/note_off midi start/stop control?


set :sequence_running, false

live_loop :midi_notes do
  use_real_time
  
  note, velocity = sync "/midi:m8_m8_midi_1_24_0:1/note_on"
  if note == 36
    puts "NOTE ON"
    set :sequence_running, true
    run_sequence
  end
  
  note, velocity = sync "/midi:m8_m8_midi_1_24_0:1/note_off"
  if note == 36
    puts "NOTE OFF"
    set :sequence_running, false
  end
end

define :run_sequence do
  in_thread(JUNGLE_TEST: :sequence_thread) do
    while get(:sequence_running)
      #JUNGLE
      use_bpm 30
      with_fx :lpf, cutoff: 90 do
      with_fx :reverb, mix: 0.5 do
      with_fx :compressor, pre_amp: 40 do
      with_fx :distortion, distort: 0.6 do
      use_random_seed 647
      1.times do
      sample :loop_amen, beat_stretch: 1, rate:[1,1,1,-1].choose / 2.0, finish: 0.5, amp: 0.5
      sample :loop_amen, beat_stretch: 1
      sleep 1
    end
  end
end
end
end
end
end
end

This code allows me to start samples with the drum pads on my midi controller and when I hit the stop button on my controller everything is muted immediately.

use_real_time
set :running_samples, []

define :mute_all_running_samples do
  rs = get[:running_samples]
  for s in rs do
    control s, amp: 0
  end
end

define :play_sample do |s_in|
  s = sample s_in
  rs = get[:running_samples]
  rs = rs + [s]
  set :running_samples, rs
end

live_loop :mute_listener do
  note, value = sync "/midi:launchkey_61_launchkey_61_launchkey_midi_28_0:1/control_change"
  if note == 114 and value == 0
    mute_all_running_samples
  end
end

live_loop :start_sample_listener do
  note, value = sync "/midi:launchkey_61_launchkey_61_launchkey_midi_28_0:10/note_on"
  if note == 36
    play_sample :ambi_lunar_land
  end
  if note == 40
    play_sample :loop_amen_full
  end
  if note == 41
    play_sample :loop_3d_printer
  end
end
1 Like

thank you for the support, this code is brilliant. will definitely try implementing it with my tracker - updates to come. have you made any recordings using this code?

No recordings where I use this, just some fooling around. My kids love it when they can trigger samples from the drum pads on my midi keyboard, could use a sampler but I do most of my stuff in Sonic Pi.

1 Like