External sample issues

Hello all,

I’m super new to both coding and Sonic Pi but love both so far. I have encountered a few issues with external samples.
When I play an external sample using live_loop and hit run again, it plays multiple samples that overlapp and doesn’t kill the previous ones. I know I’m probably not doing something right but I thought this usually shouldn’t happen using live_loop?

Another issue I’m having is with my folder of samples. I’m using “sample samples, 0” to call my samples from their folder but they come in random, for instance when I type 0 it will not play the first sample in the list but one that is somewhere in the middle. How does Sonic Pi define the list’s order?

Finally, and this is super newbie stuff, but how do I stretch my sample to play the entire length of my sleep cycle to have play continuously without interuption?

Thanks!!

1 Like

Hi Eye,

Other people will pitch in with answers no doubt, some will be better than mine, I
just happen to have got here first.

Lets go with question 3 first… stretching samples and sleeping… heres some example
code which should explain without too many words.

#sleep for the length of the sample.
live_loop :do_sample1 do
  t=[:drum_bass_hard, :drum_heavy_kick].choose
  sample t, pan: 0, amp: 1
  sleep sample_duration(t)
end

#stretch the length of the sample.
live_loop :do_sample2 do
  t=[:drum_bass_hard, :drum_heavy_kick].choose
  sample t, pan: 0, amp: 1, beat_stretch: 2
  sleep 2
end

As for question 2, I dont rely on using “sample samples, 0”
to load samples… if I want a sample, I load it by name…

sample “fred/drums/kick.wav”

It is also possible to put the name into a variable as in the
above example, and then call it with sample…

t=“fred/drums/kick.wav”
sample t

It is also possible to set a path to your samples if they
are nested deep in subfolders, etc…

sample_paths “/path/to/samples/**”

Even more convenient, you can also drag and drop a sample
file into the SP coding window and it will copy the path to the
file for you.

As for your first question, without really seeing your code,
I cant say why thats happening… so post it up in a reply.

If you use ‘’’ on the line previous to your code in the post,
it will put it in a neat scrollable box, much easier to read.

‘’’ on the line after you code will close the box, allowing you
to continue writing your post.

Regards,

Eli…

1 Like

Hey Eli,

Thanks so much for your reply! I actually figured out my first question. The problem was happening when using “sample samples, 0”. However when I load it by sample name directly I didn’t have that issue anymore. Thanks again for your help!

One reason you may get an odd looking order is that the sample path,index method is case sensitive. This means that a sample named Moo.wav would actually play before a sample named cow.wav as it will read Uppercase BEFORE lowercase.

I guess you might be wanting to play a folder of sample continuously end to end. The problem with that is that it is not obvious how to get the sample name to use in sleep sample_duration <name>
to let you sleep the length of each sample before the next one starts.
I played around with some of the other commands in Sonic Pi and came up with a solution which utilises the commands sample_info and sample_paths

i first ran the program:

path="~/Desktop/samples/"
index=0
puts sample_info path,index

This looked at my samples folder and produced some information about the matching sample

├─ #<SampleBuffer @id=38, @num_chans=2, @num_frames=282241, @sample_rate=44100.0, @duration=6.400022675736961>

Quite a lot of information, but significantly including the sample duration at the end.
Changing this to:

path="~/Desktop/samples/"
index=0
puts sample_duration sample_info path,index

produced the sample duration

 ├─ 6.400022675736961

In then built up stage by stage a command to extract the sample name:

path="~/Desktop/samples/"
index=0

puts (sample_paths sample_info path,index) #gets info as a ring
puts (sample_paths sample_info path,index)[0]  #changes back to a string
puts (sample_paths sample_info path,index)[0].split("/") #splits to a list of strings
puts (sample_paths sample_info path,index)[0].split("/")[-1] #extract the last element which is the name

which produced:

 ├─ (ring "/Users/rbn/Desktop/samples/MK03.wav")
 ├─ "/Users/rbn/Desktop/samples/MK03.wav"
 ├─ ["", "Users", "rbn", "Desktop", "samples", "MK03.wav"]
 └─ "MK03.wav"

I then put all of this together, and defined two additional methods to enable these to be used together:

path="/Users/rbn/Desktop/Sonatina Symphonic Orchestra/Samples/Percussion/"

define :getSampleName do |path,index=0|
  begin
    k=(sample_paths sample_info path,index)[0].split("/")[-1]
  rescue
    return nil
  else
    return k
  end
end

define :getSampleDuration do |path,index=0|
  begin
    k=sample_duration sample_info path,index
  rescue
    return 0.1 #return small number if no sample found
  else
    return k
  end
end

live_loop :splay do
  tick
  puts getSampleName(path,look)
  sample path,look
  sleep getSampleDuration(path,look)
end

This final example played all the percussion samples in the Sonatina Symphonic Orchestra percussion folder repeatedly. I added some error handling so it wouldn’t crash if a sample wasn’t found.

2 Likes

Yup, Told you other people would have better answers than me. :slight_smile:

Usually its Robin, Martin or Ethan. One day maybe I’ll know as much as they do.

Eli,

2 Likes

Hi Robin!
Thanks so much for taking the time to reply! It must the way the samples are labeled, I was actually looking to just play a single sample from a folder, but this is actually very helpful because this could be a great way for me to experiment playing samples continuously.
Thanks again!

Thanks Eli, you are still light years ahead of me! :slight_smile:

I will add my two cents and join this discussion :wink: ; I have two strategies I frequently use:

In my ~/.sonic-pi/init.rb (that’s the place for a Linux system) you can find e. g.:

define :beats do
  beats = "~/projects/sonicpi/playground/audio/samples/loops/beats/"
end

Let’s assume this folder contains a sample named my_best_loop.wav I then load it with:

live_loop :test do
  sample beats, "best", beat_stretch: 4
  sleep 4
end

I also have entries in the init.rb like

define :beats do
  collection = "~/a/sample/collection/with/subfolders/"
end

as shortcut to a folder which will contain subfolders with samples. Let’s assume the my_best_loop.wav would reside in a subfolder called selected_loops. It then goes this way:

live_loop :test do
  sample , collection + "selected_loops", "best", beat_stretch: 4
  sleep 4
end

That way I can reference a whole collection of folders (and samples) without the need to adjust my init.rb all the time. But that’s a matter of taste and workflow.

3 Likes

Thanks so much Martin, I will try that!