Sure - my confusion was whether you were talking about wanting the sounds triggered by MIDI to be synchronised with other existing sounds, which I gather now is not the case. Sonic Pi - Tutorial shows how to play a Sonic Pi synth via external MIDI, does that get you closer to your goal?
nope - I know how to play a Sonic Pi synth via external MIDI. thats not the issue.
In fact it what I want is the sounds triggered by MIDI to be synchronised with other existing sounds
Ok. So if you’re talking about Sonic Pi just capturing the events, and delaying triggering a synth with the MIDI values until some other sound happens some time in the future, maybe you’ll need to store these note & velocity values from the MIDI event in Time State using
set(:n, n) and
set(:v, v) for example.
That way you can use
get(:v) at the point in your code when you want to actually trigger a sound. (Since you’ll be wanting to have the code that triggers the sound in a separate loop to the one that syncs on the MIDI events).
As it happens, it’s possible the following may provide some useful reading regarding your particular goal - it may be similar:
seems similar not sure but I am looking for examples here on how to achieve as per question - no idea what "quantized after ‘recording’"means
Quantising is basically taking notes that have undesired timing variations, and aligning their timing with a particular ‘grid’. Not as important in this case, so ignore that concept here.
Anyway, there is an example that may be similar to what you are interested in, described in that topic, by Robin - with video and a link to code. Have a look and see if it’s closer to what you’re thinking.
Ok great I’ll take a look.
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 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
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 -
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
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
Hi Robin - amazing yes thats more inline to what Ive been looking for.
Im going to try it out - many thanks!
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 (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 (You can do this by placing three back ticks ` on lines before and after your code ).
nice that helps - love the tips and tricks you guys have