Help looking for Sonic Pi coder to help create some tunes

Ok great I’ll take a look.

Hi Ethan
quite amazing what you can do - but no Im not looking to record the incoming midi - Im not sure why my question is seemingly being misunderstood :upside_down_face: let me try again:
I want to play live loops of sampled sounds that i have in a folder - Ive downloaded these snippets. while these are being played I want to play midi sounds from my midi device over these sounds . but these notes Im playing I want to as far as possible have them synced with the sample loop sounds in the background.

When you play along with your loops …
Do the notes ( you play ) sound out of time ?

Sorry you’re not getting the answers you’re after yet! Thanks for your patience.

Just to make sure we’re on the same page, I’ll clarify a bit about what I was getting at before too. If each note in a sequence you play will be synced individually with the start of the next sample loop, and will play before the next note is then also synced, etc… then there’s no need to ‘store up’ the notes - you can just play each note one at a time after syncing on the looping sample.

If on the other hand you want a sequence as a single unit to be synced with the start of the next sample loop (or other cue event), then as I understand it, it requires some way of recording the incoming MIDI events into some sort of “buffer”. That is where Robin’s demo, and the use of set and get, are helpful.

Is one of those sounding like what you want to do?

I think the 1st option is where I’m aiming for - each note in a sequence - no need to ‘store up’ the notes- just not sure on how to play and overlay the midi notes over each sample loop and looking for some examples on how to achieve this -

1 Like

Sure. It’s getting late here, so I’ll pick this up again maybe tomorrow - but others are welcome to chime in in the mean time of course :grinning_face_with_smiling_eyes:

Thought I’d take a look at this.
For specimen samples I choose three of the loop samples, all of which last approx 8 beats. I arranged to play then using beat_stretch to set the duration to exactly 8 beats.

I set midi defaults to use my oxygen keyboard as input on channel 1.
I then used a live loop :midi_in to wait for incoming midi note_on events, with a velocity (how hard the note is hit) of > 0 (my keyboard uses note_on with velocity 0 to signify note_off)
I then played the note, and checked if a sample was already playing, using a time state variable :flag, initially set to false (no sample playing).
I used a function :check_sample which took two parameters, a sample name and a number for the beat stretch, and used this to start the chosen sample playing with beat-stretch: 8. The flag was set to true to prevent another sample from starting before the first one had finished and a subsequent midi note_on was received to trigger the next sample.
Using this code, the first sample starts when you start playing. Then the second and subsequent samples will sync to the next available note_on event after the previous sample finishes playing.
Of course you can adapt the samples to whatever you want to use.

#demo sample/midi synchronisation by Robin Newman
#change the midi port to suit your system
use_midi_defaults port: "usb_oxygen_8_v2",channel: 1
use_synth :tri
set :flag, false
define :check_sample do |ns,bs|
  in_thread do
    sample ns,beat_stretch: bs,amp: 0.7
    set :flag,true
    sleep bs
    set :flag,false
  end
end

live_loop :midi_in do
  use_real_time
  n,v = sync "/midi*/note_on"
  if v > 0
    play n,amp: v/127.0,release: 0.2
    if get(:flag)==false
     #tick chooses sample in sequence from a ring, 8 is the beat_stretch number
      check_sample (ring :loop_garzul,:loop_mika,:loop_safari).tick,8
    end
  end
end
1 Like

Hi Robin - amazing yes thats more inline to what Ive been looking for.
Im going to try it out - many thanks! :+1: :slightly_smiling_face:

this is great - you guys are mind blowing, its just so amazing what can be done with sonic pi! Would it possible to please modify this to play something more in line with the soundcloud sample I posted. And instead of it stopping when no note is played can you make it stop say 10 seconds after no note is played so it doesnt end so abruptly?

the code keeps throwing a runtime error thread got too far behind time. I added in a with_fx :reverb :echo in the :midi_in loop. how do I fix this

Remember that showing your code, so we can see how/where you added the fx, would be super helpful :slightly_smiling_face: (it also gives us an easy way to take it and test it out in our own devices if necessary)

ive tried to combine the code from you and above [hitsware] as I want get the midi notes playing with the loops - not getting this right, see below.

#7
set_volume! 1
##| Link to the samples folder:
samples_dir = '/home/p/synth/music'


n,v = sync "/midi:arduino_leonardo_midi_1:1:1/note_on"
use_synth :tri
set :flag, false
define :check_sample do |ns,bs|
  in_thread do
    sample ns,beat_stretch: bs,amp: 0.7
    set :flag,true
    sleep bs
    set :flag,false
  end
end

live_loop :midi_in do
  use_real_time
  #n,v = sync "/midi*/note_on"
  n,v = sync "/midi:arduino_leonardo_midi_1:1:1/note_on"
  if v > 0
    play n,amp: v/127.0,release: 0.2
    if get(:flag)==false
      #tick chooses sample in sequence from a ring, 8 is the beat_stretch number
      check_sample (ring :loop_garzul,:loop_mika,:loop_safari).tick,8
    end
  end
end

mn=[]; for j in 1..1023
  mn[j]=hz_to_midi(11*j)
end;
use_synth :hoover

m=[3,6,9]
n=[24,30,36,48]

live_loop :one do
  a=choose(m); s=choose(m); r=choose(m)
  play mn[choose(n)], attack: a,
    sustain: s, release: r, amp: 0.6
  print  mn[choose(n)], attack: a,
    sustain: s, release: r
sleep a+s+r; end

live_loop :two do
  # with_fx :echo do
  with_fx :reverb, room: 1 do
    #use_synth :dark_ambience
    use_synth (ring :blade, :hollow,  :hoover).tick
    a=choose(m); s=choose(m); r=choose(m)
    play mn[choose(n)], attack: a,
      sustain: s, release: r, amp: 0.75
  sleep a+s+r; end
  #end
end


live_loop :three do
  a=choose(m); s=choose(m); r=choose(m)
  #use_synth :prophet
  use_synth (ring :hoover, :hollow, :blade).tick
  play mn[choose(n)], attack: a,
    sustain: s, release: r, amp: 0.8
sleep a+s+r; end




# Ryhtm
in_thread do
  with_fx :reverb, room: 1 do
    with_fx :reverb, room: 1 do
      with_fx :rbpf, res: 0, mix: 0.7 do
        ##| with_fx :gverb, mix: 0.2, room: 0.7 do
        loop do
          
          sync :three  
          sample samples_dir, 2, amp: 1.35, rate: 1.4, compress: 1, finish: 0.75, release: 2  
        end
      end
    end
  end
end

Thanks. By the way, I’ve taken the liberty of formatting your code - nice coloured highlighting and indenting makes it easier to read :sweat_smile: (You can do this by placing three back ticks ` on lines before and after your code :slight_smile:).

nice that helps - love the tips and tricks you guys have

Try putting fx wrappers around the live loop rather than inside it. Otherwise you are creating a new instance each pass of the loop and using up resources quickly.
I’ll have a look at your code in more detail later.

Hi any chance of an update on the code

Sorry its taken some time to get here, but I’ve had a busy few days, including evaluating some new code to be introduced in the next version of Sonic Pi
I’ve tided up some of the problems in your code, although it could be tidied up even further.

For simplicity I’ve removed the midi source port (It will accept input from any source on channel 1)
I’ve placed all fx calls AROUND the live_loop they are acting on. That way they are only set up once.

The code is not very precise about where variable are used, and one problem was that you defined n both as the note received from midi input AND as a list used in the live loops one two and three. This created errors. I redefined this list as nl and extracted the note to be played using nv=choose(nl).
I can’t test the final section as I don’t have access to the samples you have in
samples_dir = '/home/p/synth/music'
However I hope what I have done may help you to make further progress.

BE careful in combining sections of code from differnt sources, as you may have to modify them to get them to work nicely together as in this case.
Also I’d convert the final section into a life loop rather than using a loop inside an in_thread.

#7
set_volume! 1
##| Link to the samples folder:
samples_dir = '/home/p/synth/music'


n,v = sync "/midi*:1/note_on"
use_synth :tri
set :flag, false
define :check_sample do |ns,bs|
  in_thread do
    sample ns,beat_stretch: bs,amp: 0.7
    set :flag,true
    sleep bs
    set :flag,false
  end
end

live_loop :midi_in do
  use_real_time
  #n,v = sync "/midi*/note_on"
  n,v = sync "/midi*:1/note_on"
  if v > 0
    play n,amp: v/127.0,release: 0.2
    if get(:flag)==false
      #tick chooses sample in sequence from a ring, 8 is the beat_stretch number
      check_sample (ring :loop_garzul,:loop_mika,:loop_safari).tick,8
    end
  end
end

mn=[]; for j in 1..1023
  mn[j]=hz_to_midi(11*j)
end;
use_synth :hoover

m=[3,6,9]
nl=[24,30,36,48]


live_loop :one do
  a=choose(m); s=choose(m); r=choose(m)
  nv=choose(nl)
  play mn[nv], attack: a,
    sustain: s, release: r, amp: 0.6
  print  mn[nv], attack: a,
    sustain: s, release: r
sleep a+s+r; end

with_fx :reverb, room: 1 do
  with_fx :echo do
    live_loop :two do
      #use_synth :dark_ambience
      use_synth (ring :blade, :hollow,  :hoover).tick
      a=choose(m); s=choose(m); r=choose(m)
      nv=choose(nl)
      play mn[nv], attack: a,
        sustain: s, release: r, amp: 0.75
    sleep a+s+r; end
  end
end

live_loop :three do
  a=choose(m); s=choose(m); r=choose(m)
  #use_synth :prophet
  use_synth (ring :hoover, :hollow, :blade).tick
  nv=choose(nl)
  play mn[nv], attack: a,
    sustain: s, release: r, amp: 0.8
sleep a+s+r; end




# Ryhtm
with_fx :reverb, room: 1 do
  with_fx :reverb, room: 1 do
    with_fx :rbpf, res: 0, mix: 0.7 do
      with_fx :gverb, mix: 0.2, room: 10 do       
        in_thread do
          loop do           
            sync :three
            sample samples_dir, 2, amp: 1.35, rate: 1.4, compress: 1, finish: 0.75, release: 2
          end
        end
      end
    end
  end
end

no worries - thank you for the update and fixing those bugs - I cant wait to try and test it out.

Hi Robin
thanks again Ive been playing with the code - how do I convert the final section into a life loop rather than using a loop inside an in_thread when I want try get the effect of that sample to play in sync with the life loop 3?
eventually i want to add a bunch of samples and have these play in sync with the other live loops 1, 2, 3 etc
Ive uploaded the missing sample which I called in the sample dir

https://soundcloud.com/user-780646121/synth-xmpl/s-ciYlujyfy03