# 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

## Options

rate: | Rate with which to play back the sample. Higher rates mean an increase in pitch and a decrease in duration. Default is 1.
beat_stretch: | Stretch (or shrink) the sample to last for exactly the specified number of beats. Please note - this does not keep the pitch constant and is essentially the same as modifying the rate directly.
pitch_stretch: | Stretch (or shrink) the sample to last for exactly the specified number of beats. This attempts to keep the pitch constant using the `pitch:` opt. Note, it’s very likely you’ll need to experiment with the `window_size:`, `pitch_dis:` and `time_dis:` opts depending on the sample and the amount you’d like to stretch/shrink from original size.
attack: | Time to reach full volume. Default is 0.
sustain: | Time to stay at full volume. Default is to stretch to length of sample (minus attack and release times).
release: | Time (from the end of the sample) to go from full amplitude to 0. Default is 0.
start: | Position in sample as a fraction between 0 and 1 to start playback. Default is 0.
finish: | Position in sample as a fraction between 0 and 1 to end playback. Default is 1.
pan: | Stereo position of audio. -1 is left ear only, 1 is right ear only, and values in between position the sound accordingly. Default is 0.
amp: | Amplitude of playback.
pre_amp: | Amplitude multiplier which takes place immediately before any internal FX such as the low pass filter, compressor or pitch modification. Use this opt if you want to overload the compressor.
onset: | Analyse the sample with an onset detection algorithm and automatically set or override the `start:` and `finish:` opts to play the nth onset only. Allows you to treat a rhythm sample as a palette of individual drum/synth hits. If `start:` or `finish:` opts are used in addition to `onset:` then they will work within the onset rather than the whole sample. Floats are rounded to the nearest whole number.
on: | If specified and false/nil/0 will stop the sample from being played. Ensures all opts are evaluated.
slice: | Divides the sample duration evenly into `num_slices:` sections (defaults to 16) and set the `start:` and `finish:` opts to play the nth slice only. If `start:` or `finish:` opts are used in addition to `slice:` then they will work within the slice rather than the whole sample. Use the envelope opts to remove any clicks introduced if the slice boundary is in the middle of a sound. Also consider `onset:` as an alternative to `slice:`. If `onset:` is also used then the slices will be within the onset rather than the whole sample. Floats are rounded to the nearest whole number.
num_slices: | Number of slices to divide the sample into when using the `slice:` opt. Defaults to 16. Floats are rounded to the nearest whole number.
norm: | Normalise the audio (make quieter parts of the sample louder and louder parts quieter) - this is similar to the normaliser FX. This may emphasise any clicks caused by clipping.
lpf: | Cutoff value of the built-in low pass filter (lpf) in MIDI notes. Unless specified, the lpf is not added to the signal chain.
lpf_init_level: | The initial low pass filter envelope value as a MIDI note. This envelope is bypassed if no lpf env opts are specified. Default value is to match the `lpf_min:` opt.
lpf_attack_level: | The peak lpf cutoff (value of cutoff at peak of attack) as a MIDI note. Default value is to match the `lpf_decay_level:` opt.
lpf_decay_level: | The level of lpf cutoff after the decay phase as a MIDI note. Default value is to match the `lpf_sustain_level:` opt.
lpf_sustain_level: | The sustain cutoff (value of lpf cutoff at sustain time) as a MIDI note. Default value is to match the `lpf_release_level:` opt.
lpf_release_level: | The final value of the low pass filter envelope as a MIDI note. This envelope is bypassed if no lpf env opts are specified. Default value is to match the `lpf:` opt.
lpf_attack: | Attack time for lpf cutoff filter. Amount of time (in beats) for sound to reach full cutoff value. Default value is set to match amp envelope’s attack value.
lpf_decay: | Decay time for lpf cutoff filter. Amount of time (in beats) for sound to move from full cutoff value (cutoff attack level) to the cutoff sustain level. Default value is set to match amp envelope’s decay value.
lpf_sustain: | Amount of time for lpf cutoff value to remain at sustain level in beats. When -1 (the default) will auto-stretch.
lpf_release: | Amount of time (in beats) for sound to move from lpf cutoff sustain value to lpf cutoff min value. Default value is set to match amp envelope’s release value.
lpf_min: | Starting value of the lpf cutoff envelope. Default is 30.
lpf_env_curve: | Select the shape of the curve between levels in the lpf cutoff envelope. 1=linear, 2=exponential, 3=sine, 4=welch, 6=squared, 7=cubed.
hpf: | Cutoff value of the built-in high pass filter (hpf) in MIDI notes. Unless specified, the hpf is not added to the signal chain.
hpf_init_level: | The initial high pass filter envelope value as a MIDI note. This envelope is bypassed if no hpf env opts are specified. Default value is set to 130.
hpf_attack_level: | The peak hpf cutoff (value of cutoff at peak of attack) as a MIDI note. Default value is to match the `hpf_decay_level:` opt.
hpf_decay_level: | The level of hpf cutoff after the decay phase as a MIDI note. Default value is to match the `hpf_sustain_level:` opt.
hpf_sustain_level: | The sustain cutoff (value of hpf cutoff at sustain time) as a MIDI note. Default value is to match the `hpf_release_level:` opt.
hpf_release_level: | The sustain hpf cutoff (value of hpf cutoff at sustain time) as a MIDI note. Default value is to match the `hpf:` opt.
hpf_attack: | Attack time for hpf cutoff filter. Amount of time (in beats) for sound to reach full cutoff value. Default value is set to match amp envelope’s attack value.
hpf_decay: | Decay time for hpf cutoff filter. Amount of time (in beats) for sound to move from full cutoff value (cutoff attack level) to the cutoff sustain level. Default value is set to match amp envelope’s decay value.
hpf_sustain: | Amount of time for hpf cutoff value to remain at sustain level in beats. When -1 (the default) will auto-stretch.
hpf_release: | Amount of time (in beats) for sound to move from hpf cutoff sustain value to hpf cutoff min value. Default value is set to match amp envelope’s release value.
hpf_env_curve: | Select the shape of the curve between levels in the hpf cutoff envelope. 1=linear, 2=exponential, 3=sine, 4=welch, 6=squared, 7=cubed.
hpf_max: | Maximum value of the high pass filter envelope. Default is 200.
rpitch: | Rate modified pitch. Multiplies the rate by the appropriate ratio to shift up or down the specified amount in MIDI notes. Please note - this does not keep the duration and rhythmical rate constant and is essentially the same as modifying the rate directly.
pitch: | Pitch adjustment in semitones. 1 is up a semitone, 12 is up an octave, -12 is down an octave etc. Maximum upper limit of 24 (up 2 octaves). Lower limit of -72 (down 6 octaves). Decimal numbers can be used for fine tuning.
window_size: | Pitch shift-specific opt - only honoured if the `pitch:` opt is used. Pitch shift works by chopping the input into tiny slices, then playing these slices at a higher or lower rate. If we make the slices small enough and overlap them, it sounds like the original sound with the pitch changed. The window_size is the length of the slices and is measured in seconds. It needs to be around 0.2 (200ms) or greater for pitched sounds like guitar or bass, and needs to be around 0.02 (20ms) or lower for percussive sounds like drum loops. You can experiment with this to get the best sound for your input.
pitch_dis: | Pitch shift-specific opt - only honoured if the `pitch:` opt is used. Pitch dispersion - how much random variation in pitch to add. Using a low value like 0.001 can help to “soften up” the metallic sounds, especially on drum loops. To be really technical, pitch_dispersion is the maximum random deviation of the pitch from the pitch ratio (which is set by the `pitch:` opt).
time_dis: | Pitch shift-specific opt - only honoured if the `pitch:` opt is used. Time dispersion - how much random delay before playing each grain (measured in seconds). Again, low values here like 0.001 can help to soften up metallic sounds introduced by the effect. Large values are also fun as they can make soundscapes and textures from the input, although you will most likely lose the rhythm of the original. NB - This won’t have an effect if it’s larger than window_size.
compress: | Enable the compressor. This sits at the end of the internal FX chain immediately before the `amp:` opt. Therefore to drive the compressor use the `pre_amp:` opt which will amplify the signal before it hits any internal FX. The compressor compresses the dynamic range of the incoming signal. Equivalent to automatically turning the amp down when the signal gets too loud and then back up again when it’s quiet. Useful for ensuring the containing signal doesn’t overwhelm other aspects of the sound. Also a general purpose hard-knee dynamic range processor which can be tuned via the opts to both expand and compress the signal.
threshold: | Threshold value determining the break point between slope_below and slope_above. Only valid if the compressor is enabled by turning on the `compress:` opt.
slope_below: | Slope of the amplitude curve below the threshold. A value of 1 means that the output of signals with amplitude below the threshold will be unaffected. Greater values will magnify and smaller values will attenuate the signal. Only valid if the compressor is enabled by turning on the `compress:` opt.
slope_above: | Slope of the amplitude curve above the threshold. A value of 1 means that the output of signals with amplitude above the threshold will be unaffected. Greater values will magnify and smaller values will attenuate the signal. Only valid if the compressor is enabled by turning on the `compress:` opt.
clamp_time: | Time taken for the amplitude adjustments to kick in fully (in seconds). This is usually pretty small (not much more than 10 milliseconds). Also known as the time of the attack phase. Only valid if the compressor is enabled by turning on the `compress:` opt.
relax_time: | Time taken for the amplitude adjustments to be released. Usually a little longer than clamp_time. If both times are too short, you can get some (possibly unwanted) artefacts. Also known as the time of the release phase. Only valid if the compressor is enabled by turning on the `compress:` opt.
slide: | Default slide time in beats for all slide opts. Individually specified slide opts will override this value.
path: | Path of the sample to play. Typically this opt is rarely used instead of the more powerful source/filter system. However it can be useful when working with pre-made opt maps.

## 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)