Trigger sample

sample  name_or_path (symbol_or_string)

Play back a recorded sound file (sample). Sonic Pi comes with lots of great samples included (see the section under help) but you can also load and play .wav, .wave, .aif, .aiff, .ogg, .oga or .flac files from anywhere on your computer too. To play a built-in sample use the corresponding keyword such as sample :bd_haus. To play any file on your computer use a full path such as sample "/path/to/sample.wav".

There are many opts for manipulating the playback. For example, the rate: opt affects both the speed and the pitch of the playback. To control the rate of the sample in a pitch-meaningful way take a look at the rpitch: opt.

The sampler synth has three separate envelopes - one for amplitude, one for a low pass filter and another for a high pass filter. These work very similar to the standard synth envelopes except for two major differences. Firstly, the envelope times do not stretch or shrink to match the BPM. Secondly, the sustain time by default stretches to make the envelope fit the length of the sample. This is explained in detail in the tutorial.

Samples are loaded on-the-fly when first requested (and subsequently remembered). If the sample loading process takes longer than the schedule ahead time, the sample trigger will be skipped rather than be played late and out of time. To avoid this you may preload any samples you wish to work with using load_sample or load_samples.

It is possible to set the start: and finish: positions within the sample to play only a sub-section of it. These values can be automatically chosen based on an onset detection algorithm which will essentially isolate each individual drum or synth hit in the sample and let you access each one by an integer index (floats will be rounded to the nearest integer value). See the onset: docstring and examples for more information.

Finally, the sampler supports a powerful filtering system to make it easier to work with large folders of samples. The filter commands must be used before the first standard opt. There are six kinds of filter parameters you may use:

  1. Folder strings - "/foo/bar" - which will add all samples within the folder to the set of candidates.
  2. Recursive folder strings - "/foo/bar/**" - Folder strings ending with ** will add all samples contained within all subfolders (searched recursively).
  3. Sample strings - "/path/to/sample.wav" - which will add the specific sample to the set of candidates.
  4. Other strings - "foobar" - which will filter the candidates based on whether the filename contains the string.
  5. Regular expressions - /b[aA]z.*/ - which will filter the candidates based on whether the regular expression matches the filename.
  6. Keywords - :quux - will filter the candidates based on whether the keyword is a direct match of the filename (without extension).
  7. Numbers - 0 - will select the candidate with that index (wrapping round like a ring if necessary).
  8. Lists of the above - ["/foo/bar", "baz", /0-9.*/] - will recurse down and work through the internal filter parameters as if they were in the top level.
  9. Lambdas - lambda {|s| [s.choose] } - the ultimate power tool for filters. Allows you to create a custom fn which receives a list of candidates as an arg and which should return a new list of candidates (this may be smaller, larger, re-ordered it’s up to you).

By combining commands which add to the candidates and then filtering those candidates it is possible to work with folders full of samples in very powerful ways. Note that the specific ordering of filter parameters is irrelevant with the exception of the numbers - in which case the last number is the index. All the candidates will be gathered first before the filters are applied.

Introduced in v2.0

Examples

# Example 1


sample :loop_amen



# Play a built-in sample
# Plays the Amen break



# Example 2



sample :loop_amen
sample :ambi_lunar_land
                       



# Play two samples at the same time
# with incredible timing accuracy
 
# Note, for timing guarantees select the pref:
#   Studio -> Synths and FX -> Enforce timing guarantees



# Example 3


live_loop :bass do
  sample :bd_haus
  sleep 0.5
end



# Create a simple repeating bass drum
 
 
 
 



# Example 4


live_loop :rhythm do
  sample :tabla_ghe3 if (spread 5, 7).tick
  sleep 0.125
end
live_loop :bd, sync: :rhythm do
  sample :bd_haus, lpf: 90, amp: 2
  sleep 0.5
end



# Create a more complex rhythm with multiple live loops:
 
 
 
 
 
 
 
 



# Example 5


sample :loop_amen, rate: 0.5
                            



# Change the playback speed of the sample using rate:
# Play the Amen break at half speed
# for old school hip-hop



# Example 6


sample :loop_amen, rate: 1.5
                            



# Speed things up
# Play the Amen break at 1.5x speed
# for a jungle/gabba sound



# Example 7


sample :loop_amen, rate: -1



# Go backwards
# Negative rates play the sample backwards



# Example 8


sample :loop_amen, rate: -3



# Fast rewind
# Play backwards at 3x speed for a fast rewind effect



# Example 9


sample :loop_amen, start: 0.5



# Start mid sample
# Start playback half way through



# Example 10


sample :loop_amen, finish: 0.5



# Finish mid sample
# Finish playback half way through



# Example 11


sample :loop_amen, start: 0.125, finish: 0.25



# Play part of a sample
# Play the second eighth of the sample



# Example 12


sample :loop_amen, start: 0.25, finish: 0.125



# Finishing before the start plays backwards
# Play the second eighth of the sample backwards



# Example 13


sample :loop_amen, start: 0.125, finish: 0.25, rate: -0.25
                                                          
                                                          



# Play a section of a sample at quarter speed backwards
# Play the second eighth of the
# amen break backwards at a
# quarter speed



# Example 14


s = sample :loop_amen, lpf: 70
sleep 0.5
control s, lpf: 130
sleep 0.5
synth :dsaw, note: :e3



# Control a sample synchronously
 
 
 
 
# This is triggered 1s from start



# Example 15


sample :loop_amen, lpf: 70 do |s|
  sleep 1                               
  control s, lpf: 130                   
end
sleep 0.5
synth :dsaw, note: :e3



# Controlling a sample asynchronously
 
# This block is run in an implicit in_thread
# and therefore is asynchronous
 
 
# This is triggered 0.5s from start



# Example 16


sample :loop_garzul, slice: 0     
sleep 0.5
4.times do
  sample :loop_garzul, slice: 1   
  sleep 0.125
end
sample :loop_garzul, slice: 4, num_slices: 4, rate: -1     



# Play with slices
# => play the first 16th of the sample
 
 
# => play the second 16th of the sample 4 times
 
 
# => play the final quarter backwards



# Example 17


use_sample_bpm :loop_amen                   
live_loop :beat_slicer do
  n = 8                                     
                                            
  s = rand_i n                              
  sample :loop_amen, slice: s, num_slices: n
  sleep 1.0/n                               
end



# Build a simple beat slicer
# Set the BPM to match the amen break sample
 
# Specify number of slices
# (try changing to 2, 4, 6, 16 or 32)
# Choose a random slice within range
# Play the specific part of the sample
# Sleep for the duration of the slice
 



# Example 18


sample :loop_amen, lpf: 80, hpf: 70, compress: 1, pre_amp: 10



# Play with the built-in low pass filter, high pass filter and compressor
# Make the amen break sound punchy.



# Example 19


sample :loop_garzul, lpf_attack: 8
sleep 8
sample :loop_garzul, hpf_attack: 8



# Use the cutoff filter envelopes
# Sweep the low pass filter up over 8 beats
 
# Sweep the high pass filter down over 8 beats



# Example 20


puts sample_duration :loop_industrial                  
puts sample_duration :loop_industrial, beat_stretch: 1 
live_loop :industrial do
  sample :loop_industrial, beat_stretch: 1             
  sleep 1                                              
                                                       
                                                       
end



# Sample stretching
# => 0.88347
# => 1
 
# Stretch the sample to make it 1 beat long
# This now loops perfectly.
# However, note that stretching/shrinking
# also modifies the pitch.
 



# Example 21


puts sample_duration :loop_garzul                      
puts sample_duration :loop_garzul, beat_stretch: 6     
live_loop :garzul do
  sample :loop_garzul, beat_stretch: 6                 
                                                       
                                                       
  sleep 6
end



# Sample shrinking
# => 8
# => 6
 
# As :loop_garzul is longer than 6 beats
# it is shrunk to fit. This increases the
# pitch.
 
 



# Example 22


use_bpm 30                                             
puts sample_duration :loop_garzul                      
puts sample_duration :loop_garzul, beat_stretch: 6     
live_loop :garzul do
  sample :loop_garzul, beat_stretch: 6                 
  sleep 6
end



# Sample stretching matches the BPM
# Set the BPM to 30
# => 4.0 (at 30 BPM the sample lasts for 4 beats)
# => 6.0
 
# The sample is stretched to match 6 beats at 30 BPM
 
 



# Example 23


sample "/path/to/sample.wav"                         
                                                       
                                                       



# External samples
# Play any Wav, Aif, Ogg, Oga, or FLAC sample on your computer
# by simply passing a string representing the full
# path



# Example 24


dir = "/path/to/dir/of/samples"                      
sample dir                                             
                                                       
sample dir, 1                                          
sample dir, 99                                         
                                                       
                                                       
                                                       
                                                       
sample dir, "120"                                    
                                                       
                                                       
sample dir, "120", 1                                 
                                                       
                                                       
sample dir, /beat[0-9]/                                
                                                       
                                                       
                                                       
                                                       
sample dir, /beat[0-9]0/, "100"                      
                                                       
                                                       
                                                       



# Sample pack filtering
# You can easily work with a directory of samples
# Play the first sample in the directory
# (it is sorted alphabetically)
# Play the second sample in the directory
# Play the 100th sample in the directory, or if there
# are fewer, treat the directory like a ring and keep
# wrapping the index round until a sample is found.
# For example, if there are 90 samples, the 10th sample
# is played (index 9).
# Play the first sample in the directory that contains
# the substring "120".
# For example, this may be "beat1_120_rave.wav"
# Play the second sample in the directory that contains
# the substring "120".
# For example, this may be "beat2_120_rave.wav"
# Play the first sample in the directory that matches
# the regular expression /beat[0-9]/.
# For example, this may be "beat0_100_trance.wav"
# You may use the full power of Ruby's regular expression
# system here: http://ruby-doc.org/core-2.1.1/Regexp.html
# Play the first sample in the directory that both matches
# the regular expression /beat[0-9]0/ and contains the
# the substring "100".
# For example, this may be "beat10_100_rave.wav"



# Example 25


                                                       
                                                       
sample "tabla_"                                      
                                                       
sample "tabla_", 2                                   
                                                       



# Filtering built-in samples
# If you don't pass a directory source, you can filter over
# the built-in samples.
# Play the first built-in sample that contains the substring
# "tabla"
# Play the third built-in sample that contains the substring
# "tabla"



# Example 26


load_samples "tabla_"                                
                                                       
                                                       
live_loop :tabla do
  sample "tabla_", tick                              
  sleep 0.125
end



# Play with whole directories of samples
# You may pass any of the source/filter options to load_samples
# to load all matching samples. This will load all the built-in
# samples containing the substring "tabla_"
 
# Treat the matching samples as a ring and tick through them
 
 



# Example 27


dir1 = "/path/to/sample/directory"
dir2 = "/path/to/other/sample/directory"
sample dir1, dir2, "foo"                             
                                                       
                                                       



# Specify multiple sources
 
 
# Match the first sample that contains the string "foo" out of
# all the samples in dir1 and dir2 combined.
# Note that the sources must be listed before any filters.



# Example 28


dir = "/path/to/sample/directory"                    
                                                       
dir_recursive = "/path/to/sample/directory/**"       
                                                       
                                                       
sample dir, 0                                          
sample dir_recursive, 0                                
                                                       
                                                       
                                                       
                                                       



# List contents recursively
# By default the list of all top-level samples within the directory
# is considered.
# However, if you finish your directory string with ** then if that
# directory contains other directories then the samples within the
# subdirectories and their subsubdirectories in turn are considered.
# Play the first top-level sample in the directory
# Play the first sample found after combining all samples found in
# the directory and all directories within it recursively.
# Note that if there are many sub directories this may take some time
# to execute. However, the result is cached so subsequent calls will
# be fast.



# Example 29


filter = lambda do |candidates|                        
  [candidates.choose]                                  
end                                                    
                                                       
8.times do
  sample "drum_", filter                             
  sleep 0.25                                           
end



# Bespoke filters
# If the built-in String, Regexp and index filters are not sufficient
# you may write your own. They need to be a function which takes a list
# of paths to samples and return a list of samples. This one returns a
# list of a single randomly selected sample.
 
# Play 8 randomly selected samples from the built-in sample set that also
# contain the substring "drum_"
 



# Example 30


sample :loop_tabla, start: 0, finish: 0.00763          
                                                       
                                                       
sleep 1
                                                       
                                                       
sample :loop_tabla, onset: 0                           
                                                       
                                                       
sleep 1
sample :loop_tabla, onset: 1                           
                                                       



# Basic Onset Detection
# If you know the right start: and finish: values, you can extract a
# single drum hit from a longer sample. However, finding these values
# can be very time consuming.
 
# Instead of specifying the start: and finish: values manually you can
# use the onset: option to find them for you using an integer index.
# onset: 0 will set the start: and finish: values so that the first
# percussive sound (something that shifts from quiet to loud quickly)
# is picked out.
 
# We can easily find the second percussive sound in the sample with
# onset: 1



# Example 31


                                                       
                                                       
                                                       
                                                       
                                                       
live_loop :tabla do
  use_bpm 50                                           
  sample :loop_tabla, onset: tick                      
  sleep [0.125, 0.25].choose                           
end



# Ticking through onsets
# The onsets are actually a ring so the index will wrap around. This
# means that if there are only 8 onsets in a sample, specifying an
# onset of 100 will still return one of the 8 onsets. This means we
# can use tick to work through each onset in sequence. This allows us
# to redefine the rhythm and tempo of a sample
 
# We can choose our own BPM here - it doesn't need to match the sample
# tick through each onset in sequence
# randomly choose a delay between onset triggers
 



# Example 32


                                                       
use_bpm 50
live_loop :tabla do
  sample :loop_tabla, onset: pick                      
  sleep [0.125, 0.25].choose                           
end



# Random Onset Triggering
# We can easily pick a random onset using the pick fn
 
 
# Each time round the live loop we now trigger a random onset
# creating an infinite stream of randomly selected drums
 



# Example 33


                                                       
                                                       
live_loop :tabla do
  use_random_seed 30000                                
  8.times do
    sample :loop_tabla, onset: pick
    sleep [0.125, 0.25].choose
  end
end



# Repeatable Random Onsets
# Instead of an infinite stream of choices, we can combine iteration
# and use_random_seed to create repeatable riffs:
 
# every 8 times, reset the random seed, this resets the riff
 
 
 
 
 



# Example 34


                                                           
                                                           
                                                           
                                                           
                                                           
live_loop :tabla do
  sample :loop_tabla, onset: pick, sustain: 0, release: 0.1
                                                           
                                                           
                                                           
  sleep [0.125, 0.25].choose
end



#  Random Onset Duration
# Each onset has a variable length (determined by the sample contents).
# Therefore, if you wish to ensure each onset has a specific length it
# is necessary to use the sample's amplitude envelope.
# As the sample's envelope automatically changes the sustain: value to
# match the duration - you also need to override this with a value of 0.
 
# Each drum onset will now be no longer than 0.1. Note that the envelope
# for a sample only determines the maximum duration of a sample trigger.
# If the actual audible duration of the onset is smaller than 0.1 then
# it will *not* be extended.
 
 



# Example 35


                                                       
                                                       
                                                       
l = lambda {|c| puts c ; c[0]}                         
                                                       
                                                       
                                                       
sample :loop_tabla, onset: l                           
                                                       
                                                       
                                                       
                                                       



# Onset lambdas
# The onset index can be a lambda as well as an integer. If a lambda is
# given, it will be passed a ring of all of the onsets as an argument.
# This will be a ring of maps:
# define a lambda which accepts a single argument, prints it and
# returns the first value. This particular example is essentially
# the same as using onset: 0 with the side effect of also printing out
# the full ring of onsets:
# (ring {:start=>0.0, :finish=>0.0076}, {:start=>0.0076, :finish 0.015}...)
# We are therefore free to define this lambda to do anything we want.
# This gives us very powerful control over the choice of onset. It is
# unlikely you will use this frequently, but it is a powerful tool
# that's there when you need it.



# Example 36

sample :loop_tabla, onset: 1                                        
                                                                    
                                                                    
                                                                    



# Plays the 2nd onset (the first onset would have index 0)
# Will override opts with: {start: 0.0151, finish: 0.0304}
# (these values are specific to the :loop_tabla sample and
# will vary for different samples)



# Example 37

sample :loop_tabla, onset: 1, slice: 0, num_slices: 1               
                                                                    
                                                                    
                                                                    
                                                                    



# Plays the 2nd onset. This behaves the same as not specifying
# a slice as we select the first of one slices.
# Will override opts with: {start: 0.0151, finish: 0.0304}
# (these values are specific to the :loop_tabla sample and
# will vary for different samples)



# Example 38

sample :loop_tabla, onset: 1, slice: 0, num_slices: 2               
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    



# This plays the first half of the 2nd onset.
# This is because  we split that onset into two slices and
# play just the first slice (with index 0).
# Will override opts with: {start: 0.0151, finish: 0.0227}
# (these values are specific to the :loop_tabla sample and
# will vary for different samples)



# Example 39

sample :loop_tabla, onset: 1, slice: 0, num_slices: 4               
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
sample :loop_tabla, onset: 1, slice: 0, num_slices: 4, finish: 0.5  
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
sample :loop_tabla, onset: 1, slice: 0, num_slices: 4, finish: 0.0, start: 0.5  
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                



# This plays the first quarter of the 2nd onset.
# This is because we split that onset into four slices and
# play just the first slice (with index 0).
# Will override opts with: {start: 0.0151, finish: 0.0189}
# (these values are specific to the :loop_tabla sample and
# will vary for different samples)
# Will play the first 1/8th of the 2nd onset.
# This is because we split that specific onset into 4 slices
# and then only play the first half of the first slice.
# Will override opts with: {start: 0.0151, finish: 0.017}
# (these values are specific to the :loop_tabla sample and
# will vary for different samples)
# Will play the first 1/8th of the 2nd onset backwards..
# This is because we split that specific onset into 4 slices
# and then only play from the first half of the first slice
# back to the beginning.
# Will override opts with: {start: 0.017, finish: 0.0151}
# (these values are specific to the :loop_tabla sample and
# will vary for different samples)