set :k,“C:/Users/MSI/Desktop/New folder/sounds1”
set :s,“C:/Users/MSI/Desktop/New folder/sounds2”
define :sampl do |sam, out = 1|
with_fx :sound_out_stereo, output: out do
sample get[sam]
end
end
live_loop :hoho do
if ring(:true, :true, :true, :true)
sampl :k, 3
end
sleep rrand(1, 3)
end
live_loop :haha do
if ring(:false, :true, :false, :true)
sampl :s, 5
end
sleep rrand(1, 4)
end
I edited an older code, so I can send the output of external folders of sounds (the 2 live_loops) into different channels in another software. I’m pretty new to Sonic Pi, so how can I edit the code that would play the sounds of each folder randomly? Because now it just plays the first sound of each folder, but I want it to pick randomly from the folders.
What @brendanmac is true, you need to pick one element of the ring to look at. You can use .choose to pick a random element, or .tick to iterate through them in order.
But also when you call sample get[sam] it will always play the first sample that it finds in the folder.
You can get it to pick a random one with sample get[sam], choose.
You can also do things like: sample get[sam], "guitar" : play the (first) sample with “guitar” in the name. sample get[sam], "bass", choose : play a random sample with “bass” in the name. sample get[sam], 3 : play the third sample sample get[sam], [2, 5, 7].choose : randomly play the 2nd, 5th or 7th sample
thanks so much! this is a different question, but here’s this code:
use_midi_defaults channel: 1, port: “loopmidi_port_1”
use_random_seed Time.now.to_i
live_loop :yayaya do
midi scale(:c4,:minor_pentatonic).choose,sustain: 1,vel_f: 0.8
sleep rrand(0.1, 2)
end
It sends midi notes out to an external synth, randomly picking from a scale. Is it possible to stop it from picking the same notes after each other sometimes? Like picking only different notes from that scale.
Try something like this (I"ve just played a note, but substitute midi to send externally)
set :n,:c0 #choose an out of range note for intial comparison
use_random_seed Time.now.to_i
live_loop :yayaya do
n=scale(:c4,:minor_pentatonic).choose
while n==get(:n) #check if it equals the previous note
puts "duplicate note #{n}"
n=scale(:c4,:minor_pentatonic).choose #choose another note instead
end
set :n,n #save new note for next comparison
play n,release: 0.1 #midi here in your version
sleep rrand(0.1, 2)
end
s = (scale :c4, :major)
print s
print s.length
sleep 0.5
n = rand_i(s.length) #initialise n
live_loop :scales do
print s[n] #put play / midi here
n = (n + rand_i(s.length - 1) + 1) % s.length
#+-1 because we don't want 0
sleep 1
end
Different approach without a condition. Could be done with tick instead of n as well.
thank you again everyone!
so last question, related to the og post.
this is the code I have now with the folders:
set :k,“C:/USER/New folder/sounds1”
set :s,“C:/USER/New folder/sounds2”
define :sampl do |sam, out = 1|
with_fx :sound_out_stereo, output: out do
sample get[sam], choose #I CAN ADD SAMPLE MODULATION HERE, BUT IT EFFECTS BOTH FOLDER
end
end
#FIRST FOLDER
use_random_seed Time.now.to_i
live_loop :hoho do
if ring(:true, :true, :true, :true)
sampl :k, 3 #SENDS OUT AUDIO TO 3/4 STEREO CHANNEL
end
sleep rrand(2, 6)
end
#SECOND FOLDER
use_random_seed Time.now.to_i
live_loop :haha do
if ring(:false, :true, :false, :true)
sampl :s, 5 #SENDS OUT AUDIO TO 5/6 STEREO CHANNEL
end
sleep rrand(3, 7)
end
Is it possible this way to modulate the samples of the folders individually, not both of them at the same time? It’s not a big problem, but would be handy if I could do it.
Yes, you could either not use the :sampl function and just put the code directly in each live_loop, or you can pass the options into the function like this:
set :k,"C:/USER/New folder/sounds1"
set :s,"C:/USER/New folder/sounds2"
define :sampl do |sam, out = 1, opts={}|
with_fx :sound_out_stereo, output: out do
sample get[sam], choose, **opts
end
end
#FIRST FOLDER
use_random_seed Time.now.to_i
live_loop :hoho do
if ring(:true, :true, :true, :true)
sampl :k, 3, amp: 2 #SENDS OUT AUDIO TO 3/4 STEREO CHANNEL
end
sleep rrand(2, 6)
end
#SECOND FOLDER
use_random_seed Time.now.to_i
live_loop :haha do
if ring(:false, :true, :false, :true)
sampl :s, 5, cutoff: 90 #SENDS OUT AUDIO TO 5/6 STEREO CHANNEL
end
sleep rrand(3, 7)
end
By the way, when pasting code into here, you can add three backticks (```) on a line of their own before and after the code, it will format it nicely.
Hey!
So I tried this (and the code below yours), but neither of them are working, there’s still some time when the randomiser picks the same note in a sequence from the scale, which I want to avoid. Is there another way to make this happen?
Both versions posted work for me as they are, so I’m guessing you’ve modified them to fit into your code? If you post the code that isn’t working someone can take a look and work out what’s wrong.
This is what I have now, I want multiple live_loops to run at the same time (both of them are sending midi notes to an external synth of mine). On the first live_loop (named yayaya) it seems to work, but not on the other one. Am I doing something wrong?
############################################################################
set :n,:e0 #choose an out of range note for intial comparison
use_midi_defaults channel: 1, port: “loopmidi_port_1”
use_random_seed Time.now.to_i
live_loop :yayaya do
n=scale(:e3,:minor, num_octaves: 2).choose
while n==get(:n) #check if it equals the previous note
puts “duplicate note #{n}”
n=scale(:e3,:minor, num_octaves: 2).choose #choose another note instead
end
set :n,n #save new note for next comparison
play midi n
sleep rrand(0.1, 1)
end
set :n,:e0 #choose an out of range note for intial comparison
use_midi_defaults channel: 2, port: “loopmidi_port_1”
use_random_seed Time.now.to_i
live_loop :yoyoyo do
n=scale(:e3,:minor, num_octaves: 2).choose
while n==get(:n) #check if it equals the previous note
puts “duplicate note #{n}”
n=scale(:e3,:minor, num_octaves: 2).choose #choose another note instead
end
set :n,n #save new note for next comparison
play midi n
sleep rrand(0.1, 2)
end
besides all of this, is there a chance that I can combine ( this code below with the individual live_loops above? (I copied the code below from a tutorial, which makes the leaps between the randomly picked notes smaller, which I want to incorporate into these live_loops)
sc = scale(:e4, :major, num_octaves: 2)
n = sc.choose
leap = 0
previousN = 0
live_loop :melody do
play n
sleep 0.5
previousN = n
if leap.abs() > 4
index = sc.index(n)
if one_in(2)
n = sc[index + 1]
else
n = sc[index - 1]
end
else
n = sc.choose
end
leap = n -previousN
puts "leap = ", leap
end
Sorry I can’t look at this right now as the purchase of my new home finished yesterday and I will be in the throes of moving in and unpacking lots of boxes for the next week including having new internet fibre installed.
It might be that both live_loops are saving their note in the same place (set :n,n). You should use a different name for both so that they don’t conflict with each other.
For combining the code from the tutorial, I think you can use it mostly as it is, but just after the line with n = sc.choose you can add:
while n == previousN
n = sc.choose
end
This will choose a new note whenever it happens to pick the same note as the previous one.
Also, one little thing: you don’t need to use play midi n, just midi n is enough to send the midi note.
So I tried it, and it seems to work fine, but is this the way you suggested the combination?
sorry for the number of questions I’m asking, but one more came up:
Is there a way I can change the key of the scale of both live_loops with only 1 line, when I run the code multiple times? It’s just hard to change every line with the scale in it, and it would be handy to just have 1 line that connects every line with the “scale(:e2,:minor_pentatonic, num_octaves: 3)” line together, so I could just change that, when I run the whole code again.
sc = scale(:e2,:minor_pentatonic, num_octaves: 3)
n = sc.choose
leap = 0
previousN = 0
#CHANNEL 1
set :n,:e0
use_midi_defaults channel: 1, port: “loopmidi_port_1”
use_random_seed Time.now.to_i
live_loop :yayaya do
n=scale(:e2,:minor_pentatonic, num_octaves: 3).choose
while n==get(:n)
puts “duplicate note #{n}”
n=scale(:e2,:minor_pentatonic, num_octaves: 3).choose
end
set :n,n
midi n
sleep rrand(0.1, 6)
previousN = n
if leap.abs() > 4
index = sc.index(n)
if one_in(2)
n = sc[index + 1]
else
n = sc[index - 1]
end
else
n = sc.choose
while n == previousN
n = sc.choose
end
end
leap = n -previousN
puts "leap = ", leap
end
#CHANNEL 2
set :f,:e1
use_midi_defaults channel: 2, port: “loopmidi_port_1”
use_random_seed Time.now.to_i
live_loop :yoyoyo do
n=scale(:e2,:minor_pentatonic, num_octaves: 3).choose
while n==get(:f)
puts “duplicate note #{n}”
n=scale(:e2,:minor_pentatonic, num_octaves: 3).choose
end
set :f,n
midi n
sleep rrand(0.1, 3)
previousN = n
if leap.abs() > 4
index = sc.index(n)
if one_in(2)
n = sc[index + 1]
else
n = sc[index - 1]
end
else
n = sc.choose
while n == previousN
n = sc.choose
end
end
leap = n -previousN
puts "leap = ", leap
end
I think this should do it; you can set the scale at the start of the code (set :sc, scale(...)), then every time you want to use it, you can get it with get :sc. If you change the scale at the top and rerun the code, it should change the scale used in both loops:
set :sc, scale(:e2,:minor_pentatonic, num_octaves: 3)
n = get(:sc).choose
leap = 0
previousN = 0
#CHANNEL 1
set :n,:e0
use_midi_defaults channel: 1, port: "loopmidi_port_1"
use_random_seed Time.now.to_i
live_loop :yayaya do
n=get(:sc).choose
while n==get(:n)
puts "duplicate note #{n}"
n=get(:sc).choose
end
set :n,n
midi n
sleep rrand(0.1, 6)
previousN = n
if leap.abs() > 4
index = get(:sc).index(n)
if one_in(2)
n = get(:sc)[index + 1]
else
n = get(:sc)[index - 1]
end
else
n = get(:sc).choose
while n == previousN
n = get(:sc).choose
end
end
leap = n -previousN
puts "leap = ", leap
end
#CHANNEL 2
set :f,:e1
use_midi_defaults channel: 2, port: "loopmidi_port_1"
use_random_seed Time.now.to_i
live_loop :yoyoyo do
n=get(:sc).choose
while n==get(:f)
puts "duplicate note #{n}"
n=get(:sc).choose
end
set :f,n
midi n
sleep rrand(0.1, 3)
previousN = n
if leap.abs() > 4
index = get(:sc).index(n)
if one_in(2)
n = get(:sc)[index + 1]
else
n = get(:sc)[index - 1]
end
else
n = get(:sc).choose
while n == previousN
n = get(:sc).choose
end
end
leap = n -previousN
puts "leap = ", leap
end
There should be a way to prevent that. Is idx % size from your code? If so, where does idx come from? It looks like it is sometimes getting a nil value.
Actually, I think it might come from index = get(:sc).index(n): if the note n is not in the scale (because the scale has just been changed, and n comes from the previous scale), then you will get a nil. To fix this, you can add this line just after idx is set:
idx = 0 if idx === nil
This will set it to zero if it was nil (i.e. the note was not found).