Hi there,
in Sonic Pi, random streams are thread-local. This means that each thread (such as a live_loop) has its own independent stream of random numbers to work with. This is kind of analogous to having a pre-shuffled deck of cards to work with.
Every time a random function such as rand, rrand, choose, etc is used, it will consume one rand from the random stream - or take one card from the pre-shuffled deck to determine the random value. This means that having just one call to, say, rand in each live_loop will mean the random choices in each live loop are isolated from each other as they are each working with their own independent deck of pre-shuffled cards.
If you put more than one call to rand in a live_loop, then you’re taking more than one card from the deck. This means that the calls will interfere with each other. So, say you’re using the specific order of the top 8 cards on the deck to drive your bassline, if you were to then use every other card (because you started consuming cards for the pan opt) then your bassline will inevitably change.
To fix this, you should either work with a new thread, or if that’s not possible (as it seems to be in your case) you can use the handy rand_back function to undo a call to rand and effectively put a card back on the deck.
So, try this:
use_bpm 133
live_loop :melle do
with_fx :octaver, sub_amp: 2, amp: 1.5, mix: 0.4 do
with_fx :reverb, room: 0.6, mix: 0.6 do
use_synth :saw
use_random_seed (knit, 9864, 4, 235, 4).tick(:a)
sleep 1
14.times do
play scale(:c3, :ionian, num_octaves: 2).choose, amp: 0.15, pan: rrand(-1, 1), release: 0.5 if spread(10, 14).tick
rand_back
sleep 0.5
end
end
end
end
However, this won’t completely work as expected as you’re only calling the rrand for pan: if the spread value suggests it should. This is because you’re adding an if at the end of the line so it doesn’t execute every time - whereas the rand_back is executed every time.
For it to work as expected, we need to only call rand_back when the rrand is called.
We can therefore either put both the play and rand_back within the same larger if statement:
if spread(10, 14).tick
play scale(:c3, :ionian, num_octaves: 2).choose, amp: 0.15, pan: rrand(-1, 1), release: 0.5
rand_back
end
Or my prefered solution is to use on: instead of if. That way the call to rrand happens every time, but the synth is only triggered when the spread value is appropriate (whereas with the call to if not only is the synth not triggered, but the whole line isn’t executed and therefore not the rrand).
use_bpm 133
live_loop :melle do
with_fx :octaver, sub_amp: 2, amp: 1.5, mix: 0.4 do
with_fx :reverb, room: 0.6, mix: 0.6 do
use_synth :saw
use_random_seed (knit, 9864, 4, 235, 4).tick(:a)
sleep 1
14.times do
play scale(:c3, :ionian, num_octaves: 2).choose, amp: 0.15, pan: rrand(-1, 1), release: 0.5, on: spread(10, 14).tick
rand_back
sleep 0.5
end
end
end
end
Hope that this helps!