Hi
,
I am working on a thesis project, that would use algorithmic music generation in context of live coding, by building an application, that would generate variations on melodies and beats, and integrate it with Sonic PI.
At this stage, I have a generator, that produces variations on a single voice MIDI input, based on nth-order Markov chains. The result is then sent to Sonic PI, utilzing the OSC protocol.
Sonic PI code:
live_loop :foo2 do
with_fx :reverb, mix: 0.2, room: 0.8 do
use_synth :fm
use_real_time
note = sync "/osc*/melody/notes"
play note
end
end
Sending OSC messages:
for (const [idx, [pitch, quantizedSteps]] of notes.entries()) {
this.oscClient.send(pitch);
/* eslint-disable-next-line no-await-in-loop */
await sleep((quantizedSteps / stepsPerQuater) * 1000);
bar.update(idx + 1);
}
Currently, messages are played, when they are received by Sonic PI and I was wondering what would be the options of syncing the incoming messages to the current beat/loop(s)/metronome playing in Sonic PI?
Or, what could be done alternatively to sync the generator with Sonic PI?
Thanks in advance 
Does adding a second sync under the one that receives MIDI events to wait for a metronome (or similar) cue help? eg:
note = sync "/osc*/melody/notes"
sync :metronome
play note
(This would of course need slightly different handling depending on whether the idea is to receive a single generated note at a time, or a sequence of notes at a time).
@ethancrawford Thank you for your reply!
I actually changed the way the generated notes are being sent. Instead of sending notes sequentially in real time, I am sending the whole generated sequence in two messages - notes and durations. Additionally, I am syncing the loop that plays the incoming sequence with the beat. Seems to be working 
use_bpm 120
live_loop :receive_sequence do
use_real_time
seq = sync "/osc*/gen/sequence"
s = sync "/osc*/gen/steps"
set :sequence, seq
set :steps, s
end
live_loop :beat do
sample :drum_bass_soft
sleep 1
end
live_loop :play_gen_sequence, sync: :beat do
use_synth :hoover
gen_notes = get[:sequence] || []
gen_steps = get[:steps] || []
notes = gen_notes.zip(gen_steps)
puts notes
if notes.empty?
sleep 1
else
notes.each do |note, step|
play note, release: 1, amp: 0.3
sleep step
end
end
end
1 Like