I am a computer science and music student. I have been invited to play a piece with live coding for an event at my university, and I am trying to figure out how to play the music I have in my head, using Sonic Pi.
Specifically, I was thinking about scheduling motives. I personally structure music as motives that may come into place once or several times across the piece, in specific bars or sections. Something like this:
motif1 = […]
motif2 = […]
play motif1 at bar 0
play motif2 at bar 15
Which is the best way to do this in Sonic Pi? Is it possible to schedule blocks of music to play in a future bar? Are bars, time signatures and beats incorporated into the language, or would I have to implement that?
perhaps a natural way of coding motives as you describe them is using functions. This is described in section 5.5 of the built-in tutorial.
Also, to answer your question about bars time signatures and beats - these are things that are specific to Western music and do not have any direct manifestation in Sonic Pi which attempts to be much broader in its musical opportunities. Sonic Pi just talks about tempo and time - out of which you can build your own versions of these constructs. Of course, you can also deviate and do something non-traditional should you choose. See the Steve Reich example for something that illustrates this.
I don’t know Sonic Pi in depth, but i would guess you have to implement it for yourself. My first idea to do so is: use semaphoring. In SonicPi you can use cue: and sync: explained in the tutorial (Thread Synchronisation). You may create a technical loop which cue’s every bar (i.e. every 4 beats) and create a Thread araound a motif which sync to the bar you like to play along, here an example, working with live_loops:
live_loop :give_bar_signal, auto_cue: false do
cue ("bar" + tick.to_s).to_sym
sleep 4
end
live_loop :motifInBar3 do
sync :bar3
play 60 # not really a motif
sleep 4
end
i can’t say, that this is the best, hope it helps.
Also, I should point out that the call to sleep in your :motifInBar3 live loop is actually superfluous in this case, as the sync actually ‘sleeps’ until the next matching cue is observed.
I’m suprised nobody has yet mentioned the ‘at’ command,
which seems to fit the bill completely…
I know there are better examples around than this, just can’t
find one off-hand.
Eli…
use_bpm 120
live_loop :beat4 do
sleep 4
end
define :hat do
at [0, 2, 3],
[{:amp=>0.3}, {:amp=> 1}, {:amp=>0.5}] do |p|
sample :drum_cymbal_pedal, p
end
end
define :drum do
at [1, rrand_i(2, 3)],
[{:amp=>1}] do |p|
sample [:drum_bass_hard, :drum_bass_soft].choose, p
end
end
live_loop :do_hat do
sync :beat4
hat
sleep 1
end
live_loop :do_drum do
sync :beat4
drum
sleep 1
end
Good call - you can totally use at to schedule any arbitrary piece of code/function call to be executed in the future Another related fn is time_warp which has a similar affect (although is subtly different in semantics in important ways).