# Get all sample names

``

    all_sample_names

Return a list of all the sample names available

Introduced in v2.0

# Ensure arg is valid

``

    assert  arg (anything)

Raises an exception if the argument is either nil or false.

Introduced in v2.8

## Examples

# Example 1

``

    assert true
    assert 1
    assert "foo"
    assert false

``

    # Simple assertions
    # As true is neither nil or false, this assertion passes
    # Similarly, 1 passes
    # As do string
    # This will raise an exception

# Example 2

``

    assert false, "oops"

``

    # Communicating error messages
    # This will raise an exception containing the message "oops"

# Example 3

``

    assert (1 + 1) == 2
    assert [:a, :b, :c].size == 3

``

    # More interesting assertions
    # Ensure that arithmetic is sane!
    # ensure lists can be correctly counted

# Ensure args are equal

``

    assert_equal  arg1 (anything), arg2 (anything)

Raises an exception if both arguments aren’t equal.

Introduced in v2.8

## Examples

# Example 1

``

    assert_equal 1, 1

``

    # Simple assertions

# Example 2

``

    assert_equal 1 + 1, 2
    assert_equal [:a, :b, :c].size,  3

``

    # More interesting assertions
    # Ensure that arithmetic is sane!
    # ensure lists can be correctly counted

# Example 3

``

    assert_equal 3, 5, "something is seriously wrong!"

``

    # Add messages to the exceptions

# Ensure block throws an error

``

    assert_error  class (Exception)

Runs the block and ensures that it raises the correct Exception. Useful for asserting that an Exception will be raised. You may specify the particular Exception class, which defaults to `Exception`.

Introduced in v3.0

## Examples

# Example 1

``

    assert_error do
      play 70
    end

``

    # Will throw an exception: "Assert error failed!" as the block
    # contains no errors.

# Example 2

``

    assert_error do
      1 / 0
    end

``

    # Will not throw an exception as the block contains an error.

# Example 3

``

    assert_error ZeroDivisionError do
      1 / 0
    end

``

    # Will not throw an exception as the block contains a ZeroDivisionError.

# Example 4

``

    assert_error ThreadError do
      1 / 0
    end

``

    # Will throw an exception as the block contains a ZeroDivisionError rather than
    # a ThreadError.

# Ensure arg is not valid

``

    assert_not  arg (anything)

Raises an exception if the argument is not either nil or false.

Introduced in v3.3

## Examples

# Example 1

``

    assert_not false
    assert_not nil
    assert_not 1 == 5
    assert true

``

    # Simple assertions
    # As false is either nil or false, this assertion passes
    # As nil is either nil or false, this assertion passes
    # These numbers are not equal
    # This will raise an exception

# Example 2

``

    assert_not true , "oops"

``

    # Communicating error messages
    # This will raise an exception containing the message "oops"

# Ensure args are not equal

``

    assert_not_equal  arg1 (anything), arg2 (anything)

Raises an exception if both arguments are qual.

Introduced in v3.3

## Examples

# Example 1

``

    assert_not_equal 1, 3
    assert_not_equal 1, -1
    assert_not_equal 1, :foo

``

    # Simple assertions

# Example 2

``

    assert_not_equal 3, 3, "something is seriously wrong!"

``

    # Add messages to the exceptions

# Ensure args are similar

``

    assert_similar  arg1 (anything), arg2 (anything)

Raises an exception if both arguments aren’t similar.

Currently similarity is only defined for numbers - all other types are compared for equality with assert_equal.

Useful for testing in cases where floating point imprecision stops you from being able to use `assert_equal`.

Introduced in v3.0

## Examples

# Example 1

``

    assert_similar 1, 1

``

    # Simple assertions
    #=> True

# Example 2

``

    assert_similar(4.9999999999, 5.0)

``

    # Handles floating point imprecision
    #=> True

# Asynchronous Time. Run a block at the given time(s)

``

    at  times (list), params (list)

Given a list of times, run the block once after waiting each given time. If passed an optional params list, will pass each param individually to each block call. If size of params list is smaller than the times list, the param values will act as rings (rotate through). If the block is given 1 arg, the times are fed through. If the block is given 2 args, both the times and the params are fed through. A third block arg will receive the index of the time.

Note, all code within the block is executed in its own thread. Therefore despite inheriting all thread locals such as the random stream and ticks, modifications will be isolated to the block and will not affect external code.

`at` is just-in-time scheduling using multiple isolated threads. See `time_warp` for ahead-of-time scheduling within the current thread.

Introduced in v2.1

## Examples

# Example 1

``

    at 4 do
        sample :ambi_choir
      end

``

    # play sample after waiting for 4 beats

# Example 2

``

    at [1, 2, 4] do
        play 75
      end

``

    # plays a note after waiting 1 beat,
    # then after 1 more beat,
    # then after 2 more beats (4 beats total)

# Example 3

``

    at [1, 2, 3], [75, 76, 77] do |n|
        play n
      end

``

    # plays 3 different notes

# Example 4

``

    at [1, 2, 3],
          [{:amp=>0.5}, {:amp=> 0.8}] do |p|
        sample :drum_cymbal_open, p
      end

``

    # alternate soft and loud
    # cymbal hits three times

# Example 5

``

    at [0, 1, 2] do |t|
        puts t
      end

``

    # when no params are given to at, the times are fed through to the block
    #=> prints 0, 1, then 2

# Example 6

``

    at [0, 1, 2], [:a, :b] do |t, b|
        puts [t, b]
      end

``

    #If you specify the block with 2 args, it will pass through both the time and the param
    #=> prints out [0, :a], [1, :b], then [2, :a]

# Example 7

``

    at [0, 0.5, 2] do |t, idx|
        puts [t, idx]
      end

``

    #If you specify the block with 2 args, and no param list to at, it will pass through both the time and the index
    #=> prints out [0, 0], [0.5, 1], then [2, 2]

# Example 8

``

    at [0, 0.5, 2], [:a, :b] do |t, b, idx|
        puts [t, b, idx]
      end

``

    #If you specify the block with 3 args, it will pass through the time, the param and the index
    #=> prints out [0, :a, 0], [0.5, :b, 1], then [2, :a, 2]

# Example 9

``

    puts "main: ", rand
    rand_back
    at 1 do

      puts "at:", rand
      puts "at:", rand
    end

    sleep 2
    puts "main: ", rand

``

    # at does not consume & interfere with the outer random stream
    # 0.75006103515625

    # the random stream inside the at block is separate and
    # isolated from the outer stream.
    # 0.9287109375
    # 0.1043701171875

    # value is still 0.75006103515625

# Example 10

``

    at [1, 2] do

      puts rand
      puts rand
    end

``

    # Each block run within at has its own isolated random stream:

    # first time round (after 1 beat) prints:
    # 0.9287109375
    # 0.1043701171875

    # second time round (after 2 beats) prints:
    # 0.1043701171875
    # 0.764617919921875

# Get current beat

``

    beat

Returns the beat value for the current thread/live_loop. Beats are advanced only by calls to `sleep` and `sync`. Beats are distinct from virtual time (the value obtained by calling `vt`) in that it has no notion of rate. It is just essentially a counter for sleeps. After a `sync`, the beat is overridden with the beat value from the thread which called `cue`.

Introduced in v2.10

## Example

# Example 1

``

    use_bpm 120
    puts beat
    sleep 1
    puts beat
    use_bpm 2000
    sleep 2
    puts beat

``

    #=> The initial beat does not start at 0
    #=> 109252.703125

    #=> 109253.703125
    # Changing the BPM makes no difference

    #=> 109255.703125

# Return block duration

``

    block_duration

Given a block, runs it and returns the amount of time that has passed. This time is in seconds and is not scaled to the current BPM. Any threads spawned in the block are not accounted for.

Introduced in v2.9

## Examples

# Example 1

``

    dur = block_duration do
      play 50
      sleep 1
      play 62
      sleep 2
    end

    puts dur

``

    #=> Returns 3 as 3 seconds have passed within the block

# Example 2

``

    use_bpm 120
    dur = block_duration do
      play 50
      sleep 1
      play 62
      sleep 2
    end

    puts dur

``

    #=> Returns 1.5 as 1.5 seconds have passed within the block
    #   (due to the BPM being 120)

# Determine if block contains sleep time

``

    block_slept?

Given a block, runs it and returns whether or not the block contained sleeps or syncs

Introduced in v2.9

## Examples

# Example 1

``

    slept = block_slept? do
      play 50
      sleep 1
      play 62
      sleep 2
    end

    puts slept

``

    #=> Returns true as there were sleeps in the block

# Example 2

``

    in_thread do
      sleep 1
      cue :foo
    end

    slept = block_slept? do
      sync :foo
      play 62
    end

    puts slept

``

    # trigger a cue on a different thread

    # wait for the cue before playing the note

    #=> Returns true as the block contained a sync.

# Example 3

``

    slept = block_slept? do
      play 50
      play 62
    end

    puts slept

``

    #=> Returns false as there were no sleeps in the block

# Create a ring of boolean values

``

    bools  list (array)

Create a new ring of booleans values from 1s and 0s, which can be easier to write and manipulate in a live setting.

Introduced in v2.2

## Examples

# Example 1

``

    (bools 1, 0)

``

    #=> (ring true, false)

# Example 2

``

    (bools 1, 0, true, false, nil)

``

    #=> (ring true, false, true, false, false)

# Beat time conversion

``

    bt  seconds (number)

Beat time representation. Scales the time to the current BPM. Useful for adding bpm scaling

Introduced in v2.8

## Example

# Example 1

``

    use_bpm 120
      puts bt(1)
      use_bpm 60
      puts bt(1)
      use_bpm 30
      puts bt(1)

``

    # Set the BPM to be double the default
    # 0.5
    # BPM is now default
    # 1
    # BPM is now half the default
    # 2

# Initialise or return named buffer

``

    buffer  symbol (name), number (duration)

Initialise or return a named buffer with a specific duration (defaults to 8 beats). Useful for working with the `:record` FX. If the buffer is requested with a different duration, then a new buffer will be initialised and the old one recycled.

Introduced in v3.0

## Examples

# Example 1

``

    buffer(:foo)
    b = buffer(:foo)
    puts b.duration

``

    # load a 8s buffer and name it :foo
    # return cached buffer and bind it to b
    #=> 8.0

# Example 2

``

    buffer(:foo, 16)

``

    # load a 16s buffer and name it :foo

# Example 3

``

    use_bpm 120
    buffer(:foo, 16)

``

    # load a 8s buffer and name it :foo
    # (this isn't 16s as the BPM has been
    # doubled from the default of 60)

# Example 4

``

    buffer(:foo)
    buffer(:foo, 8)
    buffer(:foo, 10)
    buffer(:foo, 10)
    buffer(:foo)
    buffer(:foo)

``

    # init a 8s buffer and name it :foo
    # return cached 8s buffer (has the same duration)
    # init a new 10s buffer and name it :foo
    # return cached 10s buffer
    # init a 8s buffer and name it :foo
    # return cached 8s buffer (has the same duration)

# Random list selection

``

    choose  list (array)

Choose an element at random from a list (array).

If no arguments are given, will return a lambda function which when called takes an argument which will be a list to be chosen from. This is useful for choosing random `onset:` vals for samples

Always returns a single element (or nil)

Introduced in v2.0

## Examples

# Example 1

``

    loop do
        play choose([60, 64, 67])
        sleep 1
        play chord(:c, :major).choose
        sleep 1
      end

``

    #=> plays one of 60, 64 or 67 at random

    #=> You can also call .choose on the list

# Example 2

``

    live_loop :foo do
      sample :loop_amen, onset: choose
      sleep 0.125
    end

``

    # Using choose for random sample onsets

    # choose a random onset value each time

# Create chord

``

    chord  tonic (symbol), name (symbol)

Creates an immutable ring of Midi note numbers when given a tonic note and a chord type. If only passed a chord type, will default the tonic to 0. See examples.

Introduced in v2.0

## Options

invert: | Apply the specified num inversions to chord. See the fn `chord_invert`.
num_octaves: | Create an arpeggio of the chord over n octaves

## Examples

# Example 1

``

    puts (chord :e, :minor)

``

    # returns a ring of midi notes - (ring 64, 67, 71)

# Example 2

``

    play (chord :e, :minor)

``

    # Play all the notes together

# Example 3

``

    play (chord :e3, :minor, invert: 0)
    play (chord :e3, :minor, invert: 1)
    play (chord :e3, :minor, invert: 2)

``

    # Chord inversions (see the fn chord_invert)
    # Play the basic :e3, :minor chord - (ring 52, 55, 59)
    # Play the first inversion of :e3, :minor - (ring 55, 59, 64)
    # Play the first inversion of :e3, :minor - (ring 59, 64, 67)

# Example 4

``

    puts (chord :minor)

``

    # You can create a chord without a tonic:
    #=> (ring 0, 3, 7)

# Example 5

``

    live_loop :arp do
      play chord(:e, :minor, num_octaves: 2).tick, release: 0.1
      sleep 0.125
    end

``

    # chords are great for arpeggiators

# Example 6

``

    (chord :C, '1')
    (chord :C, '5')
    (chord :C, '+5')
    (chord :C, 'm+5')
    (chord :C, :sus2)
    (chord :C, :sus4)
    (chord :C, '6')
    (chord :C, :m6)
    (chord :C, '7sus2')
    (chord :C, '7sus4')
    (chord :C, '7-5')
    (chord :C, 'm7-5')
    (chord :C, '7+5')
    (chord :C, 'm7+5')
    (chord :C, '9')
    (chord :C, :m9)
    (chord :C, 'm7+9')
    (chord :C, :maj9)
    (chord :C, '9sus4')
    (chord :C, '6*9')
    (chord :C, 'm6*9')
    (chord :C, '7-9')
    (chord :C, 'm7-9')
    (chord :C, '7-10')
    (chord :C, '9+5')
    (chord :C, 'm9+5')
    (chord :C, '7+5-9')
    (chord :C, 'm7+5-9')
    (chord :C, '11')
    (chord :C, :m11)
    (chord :C, :maj11)
    (chord :C, '11+')
    (chord :C, 'm11+')
    (chord :C, '13')
    (chord :C, :m13)
    (chord :C, :add2)
    (chord :C, :add4)
    (chord :C, :add9)
    (chord :C, :add11)
    (chord :C, :add13)
    (chord :C, :madd2)
    (chord :C, :madd4)
    (chord :C, :madd9)
    (chord :C, :madd11)
    (chord :C, :madd13)
    (chord :C, :major)
    (chord :C, :M)
    (chord :C, :minor)
    (chord :C, :m)
    (chord :C, :major7)
    (chord :C, :dom7)
    (chord :C, '7')
    (chord :C, :M7)
    (chord :C, :minor7)
    (chord :C, :m7)
    (chord :C, :augmented)
    (chord :C, :a)
    (chord :C, :diminished)
    (chord :C, :dim)
    (chord :C, :i)
    (chord :C, :diminished7)
    (chord :C, :dim7)
    (chord :C, :i7)

``

    # Sonic Pi supports a large range of chords
    # Notice that the more exotic ones have to be surrounded by ' quotes

# Construct chords of stacked thirds, based on scale degrees

``

    chord_degree  degree (symbol_or_number), tonic (symbol), scale (symbol), number_of_notes (number)

In music we build chords from scales. For example, a C major chord is made by taking the 1st, 3rd and 5th notes of the C major scale (C, E and G). If you do this on a piano you might notice that you play one, skip one, play one, skip one etc. If we use the same spacing and start from the second note in C major (which is a D), we get a D minor chord which is the 2nd, 4th and 6th notes in C major (D, F and A). We can move this pattern all the way up or down the scale to get different types of chords. `chord_degree` is a helper method that returns a ring of midi note numbers when given a degree (starting point in a scale) which is a symbol `:i`, `:ii`, `:iii`, `:iv`, `:v`, `:vi`, `:vii` or a number `1`-`7`. The second argument is the tonic note of the scale, the third argument is the scale type and finally the fourth argument is number of notes to stack up in the chord. If we choose 4 notes from degree `:i` of the C major scale, we take the 1st, 3rd, 5th and 7th notes of the scale to get a C major 7 chord.

Introduced in v2.1

## Options

invert: | Apply the specified num inversions to chord. See the fn `chord_invert`.

## Examples

# Example 1

``

    puts (chord_degree :i, :A3, :major)

``

    # returns a ring of midi notes - (ring 57, 61, 64, 68) - an A major 7 chord

# Example 2

``

    play (chord_degree :i, :A3, :major, 3)

``

# Example 3

``

    play (chord_degree :ii, :A3, :major, 3)

``

    # Chord ii in A major is a B minor chord

# Example 4

``

    play (chord_degree :iii, :A3, :major, 3)

``

    # Chord iii in A major is a C# minor chord

# Example 5

``

    play (chord_degree :iv, :A3, :major, 3)

``

    # Chord iv in A major is a D major chord

# Example 6

``

    play (chord_degree :i, :C4, :major, 4)

``

    # Taking four notes is the default. This gives us 7th chords - here it plays a C major 7

# Example 7

``

    play (chord_degree :i, :C4, :major, 5)

``

    # Taking five notes gives us 9th chords - here it plays a C major 9 chord

# Example 8

``

    play (chord_degree :i, :C4, :major, 3, invert: 1)

``

    # Play the first inversion of chord i in C major - (ring 64, 67, 72)

# Chord inversion

``

    chord_invert  notes (list), shift (number)

Given a set of notes, apply a number of inversions indicated by the `shift` parameter. Inversions being an increase to notes if `shift` is positive or decreasing the notes if `shift` is negative.

An inversion is simply rotating the chord and shifting the wrapped notes up or down an octave. For example, consider the chord :e3, :minor - `(ring 52, 55, 59)`. When we invert it once, we rotate the notes around to `(ring 55, 59, 52)`. However, because note 52 is wrapped round, it’s shifted up an octave (12 semitones) so the actual first inversion of the chord :e3, :minor is `(ring 55, 59, 52 + 12)` or `(ring 55, 59, 64)`.

Note that it’s also possible to directly invert chords on creation with the `invert:` opt - `(chord :e3, :minor, invert: 2)`

Introduced in v2.6

## Example

# Example 1

``

    play (chord_invert (chord :A3, "M"), 0)
    sleep 1
    play (chord_invert (chord :A3, "M"), 1)
    sleep 1
    play (chord_invert (chord :A3, "M"), 2)

``

    #No inversion     - (ring 57, 61, 64)

    #First inversion  - (ring 61, 64, 69)

    #Second inversion - (ring 64, 69, 73)

# All chord names

``

    chord_names

Returns a ring containing all chord names known to Sonic Pi

Introduced in v2.6

## Example

# Example 1

``

    puts chord_names

``

    #=>  prints a list of all the chords

# Clear all thread locals to defaults

``

    clear

All settings such as the current synth, BPM, random stream and tick values will be reset to their defaults. Consider using `reset` to reset all these values to those inherited from the parent thread.

Introduced in v2.11

## Example

# Example 1

``

    Clear wipes out the threads locals
    use_synth :blade
    use_octave 3

    puts "before"
    puts current_synth
    puts current_octave
    puts rand
    puts tick

    at do
      use_synth :tb303
      puts rand
      clear
      puts "thread"

      puts current_synth

      puts current_octave

      puts rand
      puts tick
    end

``

    #=> "before"
    #=> :blade
    #=> 3
    #=> 0.75006103515625
    #=> 0

    #=> 0.9287109375

    #=> "thread"

    # The clear reset the current synth to the default
    # of :beep. We are therefore ignoring any inherited
    # synth settings. It is as if the thread was a completely
    # new Run.
    #=> :beep

    # The current octave defaults back to 0
    #=> 0

    # The random stream defaults back to the standard
    # stream used by every new Run.
    #=> 0.75006103515625
    #=> 0

# Block level commenting

``

    comment

Does not evaluate any of the code within the block. However, any optional args passed before the block will be evaluated although they will be ignored. See `uncomment` for switching commenting off without having to remove the comment form.

Introduced in v2.0

## Example

# Example 1

``

    comment do
        play 50
        sleep 1
        play 62
      end

``

    # starting a block level comment:
    # not played
    # no sleep happens
    # not played

# Control running synth

``

    control  node (synth_node)

Control a running synth node by passing new parameters to it. A synth node represents a running synth and can be obtained by assigning the return value of a call to play or sample or by specifying a parameter to the do/end block of an FX. You may modify any of the parameters you can set when triggering the synth, sample or FX. See documentation for opt details. If the synth to control is a chord, then control will change all the notes of that chord group at once to a new target set of notes - see example. Also, you may use the on: opt to conditionally trigger the control - see the docs for the `synth` and `sample` fns for more information.

If no synth to control is specified, then the last synth triggered by the current (or parent) thread will be controlled - see example below.

Introduced in v2.0

## Examples

# Example 1

``

    my_node = play 50, release: 5, cutoff: 60
    sleep 1
    control my_node, cutoff: 70
    sleep 1
    control my_node, cutoff: 90

``

    # Basic control

    # play note 50 with release of 5 and cutoff of 60. Assign return value to variable my_node
    # Sleep for a second
    # Now modify cutoff from 60 to 70, sound is still playing
    # Sleep for another second
    # Now modify cutoff from 70 to 90, sound is still playing

# Example 2

``

    s = synth :prophet, note: :e1, cutoff: 70, cutoff_slide: 8, release: 8
    control s, cutoff: 130

``

    # Combining control with slide opts allows you to create nice transitions.

    # start synth and specify slide time for cutoff opt
    # Change the cutoff value with a control.
    # Cutoff will now slide over 8 beats from 70 to 130

# Example 3

``

    notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle

    s = synth :beep, note: :e3, sustain: 8, note_slide: 0.05
    64.times do
      control s, note: notes.tick
      sleep 0.125
    end

``

    # Use a short slide time and many controls to create a sliding melody

    # get a random ordering of a scale

    # Start our synth running with a long sustain and short note slide time

    # Keep quickly changing the note by ticking through notes repeatedly

# Example 4

``

    with_fx :bitcrusher, sample_rate: 1000, sample_rate_slide: 8 do |bc|

      sample :loop_garzul, rate: 1
      control bc, sample_rate: 5000

    end

``

    # Controlling FX

    # Start FX but also use the handy || goalposts
    # to grab a handle on the running FX. We can call
    # our handle anything we want. Here we've called it bc

    # We can use our handle bc now just like we used s in the
    # previous example to modify the FX as it runs.

# Example 5

``

    cg = play (chord :e4, :minor), sustain: 2
    sleep 1
    control cg, notes: (chord :c3, :major)

``

    # Controlling chords

    # start a chord

    # transition to new chord.
    # Each note in the original chord is mapped onto
    # the equivalent in the new chord.

# Example 6

``

    cg = play (chord :e4, :minor), sustain: 4, note_slide: 3
    sleep 1
    control cg, notes: (chord :c3, :major)

``

    # Sliding between chords

    # start a chord

    # slide to new chord.
    # Each note in the original chord is mapped onto
    # the equivalent in the new chord.

# Example 7

``

    cg = play (chord :e3, :m13), sustain: 4, note_slide: 3
    sleep 1
    control cg, notes: (chord :c3, :major)

``

    # Sliding from a larger to smaller chord

    # start a chord with 7 notes

    # slide to new chord with fewer notes (3)
    # Each note in the original chord is mapped onto
    # the equivalent in the new chord using ring-like indexing.
    # This means that the 4th note in the original chord will
    # be mapped onto the 1st note in the second chord and so-on.

# Example 8

``

    cg = play (chord :c3, :major), sustain: 4, note_slide: 3
    sleep 1
    control cg, notes: (chord :e3, :m13)

``

    # Sliding from a smaller to larger chord
    # start a chord with 3 notes

    # slide to new chord with more notes (7)
    # Each note in the original chord is mapped onto
    # the equivalent in the new chord.
    # This means that the 4th note in the new chord
    # will not sound as there is no 4th note in the
    # original chord.

# Example 9

``

    s = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 8
    sleep 1
    control s, cutoff: 130
    sleep 3
    control s, cutoff_slide: 1

``

    # Changing the slide rate

    # Start a synth playing with a long cutoff slide
    # wait a beat
    # change the cutoff so it starts sliding slowly
    # wait for 3 beats
    # Change the cutoff_slide - the cutoff now slides more quickly to 130
    # it will now take 1 beat to slide from its *current* value
    # (somewhere between 70 and 130) to 130

# Example 10

``

    synth :prophet, note: :e1, release: 8
    sleep 1
    16.times do
      control note: (octs :e1, 3).tick
      sleep 0.125
    end

``

    # Controlling the last triggered synth

    # Every time a synth is triggered, Sonic Pi automatically remembers the node

    # This means we don't need to use an explicit variable to control the synth
    # we last triggered.

# Example 11

``

    synth :beep, release: 4
    sleep 0.1
    control note: :e5
    sleep 0.5
    synth :dsaw, release: 4
    sleep 0.1
    control note: :e4

``

    # Controlling multiple synths without variables

    # Trigger a beep synth

    # Control last triggered synth (:beep)

    # Next, trigger a dsaw synth

    # Control last triggered synth (:dsaw)

# Cue other threads

``

    cue  cue_id (symbol)

Send a heartbeat synchronisation message containing the (virtual) timestamp of the current thread. Useful for syncing up external threads via the `sync` fn. Any opts which are passed are given to the thread which syncs on the `cue_id`. The values of the opts must be immutable. Currently numbers, symbols, booleans, nil and frozen strings, or vectors/rings/frozen arrays/maps of immutable values are supported.

Introduced in v2.0

## Options

your_key: | Your value
another_key: | Another value
key: | All these opts are passed through to the thread which syncs

## Examples

# Example 1

``

    in_thread do
        sync :foo
        sample :ambi_lunar_land
      end

      sleep 5

      cue :foo

``

    # this parks the current thread waiting for a foo cue message to be received.

    # We send a cue message from the main thread.
    # This then unblocks the thread above and we then hear the sample

# Example 2

``

    in_thread do
        loop do
          cue :tick
          sleep 0.5
        end
      end

      loop do
        sync :tick
        sample :drum_heavy_kick
      end

``

    # Start a metronome thread
    # Loop forever:
    # sending tick heartbeat messages
    # and sleeping for 0.5 beats between ticks

    # We can now play sounds using the metronome.
    # In the main thread, just loop
    # waiting for :tick cue messages
    # after which play the drum kick sample

# Example 3

``

    in_thread do
        loop do
          cue [:foo, :bar, :baz].choose
          sleep 0.5
        end
      end

      in_thread do
        loop do
          sync :foo
          sample :elec_beep
        end
      end

      in_thread do
        loop do
          sync :bar
          sample :elec_flip
        end
      end

      in_thread do
        loop do
          sync :baz
          sample :elec_blup
        end
      end

``

    # Start a metronome thread
    # Loop forever:
    # sending one of three tick heartbeat messages randomly
    # and sleeping for 0.5 beats between ticks

    # We can now play sounds using the metronome:

    # In the main thread, just loop
    # waiting for :foo cue messages
    # after which play the elec beep sample

    # In the main thread, just loop
    # waiting for :bar cue messages
    # after which play the elec flip sample

    # In the main thread, just loop
    # waiting for :baz cue messages
    # after which play the elec blup sample

# Example 4

``

    in_thread do
        loop do
          cue :tick, foo: 64
          sleep 0.5
        end
      end

      loop do
        values = sync :tick
        play values[:foo]
      end

``

    # sending tick heartbeat messages with a value :foo

    # The value for :foo can now be used in synced threads

    # play the note value from :foo

# Get current arg checking status

``

    current_arg_checks

Returns the current arg checking setting (`true` or `false`).

This can be set via the fns `use_arg_checks` and `with_arg_checks`.

Introduced in v2.0

## Example

# Example 1

``

    puts current_arg_checks

``

    # Print out the current arg check setting

# Duration of current beat

``

    current_beat_duration

Get the duration of the current beat in seconds. This is the actual length of time which will elapse with `sleep 1`.

Affected by calls to `use_bpm`, `with_bpm`, `use_sample_bpm` and `with_sample_bpm`.

Introduced in v2.6

## Example

# Example 1

``

    use_bpm 60
      puts current_beat_duration

      use_bpm 120
      puts current_beat_duration

``

    #=> 1

    #=> 0.5

# Get current tempo

``

    current_bpm

Returns the current tempo as a bpm value. If the thread is in :link bpm mode, this will return the latest bpm value of the shared Link network metronome (note that this value may change after reading if the Link bpm isn’t static).

To know if this thread is in :link or standard bpm mode see `current_bpm_mode`.

This can be set via the fns `use_bpm`, `with_bpm`, `use_sample_bpm` and `with_sample_bpm`.

Introduced in v2.0

## Example

# Example 1

``

    use_bpm 60
      puts current_bpm_mode
      use_bpm 70
      puts current_bpm_mode
      use_bpm :link
      puts current_bpm_mode

``

    # => 60

    # => 70

    # => 120 (or whatever the current Link BPM value is)

# Get current tempo mode

``

    current_bpm_mode

Returns the current tempo mode - either a bpm value or :link.

To know the current BPM value when this thread is in :link mode see `current_bpm`.

This can be set via the fns `use_bpm`, `with_bpm`, `use_sample_bpm` and `with_sample_bpm`.

Introduced in v4.0

## Example

# Example 1

``

    use_bpm 60
      puts current_bpm_mode
      use_bpm 70
      puts current_bpm_mode
      use_bpm :link
      puts current_bpm_mode

``

    # => 60

    # => 70

    # => :link

# Get current cent shift

``

    current_cent_tuning

Returns the cent shift value.

This can be set via the fns `use_cent_tuning` and `with_cent_tuning`.

Introduced in v2.9

## Example

# Example 1

``

    puts current_cent_tuning

``

    # Print out the current cent shift

# Get current debug status

``

    current_debug

Returns the current debug setting (`true` or `false`).

This can be set via the fns `use_debug` and `with_debug`.

Introduced in v2.0

## Example

# Example 1

``

    puts current_debug

``

    # Print out the current debug setting

# Get current MIDI defaults

``

    current_midi_defaults

Returns the current MIDI defaults. This is a map of opt names to values

This can be set via the fns `use_midi_defaults`, `with_midi_defaults`, `use_merged_midi_defaults` and `with_merged_midi_defaults`.

Introduced in v3.0

## Example

# Example 1

``

    use_midi_defaults channel: 1, port: "foo"
    midi_note_on :e1
    current_midi_defaults

``

    # Sends MIDI :e1 note on to channel 1 on port "foo"
    #=> Prints {channel: 1, port: "foo"}

# Get current octave shift

``

    current_octave

Returns the octave shift value.

This can be set via the fns `use_octave` and `with_octave`.

Introduced in v2.9

## Example

# Example 1

``

    puts current_octave

``

    # Print out the current octave shift

# Get current random seed

``

    current_random_seed

Returns the current random seed.

This can be set via the fns `use_random_seed` and `with_random_seed`. It is incremented every time you use the random number generator via fns such as `choose` and `rand`.

Introduced in v2.10

## Examples

# Example 1

``

    puts current_random_seed

``

    # Print out the current random seed

# Example 2

``

    puts rand
    puts rand
    a = current_random_seed
    puts rand
    puts rand
    use_random_seed a

    puts rand
    puts rand

``

    # Resetting the seed back to a known place
    #=>  0.75006103515625
    #=>  0.733917236328125
    # Grab the current seed
    #=> 0.464202880859375
    #=> 0.24249267578125
    # Restore the seed
    # we'll now get the same random values:
    #=> 0.464202880859375
    #=> 0.24249267578125

# Get current random source

``

    current_random_source

Returns the source of the current random number generator (what kind of noise is generating the random numbers).

This can be set via the fns `use_random_source` and `with_random_source`. Each source will provide a different pattern of random numbers.

Introduced in v4.0

## Examples

# Example 1

``

    puts current_random_source

``

    # Print out the current random source

# Example 2

``

    use_random_source :white
    puts rand
    puts rand
    a = current_random_source
    use_random_source :perlin
    puts rand
    puts rand
    use_random_source a

    puts rand
    puts rand

``

    # Use white noise as the distribution (default)
    # => 0.75006103515625
    # => 0.733917236328125
    # Grab the current random number source (:white)
    # Use perlin noise as the distribution
    # => 0.58526611328125
    # => 0.597015380859375
    # Restore the previous random number source (:white)
    # The numbers will again be generated from a white noise distribution
    # => 0.10821533203125
    # => 0.54010009765625

# Get current sample defaults

``

    current_sample_defaults

Returns the current sample defaults. This is a map of synth arg names to either values or functions.

This can be set via the fns `use_sample_defaults`, `with_sample_defaults`, `use_merged_sample_defaults` and `with_merged_sample_defaults`.

Introduced in v2.5

## Example

# Example 1

``

    use_sample_defaults amp: 0.5, cutoff: 80
    sample :loop_amen
    puts current_sample_defaults

``

    # Plays amen break with amp 0.5 and cutoff 80
    #=> Prints {amp: 0.5, cutoff: 80}

# Get current sched ahead time

``

    current_sched_ahead_time

Returns the current schedule ahead time.

This can be set via the fn `set_sched_ahead_time!`.

Introduced in v2.0

## Example

# Example 1

``

    set_sched_ahead_time! 0.5
    puts current_sched_ahead_time

``

    # Prints 0.5

# Get current synth

``

    current_synth

Returns the current synth name.

This can be set via the fns `use_synth` and `with_synth`.

Introduced in v2.0

## Example

# Example 1

``

    puts current_synth

``

    # Print out the current synth name

# Get current synth defaults

``

    current_synth_defaults

Returns the current synth defaults. This is a map of synth arg names to values.

This can be set via the fns `use_synth_defaults`, `with_synth_defaults`, `use_merged_synth_defaults` and `with_merged_synth_defaults`.

Introduced in v2.0

## Example

# Example 1

``

    use_synth_defaults amp: 0.5, cutoff: 80
    play 50
    puts current_synth_defaults

``

    # Plays note 50 with amp 0.5 and cutoff 80
    #=> Prints {amp: 0.5, cutoff: 80}

# Get current (logically quantized) time

``

    current_time

Returns the current logical time. This is a ‘wall-clock’ time which should typically be pretty similar to Time.now but quantised to a nearby sleep point in the thread. May be quite different to Time.now within a time_warp!

Unlike `Time.now`, Multiple calls to `current_time` with no interleaved calls to `sleep` or `sync` will return the same value.

Introduced in v3.0

## Examples

# Example 1

``

    puts current_time

``

    # 2017-03-19 23:37:57.324 +0000

# Example 2

``

    puts "A", Time.now.to_f
    puts "B", current_time.to_f
    puts "C", Time.now.to_f
    puts "D", current_time.to_f
    puts "E", current_time.to_f

``

    # The difference between current_time and Time.now
    # See that Time.now is continuous and current_time is discrete
    #
    # {run: 19, time: 0.0}
    # ├─ "A" 1489966042.761211
    # ├─ "B" 1489966042.760181
    # ├─ "C" 1489966042.761235
    # ├─ "D" 1489966042.760181
    # └─ "E" 1489966042.760181

# Get current transposition

``

    current_transpose

Returns the current transpose value.

This can be set via the fns `use_transpose` and `with_transpose`.

Introduced in v2.0

## Example

# Example 1

``

    puts current_transpose

``

    # Print out the current transpose value

# Get current volume

``

    current_volume

Returns the current volume.

This can be set via the fn `set_volume!`.

Introduced in v2.0

## Examples

# Example 1

``

    puts current_volume

``

    # Print out the current volume

# Example 2

``

    set_volume! 2
    puts current_volume

``

    #=> 2

# Decrement

``

    dec  n (number)

Decrement a number by `1`. Equivalent to `n - 1`

Introduced in v2.1

## Examples

# Example 1

``

    dec 1

``

    # returns 0

# Example 2

``

    dec -1

``

    # returns -2

# Define a new function

``

    define  name (symbol)

Allows you to group a bunch of code and give it your own name for future re-use. Functions are very useful for structuring your code. They are also the gateway into live coding as you may redefine a function whilst a thread is calling it, and the next time the thread calls your function, it will use the latest definition.

Note, it is not recommended to start a function name with a capital letter if it takes no parameters.

Introduced in v2.0

## Examples

# Example 1

``

      define :foo do
        play 50
        sleep 1
      end

      foo

      3.times do
        foo
      end

``

    # Define a new function called foo

    # Call foo on its own

    # You can use foo anywhere you would use normal code.
    # For example, in a block:

# Example 2

``

      define :play2 do |x|
        play x, release: 2
      end

      play2 42

``

    # Define a new function called play2, taking one parameter

    # Call play2, passing in a value for the parameter

# Define a named value only once

``

    defonce  name (symbol)

Allows you to assign the result of some code to a name, with the property that the code will only execute once - therefore stopping re-definitions. This is useful for defining values that you use in your compositions but you don’t want to reset every time you press run. You may force the block to execute again regardless of whether or not it has executed once already by using the override option (see examples).

Introduced in v2.0

## Options

override: | If set to true, re-definitions are allowed and this acts like define

## Examples

# Example 1

``

    defonce :foo do
        sleep 1

        puts "hello"
        10
      end

      puts foo

      puts foo

      defonce :foo do
        puts "you can't redefine me"
        15
      end

      puts foo

      3.times do
        play foo
      end

``

    # Define a new function called foo
    # Sleep for a beat in the function definition. Note that this amount
    # of time in seconds will depend on the current BPM of the live_loop
    # or thread calling this function.
    # Print hello
    # Return a value of 10

    # Call foo on its own
    # The run sleeps for a beat and prints "hello" before returning 10

    # Try it again:
    # This time the run doesn't sleep or print anything out. However, 10 is still returned.

    # Try redefining foo

    # We still don't see any printing or sleeping, and the result is still 10

    # You can use foo anywhere you would use normal code.
    # For example, in a block:

    # play 10

# Example 2

``

    defonce :bar do
        50
      end

      play bar

      defonce :bar do
        70
      end

      play bar

      defonce :bar, override: true do
        80
      end

      play bar

``

    # plays 50

    # This redefinition doesn't work due to the behaviour of defonce

    # Still plays 50

    # Force definition to take place with override option

    # plays 80

# Convert a degree into a note

``

    degree  degree (symbol_or_number), tonic (symbol), scale (symbol)

For a given scale and tonic it takes a symbol/string/number and resolves it to a midi note. The degree can be either a decimal number or a roman numeral (if it’s a string or symbol), and may optionally be prefixed an augmentation (`a`/`d` for an augmented/diminished interval, `aa`/`dd` for double augmented/diminished or `p` for a perfect (unchanged) interval).

Introduced in v2.1

## Examples

# Example 1

``

    play degree(:iii, :D3, :major)
    play degree(3, :C3, :minor)
    play degree('d5', :B3, :major)

``

    # major third up from :D3
    # minor third up from :C3
    # diminished fifth up from :B3

# Example 2

``

    chrd = []
    [:i, :iii, :v, :dvii, :dix, :Axi, :xiii].each do |d|
      chrd.append (degree d, :Fs, :major)
    end
    play chrd

``

    # for each degree in the chord
    # add the corresponding note

    # play an F# 13+11-9 chord, using roman numeral symbols

# Example 3

``

    chrd = []
    ['1', '3', '5', 'd7', 'd9', 'A11', '13'].each do |d|
      chrd.append (degree d, :Fs, :major)
    end
    play chrd

``

    # the same chord as above, but using decimal number strings

# Squash and repeat time

``

    density  d (density)

Runs the block `d` times with the bpm for the block also multiplied by `d`. Great for repeating sections a number of times faster yet keeping within a fixed time. If `d` is less than 1, then time will be stretched accordingly and the block will take longer to complete.

Introduced in v2.3

## Examples

# Example 1

``

    use_bpm 60

      density 2 do

        sample :bd_haus
        sleep 0.5
      end

``

    # Set the BPM to 60

    # BPM for block is now 120
    # block is called 2.times
    # sample is played twice
    # sleep is 0.25s

# Example 2

``

    density 2 do |idx|
        puts idx
        sleep 0.5
      end

``

    # You may also pass a param to the block similar to n.times
    # prints out 0, 1
    # sleep is 0.25s

# Example 3

``

    density 0.5 do

        play 80, release: 1
        sleep 0.5
      end

``

    # Specifying a density val of < 1 will stretch out time
    # A density of 0.5 will double the length of the block's
    # execution time.
    # plays note 80 with 2s release
    # sleep is 1s

# Random dice throw

``

    dice  num_sides (number)

Throws a dice with the specified num_sides (defaults to `6`) and returns the score as a number between `1` and `num_sides`.

Introduced in v2.0

## Examples

# Example 1

``

    dice

``

    # will return a number between 1 and 6 inclusively
    # (with an even probability distribution).

# Example 2

``

    dice 3

``

    # will return a number between 1 and 3 inclusively

# Create a ring of successive doubles

``

    doubles  start (number), num_doubles (int)

Create a ring containing the results of successive doubling of the `start` value. If `num_doubles` is negative, will return a ring of `halves`.

Introduced in v2.10

## Examples

# Example 1

``

    (doubles 60, 2)

``

    #=> (ring 60, 120)

# Example 2

``

    (doubles 1.5, 3)

``

    #=> (ring 1.5, 3, 6)

# Example 3

``

    (doubles 1.5, 5)

``

    #=> (ring 1.5, 3, 6, 12, 24)

# Example 4

``

    (doubles 100, -4)

``

    #=> (ring 100, 50, 25, 12.5)

# Evaluate the contents of the file inline in the current thread like a function.

``

    eval_file  filename (path)

Reads the full contents of the file with `path` and executes within the current thread like a function call.

Introduced in v3.2

## Example

# Example 1

``

    eval_file "~/path/to/sonic-pi-code.rb"

``

    #=> will run the contents of this file

# Factor test

``

    factor?  val (number), factor (number)

Test to see if factor is indeed a factor of `val`. In other words, can `val` be divided exactly by factor.

Introduced in v2.1

## Examples

# Example 1

``

    factor?(10, 2)

``

    # true - 10 is a multiple of 2 (2 * 5 = 10)

# Example 2

``

    factor?(11, 2)

``

    #false - 11 is not a multiple of 2

# Example 3

``

    factor?(2, 0.5)

``

    #true - 2 is a multiple of 0.5 (0.5 * 4 = 2)

# Get all FX names

``

    fx_names

Return a list of all the FX available

Introduced in v2.10

# Get information from the Time State

``

    get  time_state_key (default)

Retrieve information from Time State set prior to the current time from either the current or any other thread. If called multiple times will always return the same value unless a call to `sleep`, `sync`, `set` or `cue` is interleaved. Also, calls to `get` will always return the same value across Runs for deterministic behaviour - which means you may safely use it in your compositions for repeatable music. If no value is stored with the relevant key, will return `nil`.

May be used within a `time_warp` to retrieve past events. If in a time warp, `get` can not be called from a future position. Does not advance time.

Introduced in v3.0

## Examples

# Example 1

``

    get :foo

``

    #=> returns the last value set as :foo, or nil

# Example 2

``

    set :foo, 3
    get[:foo]

``

    #=> returns 3

# Example 3

``

    in_thread do
      set :foo, 3
    end

    in_thread do
      puts get[:foo]
    end

``

    #=> always returns 3 (no race conditions here!)

# Create a ring of successive halves

``

    halves  start (number), num_halves (int)

Create a ring containing the results of successive halving of the `start` value. If `num_halves` is negative, will return a ring of `doubles`.

Introduced in v2.10

## Examples

# Example 1

``

    (halves 60, 2)

``

    #=> (ring 60, 30)

# Example 2

``

    (halves 120, 3)

``

    #=> (ring 120, 60, 30)

# Example 3

``

    (halves 120, 5)

``

    #=> (ring 120, 60, 30, 15, 7.5)

# Example 4

``

    (halves 30, -5)

``

    #=> (ring 30, 60, 120, 240, 480)

# Hz to MIDI conversion

``

    hz_to_midi  freq (number)

Convert a frequency in hz to a midi note. Note that the result isn’t an integer and there is a potential for some very minor rounding errors.

Introduced in v2.0

## Example

# Example 1

``

    hz_to_midi(261.63)

``

    #=> 60.0003

# Run code block at the same time

``

    in_thread

Execute a given block (between `do` … `end`) in a new thread. Use for playing multiple ‘parts’ at once. Each new thread created inherits all the use/with defaults of the parent thread such as the time, current synth, bpm, default synth args, etc. Despite inheriting defaults from the parent thread, any modifications of the defaults in the new thread will not affect the parent thread. Threads may be named with the `name:` optional arg. Named threads will print their name in the logging pane when they print their activity. If you attempt to create a new named thread with a name that is already in use by another executing thread, no new thread will be created.

It is possible to delay the initial trigger of the thread on creation with both the `delay:` and `sync:` opts. See their respective docstrings. If both `delay:` and `sync:` are specified, on initial thread creation first the delay will be honoured and then the sync.

Introduced in v2.0

## Options

name: | Make this thread a named thread with name. If a thread with this name already exists, a new thread will not be created.
delay: | Initial delay in beats before the thread starts. Default is 0.
sync: | Initial sync symbol. Will sync with this symbol before the thread starts.
sync_bpm: | Initial sync symbol. Will sync with this symbol before the thread starts. Thread will also inherit the BPM of the thread which cued the symbol.

## Examples

# Example 1

``

    loop do
        play 50
        sleep 1
      end

      loop do
        play 55
        sleep 0.5
      end

``

    # If you write two loops one after another like this,
    # then only the first loop will execute as the loop acts
    # like a trap not letting the flow of control out

    # This code is never executed.

# Example 2

``

      in_thread do

        loop do

          play 50
          sleep 1
        end
      end

      loop do
        play 55
        sleep 0.5
      end

``

    # In order to play two loops at the same time, the first loops need to
    # be in a thread (note that it's probably more idiomatic to use live_loop
    # when performing):

    # By wrapping our loop in an in_thread block, we split the
    # control flow into two parts. One flows into the loop (a) and
    # the other part flows immediately after the in_thread block (b).
    # both parts of the control flow execute at exactly the same time.

    # (a)

    # (a)

    # (b)

    # This loop is executed thanks to the thread above

# Example 3

``

    use_bpm 120
      use_synth :dsaw

      in_thread do
        play 50
        use_synth :fm
        sleep 1
        play 38
      end

      play 62
      sleep 2
      play 67

``

    # Set the bpm to be double rate
    # Set the current synth to be :dsaw

    # Create a new thread
    # Play note 50 at time 0
    # Switch to fm synth (only affects this thread)
    # sleep for 0.5 seconds (as we're double rate)
    # Play note 38 at time 0.5

    # Play note 62 at time 0 (with dsaw synth)
    # sleep 1s
    # Play note 67 at time 1s (also with dsaw synth)

# Example 4

``

    in_thread(name: :foo) do
        loop do
          sample :drum_bass_hard
          sleep 1
        end
      end

      in_thread(name: :foo) do
        loop do
          sample :elec_chime
          sleep 0.5
        end
      end

``

    # Here we've created a named thread

    # This thread isn't created as the name is
    # the same as the previous thread which is
    # still executing.

# Example 5

``

      define :foo do
        play 50
        sleep 1
      end

      in_thread(name: :main) do
        loop do
          foo
        end
      end

``

    # Named threads work well with functions for live coding:
    # Create a function foo
    # which does something simple
    # and sleeps for some time

    # Create a named thread
    # which loops forever
    # calling our function

    # We are now free to modify the contents of :foo and re-run the entire buffer.
    # We'll hear the effect immediately without having to stop and re-start the code.
    # This is because our fn has been redefined, (which our thread will pick up) and
    # due to the thread being named, the second re-run will not create a new similarly
    # named thread. This is a nice pattern for live coding and is the basis of live_loop.

# Example 6

``

      in_thread delay: 1 do
        sample :ambi_lunar_land
      end

      play 80

``

    #Delaying the start of a thread

    # this sample is not triggered at time 0 but after 1 beat

    # Note 80 is played at time 0

# Increment

``

    inc  n (number)

Increment a number by `1`. Equivalent to `n + 1`

Introduced in v2.1

## Examples

# Example 1

``

    inc 1

``

    # returns 2

# Example 2

``

    inc -1

``

    # returns 0

# Kill synth

``

    kill  node (synth_node)

Kill a running synth sound or sample. In order to kill a sound, you need to have stored a reference to it in a variable.

Introduced in v2.0

## Examples

# Example 1

``

    foo = play 50, release: 4
    sleep 1

    kill foo

``

    # store a reference to a running synth in a variable called foo:

    # foo is still playing, but we can kill it early:

# Example 2

``

    bar = sample :loop_amen
    sleep 0.5
    kill bar

``

# Knit a sequence of repeated values

``

    knit  value (anything), count (number)

Knits a series of value, count pairs to create a ring buffer where each value is repeated count times.

Introduced in v2.2

## Examples

# Example 1

``

    (knit 1, 5)

``

    #=> (ring 1, 1, 1, 1, 1)

# Example 2

``

    (knit :e2, 2, :c2, 3)

``

    #=> (ring :e2, :e2, :c2, :c2, :c2)

# Create a ring buffer representing a straight line

``

    line  start (number), finish (number)

Create a ring buffer representing a straight line between start and finish of steps elements. Steps defaults to `4`. Indexes wrap around positively and negatively. Similar to `range`.

Introduced in v2.5

## Options

steps: | number of slices or segments along the line
inclusive: | boolean value representing whether or not to include finish value in line

## Examples

# Example 1

``

    (line 0, 4, steps: 4)

``

    #=> (ring 0.0, 1.0, 2.0, 3.0)

# Example 2

``

    (line 5, 0, steps: 5)

``

    #=> (ring 5.0, 4.0, 3.0, 2.0, 1.0)

# Example 3

``

    (line 0, 3, inclusive: true)

``

    #=> (ring 0.0, 1.0, 2.0, 3.0)

# Use Ableton Link network metronome with automatic phase syncing.

``

    link  quantum (number), phase (number)

By default link waits for the start of the next bar of the shared network metronome link. You can choose how many beats there are in a bar by setting the quantum option and/or which beat to wait for by setting the phase option.

By default, the phase to sync on is 0 and the quantum (max number of beats) is 4.

Also switches BPM to :link mode so there is no explicit need to call use_bpm :link. The time and beat set to match the network Link metronome.

This function will block the current thread until the next matching phase as if `sleep` had been called with the exact sleep time

If the quantum is 4 (the default) this suggests there are 4 beats in each bar. If the phase is set to 0 (also the default) this means that calling link will sleep until the very start of the next bar before continuing.

This can be used to sync multiple instances of Sonic Pi running on different computers connected to the same network (via wifi or ethernet). It can also be used to share and coordinate time with other apps and devices. For a full list of link-compatible apps and devices see: https://www.ableton.com/en/link/products/

For other related link functions see link_sync, use_bpm :link, set_link_bpm!

Introduced in v4.0

## Examples

# Example 1

``

    use_bpm 120
    link

    puts current_bpm

``

    # bpm is at 120
    # wait for the start of the next bar before continuing
    # (where each bar has 4 beats)
    #=> :link (not 120)

# Example 2

``

    link 8

``

    # wait for the start of the next bar
    # (where each bar has 8 beats)

# Example 3

``

    link 7, 2

``

    # wait for the 2nd beat of the next bar
    # (where each bar has 7 beats)

# Use Ableton Link network metronome with automatic session and phase syncing.

``

    link_sync  quantum (number), phase (number)

Similar to link except it also waits for the link session to be playing. If it is, then it behaves identially to link. If the session is not playing, then link_sync will first wait until the session has started before then continuing as if just link had been called.

See link for further details and usage.

Introduced in v4.0

## Example

# Example 1

``

``

# A named audio stream live from your soundcard

``

    live_audio  name (symbol)

Create a named synthesiser which works similar to `play`, `sample` or `synth`. Rather than synthesising the sound mathematically or playing back recorded audio, it streams audio live from your sound card.

However, unlike `play`, `sample` and `synth`, which allow multiple similar synths to play at the same time (i.e. a chord) only one `live_audio` synth of a given name may exist in the system at any one time. This is similar to `live_loop` where only one live loop of each name may exist at any one time. See examples for further information.

An additional difference is that `live_audio` will create an infinitely long synth rather than be timed to an envelope like the standard `synth` and `sample` synths. This is particularly suitable for working with continuous incoming audio streams where the source of the audio is unknown (for example, it may be a guitar, an analog synth or an electronic violin). If the source is continuous, then it may not be suited to being stitched together by successive enveloped calls to something like: `synth :sound_in, attack: 0, sustain: 4, release: 0`. If we were to `live_loop` this with a `sleep 4` to match the sustain duration, we would get something that emulated a continuous stream, but for certain inputs you’ll hear clicking at the seams between each successive call to `synth` where the final part of the audio signal from the previous synth doesn’t precisely match up with the start of the signal in the next synth due to very minor timing differences.

Another important feature of `live_audio` is that it will automatically move an existing `live_audio` synth into the current FX context. This means you can live code the FX chain around the live stream and it will update automatically. See examples.

To stop a `live_audio` synth, use the `:stop` arg: `live_audio :foo, :stop`. .

Introduced in v3.0

## Options

input: | The audio card input to read audio from.
stereo: | If set to truthy value (true, 1) will read from two consecutive audio card inputs.

## Examples

# Example 1

``

    live_audio :foo

``

    # Basic usage
    # Play whatever audio is coming into the sound card on input 1

# Example 2

``

    live_audio :foo, input: 3

``

    # Specify an input
    # Play whatever audio is coming into the sound card on input 3

# Example 3

``

    live_audio :foo, input: 3, stereo: true

``

    # Work with stereo input
    # Play whatever audio is coming into the sound card on inputs 3 and 4
    # as a stereo stream

# Example 4

``

    live_audio :guitar

    sleep 2

    with_fx :reverb do
      live_audio :guitar
    end

    sleep 2

    live_audio :guitar

``

    # Switching audio contexts (i.e. changing FX)
    # Play whatever audio is coming into the sound card on input 1

    # Wait for 2 seconds then...

    # Add reverb to the audio from input 1

    # Wait for another 2 seconds then...

    # Remove the reverb from input 1

# Example 5

``

    live_loop :foo do
      with_fx [:reverb, :distortion, :echo].choose do
        live_audio :voice
      end
      sleep 8
    end

``

    # Working with live_loops

    # chooses a new FX each time round the live loop
    # the audio stream from input 1 will be moved to the
    # new FX and the old FX will complete and finish as normal.

# Example 6

``

    live_audio :foo
    live_audio :bar, input: 2

    sleep 3

    live_audio :foo, :stop

``

    # Stopping

    #=> start playing audio from input 1
    #=> start playing audio from input 2

    #=> wait for 3s...

    #=> stop playing audio from input 1
    #=> (live_audio :bar is still playing)

# A loop for live coding

``

    live_loop  name (symbol)

Loop the do/end block forever. However, unlike a basic loop, a live_loop has two special properties. Firstly it runs in a thread - so you can have any number of live loops running at the same time (concurrently). Secondly, you can change the behaviour of a live loop whilst it is still running without needing to stop it. Live loops are therefore the secret to live coding with Sonic Pi.

As live loops are excecuted within a named in_thread, they behave similarly. See the in_thread documentation for all the details. However, it’s worth mentioning a few important points here. Firstly, only one live loop with a given name can run at any one time. Therefore, if you define two or more `live_loop`s called `:foo` only one will be running. Another important aspect of `live_loop`s is that they manage their own thread locals set with the `use_*` and `with_*` fns. This means that each `live_loop` can have its own separate default synth, BPM and sample defaults. When a `live_loop` is first created, it inherits the thread locals from the parent thread, but once it has started, the only way to change them is by re-defining the do/end body of the `live_loop`. See the examples below for details. Finally, as mentioned above, provided their names are different, you may have many `live_loop`s executing at once.

A typical way of live coding with live loops is to define a number of them in a buffer, hit Run to start them and then to modify their do/end blocks and then hit Run again. This will not create any more thread, but instead just modify the behaviour of the existing threads. The changes will not happen immediately. Instead, they will only happen the next time round the loop. This is because the behaviour of each live loop is implemented with a standard function. When a live loop is updated, the function definition is also updated. Each time round the live loop, the function is called, so the new behviour is only observed next time round the loop.

Also sends a `cue` with the same name each time the `live_loop` repeats. This may be used to `sync` with other threads and `live_loop`s.

If the `live_loop` block is given a parameter, this is given the result of the last run of the loop (with initial value either being `0` or an init arg). This allows you to ‘thread’ values across loops.

Finally, it is possible to delay the initial trigger of the live_loop on creation with both the `delay:` and `sync:` opts. See their respective docstrings. If both `delay:` and `sync:` are specified, on initial live_loop creation first the delay will be honoured and then the sync.

Introduced in v2.1

## Options

init: | initial value for optional block arg
auto_cue: | enable or disable automatic cue (default is true)
delay: | Initial delay in beats before the live_loop starts. Default is 0.
sync: | Initial sync symbol. Will sync with this symbol before the live_loop starts.
sync_bpm: | Initial sync symbol. Will sync with this symbol before the live_loop starts. Live loop will also inherit the BPM of the thread which cued the symbol.
seed: | override initial random generator seed before starting loop.

## Examples

# Example 1

``

    live_loop :ping do
      sample :elec_ping
      sleep 1
    end

``

    # Define and start a simple live loop

    # Create a live loop called :ping
    # This live loops plays the :elec_ping sample
    # Then sleeps for 1 beat before repeating

# Example 2

``

    live_loop :ping do
      sample :elec_ping

    end

``

    # Every live loop must sleep or sync

    # Create a live loop called :ping
    # This live loops plays the :elec_ping sample
    # However, because the do/end lock of the live loop does not
    # contain any calls to sleep or sync, the live loop stops at
    # the end of the first loop with a 'Did not sleep' error.

# Example 3

``

    live_loop :foo do
      play 70
      sleep 1
    end

    live_loop :bar do
      sample :bd_haus
      sleep 0.5
    end

``

    # Multiple live loops will play at the same time
    # Start a live loop called :foo

    # Start another live loop called :bar
    # Both :foo and :bar will be playing
    # at the same time.

# Example 4

``

    use_bpm 30
    live_loop :foo do
      play 70
      sleep 1
    end

``

    # Live loops inherit external use_* thread locals

    # live loop :foo now has a BPM of 30
    # This sleep will be for 2 seconds

# Example 5

``

    live_loop :foo do
      use_bpm 30
      play 70
      sleep 1
    end

    live_loop :bar do
      use_bpm 120
      play 82
      sleep 1
    end

``

    # Live loops can have their own thread locals

    # Set the BPM of live loop :foo to 30

    # This sleep will be for 2 seconds

    # Set the BPM of live loop :bar to 120

    # This sleep will be for 0.5 seconds

# Example 6

``

    live_loop :foo do |a|
      puts a
      sleep 1
      a += 1
    end

``

    # Live loops can pass values between iterations
    # pass a param (a) to the block (inits to 0)
    # prints out all the integers

    # increment a by 1 (last value is passed back into the loop)

# Example 7

``

    live_loop :foo do
      play 70
      sleep 1
    end

    live_loop :foo do
      sample :bd_haus
      sleep 0.5

    end

``

    # Live loop names must be unique
    # Start a live loop called :foo

    # Attempt to start another also called :foo
    # With a different do/end block
    # This will not start another live loop
    # but instead replace the behaviour of the first.
    # There will only be one live loop running playing
    # The bass drum

# Example 8

``

    live_loop :foo, sync: :bar do
     play 70
     sleep 1
    end

    sleep 4

    live_loop :bar do
      sample :bd_haus
      sleep 0.5
    end

``

    # You can sync multiple live loops together
    # Wait for a :bar cue event before starting :foo
    # Live loop :foo is therefore blocked and does
    # not make a sound initially

    # Wait for 4 beats

    # Start a live loop called :foo which will emit a :bar
    # cue message therefore releasing the :foo live loop.
    # Live loop :foo therefore starts and also inherits the
    # logical time of live loop :bar.

    # This pattern is also useful to re-sync live loops after
    # errors are made. For example, when modifying live loop :foo
    # it is possible to introduce a runtime error which will stop
    # :foo but not :bar (as they are separate, isolated threads).
    # Once the error has been fixed and the code is re-run, :foo
    # will automatically wait for :bar to loop round and restart
    # in sync with the correct virtual clock.

# Load the contents of a file to the current buffer

``

    load_buffer  path (string)

Given a path to a file, will read the contents and load it into the current buffer. This will replace any previous content.

Introduced in v2.10

## Example

# Example 1

``

    load_buffer "~/sonic-pi-tracks/phat-beats.rb"

``

    # will replace content of current buffer with contents of the file

# Load a built-in example

``

    load_example  path (string)

Given a keyword representing an example, will load it into the current buffer. This will replace any previous content.

Introduced in v2.10

## Example

# Example 1

``

    load_example :rerezzed

``

    # will replace content of current buffer with the rerezzed example

# Pre-load first matching sample

``

    load_sample  path (string)

Given a path to a `.wav`, `.wave`, `.aif`, `.aiff`, `.ogg`, `.oga`, `.flac` or `.mp3` file, pre-loads the sample into memory.

You may also specify the same set of source and filter pre-args available to `sample` itself. `load_sample` will then load all matching samples. See `sample`’s docs for more information.

Introduced in v2.0

## Examples

# Example 1

``

    load_sample :elec_blip
    sample :elec_blip

``

    # :elec_blip is now loaded and ready to play as a sample
    # No delay takes place when attempting to trigger it

# Example 2

``

    dir = "/path/to/sample/dir"
    load_sample dir
    load_sample dir, 1
    load_sample dir, :foo
    load_sample dir, "quux"
    load_sample dir, /[Bb]ar/

``

    # Using source and filter pre-args

    # loads first matching sample in "/path/to/sample/dir"
    # loads sample with index 1 in "/path/to/sample/dir"
    # loads sample with name "foo" in "/path/to/sample/dir"
    # loads first sample with file name containing "quux" in "/path/to/sample/dir"
    # loads first sample which matches regex /[Bb]ar/ in "/path/to/sample/dir"

# Pre-load all matching samples

``

    load_samples  paths (list)

Given a directory containing multiple `.wav`, `.wave`, `.aif`, `.aiff`, `.ogg`, `.oga`, `.flac` or `.mp3` files, pre-loads all the samples into memory.

You may also specify the same set of source and filter pre-args available to `sample` itself. `load_sample` will load all matching samples (not just the sample `sample` would play given the same opts) - see `sample`’s docs for more information.

Introduced in v2.0

## Examples

# Example 1

``

    load_sample :elec_blip
     sample :elec_blip

``

    # :elec_blip is now loaded and ready to play as a sample
    # No delay takes place when attempting to trigger it

# Example 2

``

     dir = "/path/to/sample/dir"
     load_sample dir
     load_sample dir, 1
     load_sample dir, :foo
     load_sample dir, "quux"
     load_sample dir, /[Bb]ar/

``

    # Using source and filter pre-args

    # loads all samples in "/path/to/sample/dir"
    # loads sample with index 1 in "/path/to/sample/dir"
    # loads sample with name "foo" in "/path/to/sample/dir"
    # loads all samples with file names containing "quux" in "/path/to/sample/dir"
    # loads all samples which match regex /[Bb]ar/ in "/path/to/sample/dir"

# Load a single external synthdef

``

    load_synthdef  path (string)

Load a pre-compiled synth design from the specified file. This is useful if you wish to use your own SuperCollider synthesiser designs within Sonic Pi.

## Important notes

The binary file containing the synth design must have the extension `.scsyndef`.

You may not trigger external synthdefs unless you enable the following GUI preference:

`Studio -> Synths and FX -> Enable external synths and FX`

If you wish your synth to work with Sonic Pi’s automatic stereo sound infrastructure you need to ensure your synth outputs a stereo signal to an audio bus with an index specified by a synth arg named `out_bus`. Also, Sonic Pi makes no automatic attempt to free a synth once triggered, so to behave like the built-in synths, your synth needs to automatically free itself. For example, the following synth would work nicely:

    (
    SynthDef(\piTest,
             {|freq = 200, amp = 1, out_bus = 0 |
               Out.ar(out_bus,
                      SinOsc.ar([freq,freq],0,0.5)* Line.kr(1, 0, 5, amp, doneAction: 2))}
    ).writeDefFile("/Users/sam/Desktop/")
    )

Introduced in v4.0

## Example

# Example 1

``

    load_synthdef "~/Desktop/my_noises/whoosh.scsyndef"

``

    # Load whoosh synthdef design.

# Load external synthdefs

``

    load_synthdefs  path (string)

Load all pre-compiled synth designs in the specified directory. This is useful if you wish to use your own SuperCollider synthesiser designs within Sonic Pi.

## Important notes

Only files with the extension `.scsyndef` within the specified directory will be loaded.

You may not trigger external synthdefs unless you enable the following GUI preference:

`Studio -> Synths and FX -> Enable external synths and FX`

If you wish your synth to work with Sonic Pi’s automatic stereo sound infrastructure you need to ensure your synth outputs a stereo signal to an audio bus with an index specified by a synth arg named `out_bus`. Also, Sonic Pi makes no automatic attempt to free a synth once triggered, so to behave like the built-in synths, your synth needs to automatically free itself. For example, the following synth would work nicely:

    (
    SynthDef(\piTest,
             {|freq = 200, amp = 1, out_bus = 0 |
               Out.ar(out_bus,
                      SinOsc.ar([freq,freq],0,0.5)* Line.kr(1, 0, 5, amp, doneAction: 2))}
    ).writeDefFile("/Users/sam/Desktop/")
    )

Introduced in v2.0

## Example

# Example 1

``

    load_synthdefs "~/Desktop/my_noises"

``

    # Load all synthdefs in my_noises folder

# Obtain value of a tick

``

    look

Read and return value of default tick. If a `key` is specified, read the value of that specific tick. Ticks are `in_thread` and `live_loop` local, so the tick read will be the tick of the current thread calling `look`.

Introduced in v2.6

## Options

offset: | Offset to add to index returned. Useful when calling look on lists, rings and vectors to offset the returned value

## Examples

# Example 1

``

    puts look
      puts look
      puts look

``

    #=> 0
    #=> 0
    #=> 0 # look doesn't advance the tick, it just returns the current value

# Example 2

``

    puts look
      tick
      puts look
      tick
      puts look
      puts look
      tick
      puts look

``

    #=> 0 # A look is always 0 before the first tick
    # advance the tick
    #=> 0 # Note: a look is still 0 after the first tick.

    #=> 1
    #=> 1 # making multiple calls to look doesn't affect tick value

    #=> 2

# Example 3

``

    tick(:foo)
      tick(:foo)
      puts look(:foo)
      puts look
      puts look(:bar)

``

    #=> 1 (keyed look :foo has been advanced)
    #=> 0 (default look hasn't been advanced)
    #=> 0 (other keyed looks haven't been advanced either)

# Example 4

``

      live_loop :foo do
        tick
        use_synth :beep
        play (scale :e3, :minor_pentatonic).look
        sleep 0.5
        use_synth :square
        play (ring :e1, :e2, :e3).look, release: 0.25
        sleep 0.25
      end

``

    # You can call look on lists and rings

    # advance the default tick

    # look into the default tick to play all notes in sequence

    # use the same look on another ring

# Example 5

``

    puts look(0)
    puts look(4)
    puts look(-4)
    puts look(20.3)

``

    # Returns numbers unchanged if single argument
    #=> 0
    #=> 4
    #=> -4
    #=> 20.3

# Repeat do/end block forever

``

    loop

Given a do/end block, repeats it forever. Note that once the program enters the loop - it will not move on but will instead stay within the loop. Plain loops like this are like black holes - instead of sucking in the light they suck in the program.

The loop must either `sleep` or `sync` each time round otherwise it will stop and throw an error. This is to stop the loop from spinning out of control and locking the system.

For a more powerful, flexible loop built for live coding see `live_loop`.

Introduced in v2.0

## Example

# Example 1

``

    play 70

    loop do
      play 50
      sleep 1
      play 62
      sleep 2
    end

    play 80

``

    # note 70 is played

    # This loop will repeat notes 50 and 62 forever

    # This is *never* played as the program is trapped in the loop above

# Create an immutable map

``

    map  list (array)

Create a new immutable key/value map from args.

Introduced in v2.11

## Examples

# Example 1

``

    (map foo: 1, bar: 2)[:foo]

``

    #=> 1

# Example 2

``

    (map foo: 1, bar: 2)[:bar]

``

    #=> 2

# Example 3

``

    (map foo: 1, bar: 2)[:quux]

``

    #=> nil

# Trigger and release an external synth via MIDI

``

    midi  note (number)

Sends a MIDI note on event to all connected MIDI devices and all channels and then after sustain beats sends a MIDI note off event. Ensures MIDI trigger is synchronised with standard calls to play and sample. Co-operates completely with Sonic Pi’s timing system including `time_warp`.

If `note` is specified as `:off` then all notes will be turned off (same as `midi_all_notes_off`).

Introduced in v3.0

## Options

sustain: | Duration of note event in beats
vel: | Velocity of note as a MIDI number
on: | If specified and false/nil/0 will stop the midi on/off messages from being sent out. (Ensures all opts are evaluated in this call to `midi` regardless of value).

## Examples

# Example 1

``

    midi :e1, sustain: 0.3, vel_f: 0.5, channel: 3

``

    # Play E, octave 1 for 0.3 beats at half velocity on channel 3 on all connected MIDI ports.

# Example 2

``

    midi :off, channel: 3

``

    #=> Turn off all notes on channel 3 on all connected MIDI ports

# Example 3

``

    midi :e1, channel: 3, port: "foo"

``

    #=> Play note :E1 for 1 beats on channel 3 on MIDI port named "foo" only

# Example 4

``

    live_loop :arp do
      midi (octs :e1, 3).tick, sustain: 0.1
      sleep 0.125
    end

``

    # repeatedly play a ring of octaves

# Turn off all notes on MIDI devices

``

    midi_all_notes_off

Sends a MIDI all notes off message to all connected MIDI devices. on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

When an All Notes Off event is received, all oscillators will turn off.

MIDI 1.0 Specification - Channel Mode Messages - All Notes Off

Introduced in v3.0

## Options

channel: | Channel to send the all notes off message to
port: | MIDI port to send to
on: | If specified and false/nil/0 will stop the midi all notes off message from being sent out. (Ensures all opts are evaluated in this call to `midi_all_notes_off` regardless of value).

## Examples

# Example 1

``

    midi_all_notes_off

``

    #=> Turn off all notes on MIDI devices on all channels (and ports)

# Example 2

``

    midi_all_notes_off channel: 2

``

    #=> Turn off all notes on MIDI devices on channel 2

# Send MIDI control change message

``

    midi_cc  control_num (midi), value (midi)

Sends a MIDI control change message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Control number and control value can be passed as a note such as `:e3` and decimal values will be rounded down or up to the nearest whole number - so values between 3.5 and 4 will be rounded up to 4 and values between 3.49999… and 3 will be rounded down to 3.

You may also optionally pass the control value as a floating point value between 0 and 1 such as 0.2 or 0.785 (which will be mapped to MIDI values between 0 and 127) using the `val_f:` opt.

MIDI 1.0 Specification - Channel Voice Messages - Control change

Introduced in v3.0

## Options

channel: | Channel(s) to send to
port: | MIDI port(s) to send to
value: | Control value as a MIDI number.
val_f: | Control value as a value between 0 and 1 (will be converted to a MIDI value)
on: | If specified and false/nil/0 will stop the midi cc message from being sent out. (Ensures all opts are evaluated in this call to `midi_cc` regardless of value).

## Examples

# Example 1

``

    midi_cc 100, 32

``

    #=> Sends MIDI cc message to control 100 with value 32 to all ports and channels

# Example 2

``

    midi_cc :e7, 32

``

    #=> Sends MIDI cc message to control 100 with value 32 to all ports and channels

# Example 3

``

    midi_cc 100, 32, channel: 5

``

    #=> Sends MIDI cc message to control 100 with value 32 on channel 5 to all ports

# Example 4

``

    midi_cc 100, val_f: 0.8, channel: 5

``

    #=> Sends MIDI cc message to control 100 with value 102 on channel 5 to all ports

# Example 5

``

    midi_cc 100, value: 102, channel: [1, 5]

``

    #=> Sends MIDI cc message to control 100 with value 102 on channel 1 and 5 to all ports

# Send MIDI channel pressure (aftertouch) message

``

    midi_channel_pressure  val (midi)

Sends a MIDI channel pressure (aftertouch) message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

The pressure value can be passed as a note such as `:e3` and decimal values will be rounded down or up to the nearest whole number - so values between 3.5 and 4 will be rounded up to 4 and values between 3.49999… and 3 will be rounded down to 3.

You may also optionally pass the pressure value as a floating point value between 0 and 1 such as 0.2 or 0.785 (which will be mapped to MIDI values between 0 and 127) using the `val_f:` opt.

MIDI 1.0 Specification - Channel Voice Messages - Channel Pressure (Aftertouch)

Introduced in v3.0

## Options

channel: | Channel(s) to send to
port: | MIDI port(s) to send to
value: | Pressure value as a MIDI number.
val_f: | Pressure value as a value between 0 and 1 (will be converted to a MIDI value)
on: | If specified and false/nil/0 will stop the midi channel pressure message from being sent out. (Ensures all opts are evaluated in this call to `midi_channel_pressure` regardless of value).

## Examples

# Example 1

``

    midi_channel_pressure 50

``

    #=> Sends MIDI channel pressure message with value 50 to all ports and channels

# Example 2

``

    midi_channel_pressure :C4

``

    #=> Sends MIDI channel pressure message with value 60 to all ports and channels

# Example 3

``

    midi_channel_pressure 0.5

``

    #=> Sends MIDI channel pressure message with value 63.5 to all ports and channels

# Example 4

``

    midi_channel_pressure 30, channel: [1, 5]

``

    #=> Sends MIDI channel pressure message with value 30 on channel 1 and 5 to all ports

# Send a quarter-note's worth of MIDI clock ticks

``

    midi_clock_beat  duration (beats)

Sends enough MIDI clock ticks for one beat to all connected MIDI devices. Use the `port:` opt to restrict which MIDI ports are used.

The MIDI specification requires 24 clock tick events to be sent per beat. These can either be sent manually using `midi_clock_tick` or all 24 can be scheduled in one go using this fn. `midi_clock_beat` will therefore schedule for 24 clock ticks to be sent linearly spread over duration beats. This fn will automatically take into account the current BPM and any `time_warp`s.

Introduced in v3.0

## Options

port: | MIDI port to send to
on: | If specified and false/nil/0 will stop the midi clock tick messages from being sent out. (Ensures all opts are evaluated in this call to `midi_clock_beat` regardless of value).

## Examples

# Example 1

``

    midi_clock_beat

``

    #=> Send 24 clock ticks over a period of 1 beat to all connected MIDI devices

# Example 2

``

    midi_clock_beat 0.5

``

    #=> Send 24 clock ticks over a period of 0.5 beats to all connected MIDI devices

# Example 3

``

    midi_clock_beat port: "moog_subphatty"

``

    #=> Send 24 clock ticks over a period of 1 beat to just the MIDI port with name moog_subphatty

# Example 4

``

    live_loop :clock do
      midi_clock_beat
      sleep 1
    end

``

    # Create a live loop which continually sends out MIDI clock
    # events at the current BPM

# Example 5

``

    live_loop :clock do
      midi_start if tick == 0
      midi_clock_beat
      sleep 1
    end

``

    # Ensuring Clock Phase is Correct

    # Send a midi_start event the first time round the live loop only
    # this will not just send a steady clock beat, but also ensure
    # the clock phase of the MIDI device matches Sonic Pi.

# Send an individual MIDI clock tick

``

    midi_clock_tick

Sends a MIDI clock tick message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Typical MIDI devices expect the clock to send 24 ticks per quarter note (typically a beat). See `midi_clock_beat` for a simple way of sending all the ticks for a given beat.

MIDI 1.0 Specification - System Real-Time Messages - Timing Clock

Introduced in v3.0

## Options

port: | MIDI port to send to
on: | If specified and false/nil/0 will stop the midi clock tick message from being sent out. (Ensures all opts are evaluated in this call to `midi_clock_tick` regardless of value).

## Example

# Example 1

``

    midi_clock_tick

``

    #=> Send an individual clock tick to all connected MIDI devices on all ports.

# Send MIDI system message - continue

``

    midi_continue

Sends the MIDI continue system message to all connected MIDI devices on all ports. Use the `port:` opt to restrict which MIDI ports are used.

Upon receiving the MIDI continue event, the MIDI device(s) will continue at the point the sequence was stopped.

MIDI 1.0 Specification - System Real-Time Messages - Continue

Introduced in v3.0

## Options

port: | MIDI Port(s) to send the continue message to

## Example

# Example 1

``

    midi_continue

``

    #=> Send continue message to all connected MIDI devices

# Disable local control on MIDI devices

``

    midi_local_control_off

Sends a MIDI local control off message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

All devices on a given channel will respond only to data received over MIDI. Played data, etc. will be ignored. See `midi_local_control_on` to enable local control.

MIDI 1.0 Specification - Channel Mode Messages - Local Control Off

Introduced in v3.0

## Options

channel: | Channel to send the local control off message to
port: | MIDI port to send to
on: | If specified and false/nil/0 will stop the midi local control off message from being sent out. (Ensures all opts are evaluated in this call to `midi_local_control_off` regardless of value).

## Examples

# Example 1

``

    midi_local_control_off

``

    #=> Disable local control on MIDI devices on all channels (and ports)

# Example 2

``

    midi_local_control_off channel: 2

``

    #=> Disable local control on MIDI devices on channel 2

# Enable local control on MIDI devices

``

    midi_local_control_on

Sends a MIDI local control on message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

All devices on a given channel will respond both to data received over MIDI and played data, etc. See `midi_local_control_off` to disable local control.

MIDI 1.0 Specification - Channel Mode Messages - Local Control On

Introduced in v3.0

## Options

channel: | Channel to send the local control on message to
port: | MIDI port to send to
on: | If specified and false/nil/0 will stop the midi local control on message from being sent out. (Ensures all opts are evaluated in this call to `midi_local_control_on` regardless of value).

## Examples

# Example 1

``

    midi_local_control_on

``

    #=> Enable local control on MIDI devices on all channels (and ports)

# Example 2

``

    midi_local_control_on channel: 2

``

    #=> Enable local control on MIDI devices on channel 2

# Set Omni/Mono/Poly mode

``

    midi_mode  mode (mode_keyword)

Sends the Omni/Mono/Poly MIDI mode message to all connected MIDI devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Valid modes are:

- :omni_off - Omni Mode Off
- :omni_on - Omni Mode On
- :mono - Mono Mode On (Poly Off). Set num_chans: to be the number of channels to use (Omni Off) or 0 (Omni On). Default for num_chans: is 16.
- :poly - Poly Mode On (Mono Off)

Note that this fn also includes the behaviour of `midi_all_notes_off`.

MIDI 1.0 Specification - Channel Mode Messages - Omni Mode Off / Omni Mode On / Mono Mode On (Poly Off) / Poly Mode On

Introduced in v3.0

## Options

channel: | Channel to send the MIDI mode message to
port: | MIDI port to send to
mode: | Mode keyword - one of :omni_off, :omni_on, :mono or :poly
num_chans: | Used in mono mode only - Number of channels (defaults to 16)
on: | If specified and false/nil/0 will stop the midi local control off message from being sent out. (Ensures all opts are evaluated in this call to `midi_local_control_off` regardless of value).

## Examples

# Example 1

``

    midi_mode :omni_on

``

    #=> Turn Omni Mode On on all ports and channels

# Example 2

``

    midi_mode :mono, num_chans: 5

``

    #=> Mono Mode On, Omni off using 5 channels.

# Example 3

``

    midi_mode :mono, num_chans: 0

``

    #=> Mono Mode On, Omni on.

# Example 4

``

    midi_mode :mono

``

    #=> Mono Mode On, Omni off using 16 channels (the default) .

# Send MIDI note off message

``

    midi_note_off  note (midi), release_velocity (midi)

Sends the MIDI note off message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Note and release velocity values can be passed as a note symbol such as `:e3` or a number. Decimal values will be rounded down or up to the nearest whole number - so values between 3.5 and 4 will be rounded up to 4 and values between 3.49999… and 3 will be rounded down to 3. These values will also be clipped within the range 0->127 so all values lower then 0 will be increased to 0 and all values greater than 127 will be reduced to 127.

The `release_velocity` param may be omitted - in which case it will default to 127 unless you supply it as a named opt via the keys `velocity:` or `vel_f:`.

You may also optionally pass the release velocity value as a floating point value between 0 and 1 such as 0.2 or 0.785 (which will be mapped to MIDI values between 0 and 127) using the `vel_f:` opt.

MIDI 1.0 Specification - Channel Voice Messages - Note off event

Introduced in v3.0

## Options

channel: | MIDI channel(s) to send event on as a number or list of numbers.
port: | MIDI port(s) to send to as a string or list of strings.
velocity: | Release velocity as a MIDI number.
vel_f: | Release velocity as a value between 0 and 1 (will be converted to a MIDI velocity)
on: | If specified and false/nil/0 will stop the midi note off message from being sent out. (Ensures all opts are evaluated in this call to `midi_note_off` regardless of value).

## Examples

# Example 1

``

    midi_note_off :e3

``

    #=> Sends MIDI note off for note :e3 with the default release velocity of 127 to all ports and channels

# Example 2

``

    midi_note_off :e3, 12

``

    #=> Sends MIDI note off for note :e3 with velocity 12 on all channels

# Example 3

``

    midi_note_off :e3, 12, channel: 3

``

    #=> Sends MIDI note off for note :e3 with velocity 12 to channel 3

# Example 4

``

    midi_note_off :e3, velocity: 100

``

    #=> Sends MIDI note off for note :e3 with release velocity 100

# Example 5

``

    midi_note_off :e3, vel_f: 0.8

``

    #=> Scales release velocity 0.8 to MIDI value 102 and sends MIDI note off for note :e3 with release velocity 102

# Example 6

``

    midi_note_off 60.3, 50.5

``

    #=> Rounds params up or down to the nearest whole number and sends MIDI note off for note 60 with release velocity 51

# Example 7

``

    midi_note_off :e3, channel: [1, 3, 5]

``

    #=> Send MIDI note off for note :e3 to channels 1, 3, 5 on all connected ports

# Example 8

``

    midi_note_off :e3, port: ["foo", "bar"]

``

    #=> Send MIDI note off for note :e3 to all channels on ports named "foo" and "bar"

# Example 9

``

    midi_note_off :e3, channel: 1, port: "foo"

``

    #=> Send MIDI note off for note :e3 only on channel 1 on port "foo"

# Send MIDI note on message

``

    midi_note_on  note (midi), velocity (midi)

Sends a MIDI Note On Event to all connected devices on all channels. Use the `port:` and `channel:` opts to indepently restrict which MIDI ports and channels are used.

Note and velocity values can be passed as a note symbol such as `:e3` or a MIDI number such as 52. Decimal values will be rounded down or up to the nearest whole number - so values between 3.5 and 4 will be rounded up to 4 and values between 3.49999… and 3 will be rounded down to 3. These values will also be clipped within the range 0->127 so all values lower than 0 will be increased to 0 and all values greater than 127 will be reduced to 127.

The `velocity` param may be omitted - in which case it will default to 127 unless you supply it as an opt via the keys `velocity:` or `vel_f:`.

You may also optionally pass the velocity value as a floating point value between 0 and 1 such as 0.2 or 0.785 (which will be linearly mapped to MIDI values between 0 and 127) using the vel_f: opt.

MIDI 1.0 Specification - Channel Voice Messages - Note on event

Introduced in v3.0

## Options

channel: | MIDI channel(s) to send event on
port: | MIDI port(s) to send to
velocity: | Note velocity as a MIDI number.
vel_f: | Velocity as a value between 0 and 1 (will be converted to a MIDI velocity between 0 and 127)
on: | If specified and false/nil/0 will stop the midi note on message from being sent out. (Ensures all opts are evaluated in this call to `midi_note_on` regardless of value).

## Examples

# Example 1

``

    midi_note_on :e3

``

    #=> Sends MIDI note on for note :e3 with the default velocity of 12 to all ports and channels

# Example 2

``

    midi_note_on :e3, 12

``

    #=> Sends MIDI note on for note :e3 with velocity 12 to all channels

# Example 3

``

    midi_note_on :e3, 12, channel: 3

``

    #=> Sends MIDI note on for note :e3 with velocity 12 on channel 3

# Example 4

``

    midi_note_on :e3, velocity: 100

``

    #=> Sends MIDI note on for note :e3 with velocity 100

# Example 5

``

    midi_note_on :e3, vel_f: 0.8

``

    #=> Scales velocity 0.8 to MIDI value 102 and sends MIDI note on for note :e3 with velocity 102

# Example 6

``

    midi_note_on 60.3, 50.5

``

    #=> Rounds params up or down to the nearest whole number and sends MIDI note on for note 60 with velocity 51

# Example 7

``

    midi_note_on :e3, channel: [1, 3, 5]

``

    #=> Send MIDI note on for note :e3 to channels 1, 3, 5 on all connected ports

# Example 8

``

    midi_note_on :e3, port: ["foo", "bar"]

``

    #=> Send MIDI note on for note :e3 to all channels on ports named "foo" and "bar"

# Example 9

``

    midi_note_on :e3, channel: 1, port: "foo"

``

    #=> Send MIDI note on for note :e3 only on channel 1 on port "foo"

# Create a ring buffer of midi note numbers

``

    midi_notes  list (array)

Create a new immutable ring buffer of notes from args. Indexes wrap around positively and negatively. Final ring consists only of MIDI numbers and nil.

Introduced in v2.7

## Examples

# Example 1

``

    (midi_notes :d3, :d4, :d5)

``

    #=> (ring 50, 62, 74)

# Example 2

``

    (midi_notes :d3, 62,  nil)

``

    #=> (ring 50, 62, nil)

# Send MIDI program change message

``

    midi_pc  program_num (midi)

Sends a MIDI program change message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Program number can be passed as a note such as `:e3` and decimal values will be rounded down or up to the nearest whole number - so values between 3.5 and 4 will be rounded up to 4 and values between 3.49999… and 3 will be rounded down to 3.

MIDI 1.0 Specification - Channel Voice Messages - Program change

Introduced in v3.1

## Options

channel: | Channel(s) to send to
port: | MIDI port(s) to send to
on: | If specified and false/nil/0 will stop the midi pc message from being sent out. (Ensures all opts are evaluated in this call to `midi_pc` regardless of value).

## Examples

# Example 1

``

    midi_pc 100

``

    #=> Sends MIDI pc message to all ports and channels

# Example 2

``

    midi_pc :e7

``

    #=> Sends MIDI pc message to all ports and channels

# Example 3

``

    midi_pc 100, channel: 5

``

    #=> Sends MIDI pc message on channel 5 to all ports

# Example 4

``

    midi_pc 100, port: ["foo", "bar"], channel: 5

``

    #=> Sends MIDI pc message on channel 5 to ports named "foo" and "bar"

# Example 5

``

    midi_pc 100, channel: [1, 5]

``

    #=> Sends MIDI pc message on channel 1 and 5 to all ports

# Send MIDI pitch bend message

``

    midi_pitch_bend  delta (float01)

Sends a MIDI pitch bend message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Delta value is between 0 and 1 with 0.5 representing no pitch bend, 1 max pitch bend and 0 minimum pitch bend.

Typical MIDI values such as note or cc are represented with 7 bit numbers which translates to the range 0-127. This makes sense for keyboards which have at most 88 keys. However, it translates to a poor resolution when working with pitch bend. Therefore, pitch bend is unlike most MIDI values in that it has a much greater range: 0 - 16383 (by virtue of being represented by 14 bits).

- It is also possible to specify the delta value as a (14 bit) MIDI pitch bend value between 0 and 16383 using the `delta_midi:` opt.
- When using the `delta_midi:` opt no pitch bend is the value 8192

MIDI 1.0 Specification - Channel Voice Messages - Pitch Bend Change

Introduced in v3.0

## Options

channel: | Channel(s) to send to
port: | MIDI port(s) to send to
delta: | Pitch bend value as a number between 0 and 1 (will be converted to a value between 0 and 16383). No bend is the central value 0.5
delta_midi: | Pitch bend value as a number between 0 and 16383 inclusively. No bend is central value 8192.
on: | If specified and false/nil/0 will stop the midi pitch bend message from being sent out. (Ensures all opts are evaluated in this call to `midi_pitch_bend` regardless of value).

## Examples

# Example 1

``

    midi_pitch_bend 0

``

    #=> Sends MIDI pitch bend message with value 0 to all ports and channels

# Example 2

``

    midi_pitch_bend 1

``

    #=> Sends MIDI pitch bend message with value 16383 to all ports and channels

# Example 3

``

    midi_pitch_bend 0.5

``

    #=> Sends MIDI pitch bend message with value 8192 to all ports and channels

# Example 4

``

    midi_pitch_bend delta_midi: 8192

``

    #=> Sends MIDI pitch bend message with value 8192 to all ports and channels

# Example 5

``

    midi_pitch_bend 0, channel: [1, 5]

``

    #=> Sends MIDI pitch bend message with value 0 on channel 1 and 5 to all ports

# Send a MIDI polyphonic key pressure message

``

    midi_poly_pressure  note (midi), value (midi)

Sends a MIDI polyphonic key pressure message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

Note number and pressure value can be passed as a note such as `:e3` and decimal values will be rounded down or up to the nearest whole number - so values between 3.5 and 4 will be rounded up to 4 and values between 3.49999… and 3 will be rounded down to 3.

You may also optionally pass the pressure value as a floating point value between 0 and 1 such as 0.2 or 0.785 (which will be mapped to MIDI values between 0 and 127) using the `val_f:` opt.

MIDI 1.0 Specification - Channel Voice Messages - Polyphonic Key Pressure (Aftertouch)

Introduced in v3.0

## Options

channel: | Channel(s) to send to
port: | MIDI port(s) to send to
value: | Pressure value as a MIDI number.
val_f: | Pressure value as a value between 0 and 1 (will be converted to a MIDI value)
on: | If specified and false/nil/0 will stop the midi poly pressure message from being sent out. (Ensures all opts are evaluated in this call to `midi_poly_pressure` regardless of value).

## Examples

# Example 1

``

    midi_poly_pressure 100, 32

``

    #=> Sends a MIDI poly key pressure message to control note 100 with value 32 to all ports and channels

# Example 2

``

    midi_poly_pressure :e7, 32

``

    #=> Sends a MIDI poly key pressure message to control note 100 with value 32 to all ports and channels

# Example 3

``

    midi_poly_pressure 100, 32, channel: 5

``

    #=> Sends MIDI poly key pressure message to control note 100 with value 32 on channel 5 to all ports

# Example 4

``

    midi_poly_pressure 100, val_f: 0.8, channel: 5

``

    #=> Sends a MIDI poly key pressure message to control note 100 with value 102 on channel 5 to all ports

# Example 5

``

    midi_poly_pressure 100, value: 102, channel: [1, 5]

``

    #=> Sends MIDI poly key pressure message to control note 100 with value 102 on channel 1 and 5 to all ports

# Send raw MIDI message

``

    midi_raw

Sends the raw MIDI message to all connected MIDI devices. Gives you direct access to sending the individual bytes of a MIDI message. Typically this should be rarely used - prefer the other `midi_` fns where possible.

A raw MIDI message consists of multiple bytes as numbers in decimal notation (i.e. 176), hex (0xb0) or binary (0b10110000).

See https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message for a summary of MIDI messages and their corresponding byte structures.

Introduced in v3.0

## Options

port: | Port(s) to send the raw MIDI message events to
on: | If specified and false/nil/0 will stop the raw midi message from being sent out. (Ensures all opts are evaluated in this call to `midi_raw` regardless of value).

## Examples

# Example 1

``

    midi_raw 176, 121, 0

``

    #=> Sends the MIDI reset command

# Example 2

``

    midi_raw 176.1, 120.5, 0.49

``

    #=> Sends the MIDI reset command (values are rounded down, up and down respectively)

# Example 3

``

    midi_raw 0xb0, 0x79, 0x0

``

    #=> Sends the MIDI reset command

# Example 4

``

    midi_raw 0b10110000, 0b01111001, 0b00000000

``

    #=> Sends the MIDI reset command

# Reset MIDI devices

``

    midi_reset  value (number)

Sends a MIDI reset all controllers message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

All controller values are reset to their defaults.

MIDI 1.0 Specification - Channel Mode Messages - Reset All Controllers

Introduced in v3.0

## Options

channel: | Channel to send the midi reset message to
port: | MIDI port to send to
value: | Value must only be zero (the default) unless otherwise allowed in a specific Recommended Practice
on: | If specified and false/nil/0 will stop the midi reset message from being sent out. (Ensures all opts are evaluated in this call to `midi_reset` regardless of value).

## Examples

# Example 1

``

    midi_reset

``

    #=> Reset MIDI devices on all channels (and ports)

# Example 2

``

    midi_reset channel: 2

``

    #=> Reset MIDI devices on channel 2

# Silence all MIDI devices

``

    midi_sound_off

Sends a MIDI sound off message to all connected devices on all channels. Use the `port:` and `channel:` opts to restrict which MIDI ports and channels are used.

All oscillators will turn off, and their volume envelopes are set to zero as soon as possible.

MIDI 1.0 Specification - Channel Mode Messages - All Sound Off

Introduced in v3.0

## Options

channel: | Channel to send the sound off message to
port: | MIDI port to send to
on: | If specified and false/nil/0 will stop the midi sound off on message from being sent out. (Ensures all opts are evaluated in this call to `midi_sound_off` regardless of value).

## Examples

# Example 1

``

    midi_sound_off

``

    #=> Silence MIDI devices on all ports and channels

# Example 2

``

    midi_sound_off channel: 2

``

    #=> Silence MIDI devices on channel 2

# Send MIDI system message - start

``

    midi_start

Sends the MIDI start system message to all connected MIDI devices on all ports. Use the `port:` opt to restrict which MIDI ports are used.

Start the current sequence playing. (This message should be followed with calls to `midi_clock_tick` or `midi_clock_beat`).

MIDI 1.0 Specification - System Real-Time Messages - Start

Introduced in v3.0

## Example

# Example 1

``

    midi_start

``

    #=> Send start message to all connected MIDI devices

# Send MIDI system message - stop

``

    midi_stop

Sends the MIDI stop system message to all connected MIDI devices on all ports. Use the `port:` opt to restrict which MIDI ports are used.

Stops the current sequence.

MIDI 1.0 Specification - System Real-Time Messages - Start

Introduced in v3.0

## Options

port: | MIDI Port(s) to send the stop message to

## Example

# Example 1

``

    midi_stop

``

    #=> Send stop message to all connected MIDI devices

# Send MIDI System Exclusive (SysEx) message

``

    midi_sysex

Sends the MIDI SysEx message to all connected MIDI devices.

MIDI SysEx messages, unlike all other MIDI messages, are variable in length. They allow MIDI device manufacturers to define device-specific messages, for example loading/saving patches, or programming device features such as illuminated buttons.

Floats will be rounded up or down to the nearest whole number e.g. 176.1 -> 176, 120.5 -> 121, 0.49 -> 0.

Non-number values will be automatically turned into numbers prior to sending the event if possible (if this conversion does not work an Error will be thrown).

Introduced in v3.2

## Options

port: | Port(s) to send the MIDI SysEx message events to
on: | If specified and false/nil/0 will stop the midi SysEx message from being sent out. (Ensures all opts are evaluated in this call to `midi_sysex` regardless of value).

## Example

# Example 1

``

    midi_sysex 0xf0, 0x00, 0x20, 0x6b, 0x7f, 0x42, 0x02, 0x00, 0x10, 0x77, 0x11, 0xf7

``

    #=> Program an Arturia Beatstep controller to turn the eighth pad pink

# MIDI to Hz conversion

``

    midi_to_hz  note (symbol_or_number)

Convert a midi note to hz

Introduced in v2.0

## Example

# Example 1

``

    midi_to_hz(60)

``

    #=> 261.6256

# Define a new function

``

    ndefine  name (symbol)

Does nothing. Use to stop a define from actually defining. Simpler than wrapping whole define in a comment block or commenting each individual line out.

Introduced in v2.1

# Describe note

``

    note  note (symbol_or_number)

Takes a midi note, a symbol (e.g. `:C`) or a string (e.g. `"C"`) and resolves it to a midi note. You can also pass an optional `octave:` parameter to get the midi note for a given octave. Please note - `octave:` param overrides any octave specified in a symbol i.e. `:c3`. If the note is `nil`, `:r` or `:rest`, then `nil` is returned (`nil` represents a rest)

Introduced in v2.0

## Options

octave: | The octave of the note. Overrides any octave declaration in the note symbol such as :c2. Default is 4

## Examples

# Example 1

``

    puts note(60)
    puts note(:C)
    puts note(:C4)
    puts note('C')

``

    # These all return 60 which is the midi number for middle C (octave 4)

# Example 2

``

    puts note(60, octave: 2)

    puts note(:C, octave: 2)
    puts note(:C4, octave: 2)
    puts note('C', octave: 2)

``

    # returns 60 - octave param has no effect if we pass in a number

    # These all return 36 which is the midi number for C2 (two octaves below middle C)

    # note the octave param overrides any octaves specified in a symbol

# Get note info

``

    note_info  note (symbol_or_number)

Returns an instance of `SonicPi::Note`. Please note - `octave:` param overrides any octave specified in a symbol i.e. `:c3`

Introduced in v2.0

## Options

octave: | The octave of the note. Overrides any octave declaration in the note symbol such as :c2. Default is 4

## Example

# Example 1

``

    puts note_info(:C, octave: 2)

``

    # returns #<SonicPi::Note :C2>

# Get a range of notes

``

    note_range  start_note (note), end_note (note)

Produces a ring of all the notes between a start note and an end note. By default this is chromatic (all the notes) but can be filtered with a pitches: argument. This opens the door to arpeggiator style sequences and other useful patterns. If you try to specify only pitches which aren’t in the range it will raise an error - you have been warned!

Introduced in v2.6

## Options

pitches: | An array of notes (symbols or ints) to filter on. Octave information is ignored.

## Examples

# Example 1

``

    (note_range :c4, :c5)

``

    # => (ring 60,61,62,63,64,65,66,67,68,69,70,71,72)

# Example 2

``

    (note_range :c5, :c4)

``

    # => (ring 72,71,70,69,68,67,66,65,64,63,62,61,60)

# Example 3

``

    (note_range :c4, :c5, pitches: (chord :c, :major))

``

    # => (ring 60,64,67,72)

# Example 4

``

    (note_range :c4, :c6, pitches: (chord :c, :major))

``

    # => (ring 60,64,67,72,76,79,84)

# Example 5

``

    (note_range :c4, :c5, pitches: (scale :c, :major))

``

    # => (ring 60,62,64,65,67,69,71,72)

# Example 6

``

    (note_range :c4, :c5, pitches: [:c4, :g2])

``

    # => (ring 60,67,72)

# Example 7

``

    live_loop :arpeggiator do

      play (note_range :c4, :c5, pitches: (chord :c, :major)).tick
      sleep 0.125
    end

``

    # try changing the chord

# Create a ring of octaves

``

    octs  start (note), num_octaves (pos_int)

Create a ring of successive octaves starting at `start` for `num_octaves`.

Introduced in v2.8

## Examples

# Example 1

``

    (octs 60, 2)

``

    #=> (ring 60, 72)

# Example 2

``

    (octs :e3, 3)

``

    #=> (ring 52, 64, 76)

# Optionally evaluate block

``

    on  condition (truthy)

Optionally evaluate the block depending on the truthiness of the supplied condition. The truthiness rules are as follows: all values are seen as true except for: false, nil and 0. Lambdas will be automatically called and the truthiness of their results used.

Introduced in v2.10

## Examples

# Example 1

``

    on true do
      play 70
    end

``

    #=> will play 70 as true is truthy

# Example 2

``

    on 1 do
      play 70
    end

``

    #=> will play 70 as 1 is truthy

# Example 3

``

    on 0 do
      play 70
    end

``

    #=> will *not* play 70 as 0 is not truthy

# Example 4

``

    on false do
      play 70
    end

``

    #=> will *not* play 70 as false is not truthy

# Example 5

``

    on nil do
      play 70
    end

``

    #=> will *not* play 70 as nil is not truthy

# Example 6

``

    on lambda{true} do
      play 70
    end

``

    #=> will play 70 as the lambda returns a truthy value

# Example 7

``

    on lambda{false} do
      play 70
    end

``

    #=> will *not* play 70 as the lambda does not return a truthy value

# Example 8

``

    on lambda{[true, false].choose} do
      play 70
    end

``

    #=> will maybe play 70 depending on the choice in the lambda

# Random true value with specified probability

``

    one_in  num (number)

Returns `true` or `false` with a specified probability - it will return true every one in num times where num is the param you specify

Introduced in v2.0

## Examples

# Example 1

``

    one_in 2

``

    # will return true with a probability of 1/2, false with probability 1/2

# Example 2

``

    one_in 3

``

    # will return true with a probability of 1/3, false with a probability of 2/3

# Example 3

``

    one_in 100

``

    # will return true with a probability of 1/100, false with a probability of 99/100

# Send an OSC message (Open Sound Control)

``

    osc  path (arguments)

Sends an OSC message to the current host and port specified by `use_osc` or `with_osc`.

OSC (Open Sound Control) is a simple way of passing messages between two separate programs on the same computer or even on different computers via a local network or even the internet. `osc` enables you to send well-timed OSC messages from within Sonic Pi. `osc` will ensure that the OSC message is sent at the correct time using the same timing system shared with the synthesis functionality via `sample`, `synth` and friends. `osc` even works seamlessly within `time_warp` - see examples.

A typical OSC message has two parts: a descriptive `path` which looks similar to a URL (website address), and an optional list of `arguments` that are either numbers or strings.

For example, a hypothetical synth program might accept this OSC message:

`/set/filter lowpass 80 0.5`

where `/set/filter` is the path, and `lowpass`, `80`, and `0.5` are three arguments. This can be sent from within Sonic Pi by writing:

`osc "/set/filter", "lowpass", 80, 0.5`

However, in order to send the OSC message you must first specify where to send it to. This is achieved by specifying both the host (the machine’s internet address) and the port that the remote OSC server is listening on. This is configured using `use_osc` or `with_osc`. So, if our synth program was running on a machine on the local network with IP address `10.0.1.5` on port `5100` we could send our OSC message to it with the following:

`use_osc "10.0.1.5", 5100`

`osc "/set/filter", "lowpass", 80, 0.5`

Note, by default, Sonic Pi listens for OSC messages on port `4560`, so you may send messages to an external machine running Sonic Pi if you know the IP address of that external machine. Any OSC messages received on port `4560` are automatically converted to standard cue events and displayed in the GUI’s cue log. This also means that you can use `sync` to wait for the next incoming OSC message with a given path (see example).

Finally, it is also very useful to send OSC messages to other programs on the same computer. This can be achieved by specifying “localhost” as the hostname and the port as normal (depending on which port the other program is listening on).

See `osc_send` for a version which allows you to specify the hostname and port directly (ignoring any values set via `use_osc` or `with_osc`).

For further information see the OSC spec: https://opensoundcontrol.stanford.edu/spec-1_0.html

Introduced in v3.0

## Examples

# Example 1

``

    use_osc "localhost", 7000
    osc "/foo/bar"

``

    # Send a simple OSC message to another program on the same machine

    # Specify port 7000 on this machine
    # Send an OSC message with path "/foo/bar"
    # and no arguments

# Example 2

``

    use_osc "localhost", 7000
    osc "/foo/bar", 1, 3.89, "baz"

``

    # Send an OSC message with arguments to another program on the same machine

    # Specify port 7000 on this machine
    # Send an OSC message with path "/foo/bar"
    # and three arguments:
    # 1) The whole number (integer) 1
    # 2) The fractional number (float) 3.89
    # 3) The string "baz"

# Example 3

``

    use_osc "10.0.1.5", 7000
    osc "/foo/bar", 1, 3.89, "baz"

``

    # Send an OSC message with arguments to another program on a different machine

    # Specify port 7000 on the machine with address 10.0.1.5
    # Send an OSC message with path "/foo/bar"
    # and three arguments:
    # 1) The whole number (integer) 1
    # 2) The fractional number (float) 3.89
    # 3) The string "baz"

# Example 4

``

    osc "/foo/bar"
    play 60

    sleep 1

    osc "/baz/quux"
    play 72

``

    # OSC messages honour the timing system

    # Send an OSC message with path /foo/bar at *exactly* the
    # same time as note 60 is played

    # Wait for 1 beat

    # Send an OSC message with path /baz/quux at *exactly* the
    # same time as note 72 is played

# Example 5

``

    live_loop :foo do
      osc "/counter", tick

      sleep 1
    end

``

    # Send a incrementing OSC counter

    # Start a live loop called :foo
    # Send an OSC message with the path /counter
    # with successive whole numbers (0, 1, 2, 3.. etc.)
    # each time round the live loop
    # Repeat the live loop every 1 beat

# Example 6

``

    time_warp 0.5 do
      osc "/foo/bar"
    end

    sleep 1

    time_warp -0.1 do
      osc "/baz/quux"
    end

``

    # OSC messages can be sent from within time_warp

    # Send an OSC message with path /foo/bar at 0.5 beats

    # Wait for 1 beat

    # Send an OSC message with path /baz/quux at 0.9 beats

# Send an OSC message to a specific host and port

``

    osc_send  hostname (string), port (number), path (osc_path), args (list)

Similar to `osc` except ignores any `use_osc` settings and sends the OSC message directly to the specified `hostname` and `port`.

See `osc` for more information.

Introduced in v3.0

## Examples

# Example 1

``

    osc_send "localhost", 7000, "/foo/baz"

``

    # Send an OSC message to port 7000 on the same machine

# Example 2

``

    use_osc "localhost", 7010
    osc "/foo/baz"

    osc_send "localhost", 7000, "/foo/baz"

``

    # set hostname and port
    # Send an OSC message to port 7010

    # Send an OSC message to port 7000
    # (ignores use_osc settings)

# Randomly pick from list (with duplicates)

``

    pick  list (array), n (number_or_nil)

Pick n elements from list or ring. Unlike shuffle, after each element has been picked, it is ‘returned’ to the list so it may be picked again. This means there may be duplicates in the result. If n is greater than the size of the ring/list then duplicates are guaranteed to be in the result.

If `n` isn’t supplied it defaults to a size of 1.

If no arguments are given, will return a lambda function which when called takes an argument which will be a list to be picked from. This is useful for choosing random `onset:` vals for samples.

Always returns a list-like thing (either an array or ring)

Introduced in v2.10

## Options

skip: | Number of rands to skip over with each successive pick

## Examples

# Example 1

``

    puts [1, 2, 3, 4, 5].pick(3)

``

    #=> [4, 4, 3]

# Example 2

``

    puts (ring 1, 2, 3, 4, 5).pick(3)

``

    #=> (ring 4, 4, 3)

# Example 3

``

    puts (ring 1, 2).pick(5)

``

    #=> (ring 2, 2, 1, 1, 1)

# Example 4

``

    puts (ring 1, 2, 3).pick

``

    #=> (ring 3)

# Example 5

``

    live_loop :foo do
      sample :loop_amen, onset: pick
      sleep 0.125
    end

``

    # Using pick for random sample onsets

    # pick a random onset value each time

# Relative MIDI pitch to frequency ratio

``

    pitch_to_ratio  pitch (midi_number)

Convert a midi note to a ratio which when applied to a frequency will scale the frequency by the number of semitones. Useful for changing the pitch of a sample by using it as a way of generating the rate.

Introduced in v2.5

## Examples

# Example 1

``

    pitch_to_ratio 12

``

    #=> 2.0

# Example 2

``

    pitch_to_ratio 1

``

    #=> 1.05946

# Example 3

``

    pitch_to_ratio -12

``

    #=> 0.5

# Example 4

``

    sample :ambi_choir, rate: pitch_to_ratio(3)

``

    # Plays :ambi_choir 3 semitones above default.

# Example 5

``

    (range 0, 16).each do |n|
      sample :ambi_choir, rate: pitch_to_ratio(n)
      sleep 0.5
    end

``

    # Play a chromatic scale of semitones
    # For each note in the range 0->16
    # play :ambi_choir at the relative pitch
    # and wait between notes

# Play current synth

``

    play  note (symbol_or_number)

Play note with current synth. Accepts a set of standard options which include control of an amplitude envelope with `attack:`, `decay:`, `sustain:` and `release:` phases. These phases are triggered in order, so the duration of the sound is attack + decay + sustain + release times. The duration of the sound does not affect any other notes. Code continues executing whilst the sound is playing through its envelope phases.

If `duration:` is supplied and `sustain:` isn’t, it causes `sustain:` to be set so that all four phases add up to the duration.

Accepts optional args for modification of the synth being played. See each synth’s documentation for synth-specific opts. See `use_synth` and `with_synth` for changing the current synth.

If note is `nil`, `:r` or `:rest`, play is ignored and treated as a rest. Also, if the `on:` opt is specified and returns `false`, or `nil` then play is similarly ignored and treated as a rest.

Note that the default opts listed are only a guide to the most common opts across all the synths. Not all synths support all the default opts and each synth typically supports many more opts specific to that synth. For example, the `:tb303` synth supports 45 unique opts. For a full list of a synth’s opts see its documentation in the Help system.

Introduced in v2.0

## Options

amp: | The amplitude of the note
amp_slide: | The duration in beats for amplitude changes to take place
pan: | The stereo position of the sound. -1 is left, 0 is in the middle and 1 is on the right. You may use a value in between -1 and 1 such as 0.25
pan_slide: | The duration in beats for the pan value to change
attack: | Amount of time (in beats) for sound to reach full amplitude (attack_level). A short attack (i.e. 0.01) makes the initial part of the sound very percussive like a sharp tap. A longer attack (i.e 1) fades the sound in gently.
decay: | Amount of time (in beats) for the sound to move from full amplitude (attack_level) to the sustain amplitude (sustain_level).
sustain: | Amount of time (in beats) for sound to remain at sustain level amplitude. Longer sustain values result in longer sounds. Full length of sound is attack + decay + sustain + release.
release: | Amount of time (in beats) for sound to move from sustain level amplitude to silent. A short release (i.e. 0.01) makes the final part of the sound very percussive (potentially resulting in a click). A longer release (i.e 1) fades the sound out gently.
attack_level: | Amplitude level reached after attack phase and immediately before decay phase
decay_level: | Amplitude level reached after decay phase and immediately before sustain phase. Defaults to sustain_level unless explicitly set
sustain_level: | Amplitude level reached after decay phase and immediately before release phase.
env_curve: | Select the shape of the curve between levels in the envelope. 1=linear, 2=exponential, 3=sine, 4=welch, 6=squared, 7=cubed
slide: | Default slide time in beats for all slide opts. Individually specified slide opts will override this value
pitch: | Pitch adjustment in semitones. 1 is up a semitone, 12 is up an octave, -12 is down an octave etc. Decimal numbers can be used for fine tuning.
on: | If specified and false/nil/0 will stop the synth from being played. Ensures all opts are evaluated.

## Examples

# Example 1

``

    play 50

``

    # Plays note 50 on the current synth

# Example 2

``

    play 50, attack: 1

``

    # Plays note 50 with a fade-in time of 1s

# Example 3

``

    play 62, pan: -1, release: 3

``

    # Play note 62 in the left ear with a fade-out time of 3s.

# Example 4

``

    s = play :e3, release: 4
    sleep 1
    control s, note: :e5
    sleep 0.5
    use_synth :dsaw
    play :e3

``

    # controlling a synth synchronously

    # This is triggered after 1.5s from start

# Example 5

``

    play :e3, release: 4 do |s|
      sleep 1
      control s, note: :e5
    end

    sleep 0.5
    use_synth :dsaw
    play :e3

``

    # Controlling a synth asynchronously

    # This block is run in an implicit in_thread
    # and therefore is asynchronous

    # This is triggered after 0.5s from start

# Play notes simultaneously

``

    play_chord  notes (list)

Play a list of notes at the same time.

Accepts optional args for modification of the synth being played. See each synth’s documentation for synth-specific opts. See `use_synth` and `with_synth` for changing the current synth.

Introduced in v2.0

## Options

amp: | The amplitude of the note
amp_slide: | The duration in beats for amplitude changes to take place
pan: | The stereo position of the sound. -1 is left, 0 is in the middle and 1 is on the right. You may use a value in between -1 and 1 such as 0.25
pan_slide: | The duration in beats for the pan value to change
attack: | Amount of time (in beats) for sound to reach full amplitude (attack_level). A short attack (i.e. 0.01) makes the initial part of the sound very percussive like a sharp tap. A longer attack (i.e 1) fades the sound in gently.
decay: | Amount of time (in beats) for the sound to move from full amplitude (attack_level) to the sustain amplitude (sustain_level).
sustain: | Amount of time (in beats) for sound to remain at sustain level amplitude. Longer sustain values result in longer sounds. Full length of sound is attack + decay + sustain + release.
release: | Amount of time (in beats) for sound to move from sustain level amplitude to silent. A short release (i.e. 0.01) makes the final part of the sound very percussive (potentially resulting in a click). A longer release (i.e 1) fades the sound out gently.
attack_level: | Amplitude level reached after attack phase and immediately before decay phase
decay_level: | Amplitude level reached after decay phase and immediately before sustain phase. Defaults to sustain_level unless explicitly set
sustain_level: | Amplitude level reached after decay phase and immediately before release phase.
env_curve: | Select the shape of the curve between levels in the envelope. 1=linear, 2=exponential, 3=sine, 4=welch, 6=squared, 7=cubed
slide: | Default slide time in beats for all slide opts. Individually specified slide opts will override this value
pitch: | Pitch adjustment in semitones. 1 is up a semitone, 12 is up an octave, -12 is down an octave etc. Decimal numbers can be used for fine tuning.
on: | If specified and false/nil/0 will stop the synth from being played. Ensures all opts are evaluated.

## Examples

# Example 1

``

    play_chord [40, 45, 47]

    play 40
    play 45
    play 47

``

    # same as:

# Example 2

``

    play_chord [40, 45, 47], amp: 0.5

    play 40, amp: 0.5
    play 45, amp: 0.5
    play 47, amp: 0.5

``

    # same as:

# Example 3

``

    play_chord chord(:e3, :minor)

``

# Play pattern of notes

``

    play_pattern  notes (list)

Play list of notes with the current synth one after another with a sleep of 1

Accepts optional args for modification of the synth being played. See each synth’s documentation for synth-specific opts. See use_synth and with_synth for changing the current synth.

Introduced in v2.0

## Examples

# Example 1

``

    play_pattern [40, 41, 42]

``

    # Same as:
    #   play 40, sustain: 1
    #   sleep 1
    #   play 41, sustain: 1
    #   sleep 1
    #   play 42, sustain: 1
    #   sleep 1

# Example 2

``

    play_pattern [:d3, :c1, :Eb5]

``

    # You can use keyword notes

# Example 3

``

    play_pattern [:d3, :c1, :Eb5], amp: 0.5, cutoff: 90

``

    # Supports the same arguments as play:

# Play pattern of notes with specific times

``

    play_pattern_timed  notes (list), times (list_or_number)

Play each note in a list of notes one after another with specified durations. The notes should be a list of MIDI numbers, symbols such as :E4 or chords such as chord(:A3, :major) - identical to the first parameter of the play function. The times should be a list of durations for each note in beats.

If the list of times is smaller than the number of notes, the list is repeated again. If the list of times is longer than the number of notes, then some of the times are ignored. See examples for more detail.

Accepts optional args for modification of the synth being played. See each synth’s documentation for synth-specific opts. See `use_synth` and `with_synth` for changing the current synth.

Introduced in v2.0

## Options

amp: | The amplitude of the note
amp_slide: | The duration in beats for amplitude changes to take place
pan: | The stereo position of the sound. -1 is left, 0 is in the middle and 1 is on the right. You may use a value in between -1 and 1 such as 0.25
pan_slide: | The duration in beats for the pan value to change
attack: | Amount of time (in beats) for sound to reach full amplitude (attack_level). A short attack (i.e. 0.01) makes the initial part of the sound very percussive like a sharp tap. A longer attack (i.e 1) fades the sound in gently.
decay: | Amount of time (in beats) for the sound to move from full amplitude (attack_level) to the sustain amplitude (sustain_level).
sustain: | Amount of time (in beats) for sound to remain at sustain level amplitude. Longer sustain values result in longer sounds. Full length of sound is attack + decay + sustain + release.
release: | Amount of time (in beats) for sound to move from sustain level amplitude to silent. A short release (i.e. 0.01) makes the final part of the sound very percussive (potentially resulting in a click). A longer release (i.e 1) fades the sound out gently.
attack_level: | Amplitude level reached after attack phase and immediately before decay phase
decay_level: | Amplitude level reached after decay phase and immediately before sustain phase. Defaults to sustain_level unless explicitly set
sustain_level: | Amplitude level reached after decay phase and immediately before release phase.
env_curve: | Select the shape of the curve between levels in the envelope. 1=linear, 2=exponential, 3=sine, 4=welch, 6=squared, 7=cubed
slide: | Default slide time in beats for all slide opts. Individually specified slide opts will override this value
pitch: | Pitch adjustment in semitones. 1 is up a semitone, 12 is up an octave, -12 is down an octave etc. Decimal numbers can be used for fine tuning.
on: | If specified and false/nil/0 will stop the synth from being played. Ensures all opts are evaluated.

## Examples

# Example 1

``

    play_pattern_timed [40, 42, 44], [1, 2, 3]

    play 40, sustain: 1
    sleep 1
    play 42, sustain: 2
    sleep 2
    play 44, sustain: 3
    sleep 3

``

    # same as:

# Example 2

``

    play_pattern_timed [40, 42, 44, 46, 49], [1, 0.5]

    play 40, sustain: 1
    sleep 1
    play 42, sustain: 0.5
    sleep 0.5
    play 44, sustain: 1
    sleep 1
    play 46, sustain: 0.5
    sleep 0.5
    play 49, sustain: 1
    sleep 1

``

    # same as:

# Example 3

``

    play_pattern_timed [40, 42, 44, 46], [0.5]

    play 40, sustain: 0.5
    sleep 0.5
    play 42, sustain: 0.5
    sleep 0.5
    play 44, sustain: 0.5
    sleep 0.5
    play 46, sustain: 0.5
    sleep 0.5

``

    # same as:

# Example 4

``

    play_pattern_timed [40, 42, 44], [1, 2, 3, 4, 5]

    play 40, sustain: 1
    sleep 1
    play 42, sustain: 2
    sleep 2
    play 44, sustain: 3
    sleep 3

``

    # same as:

# Example 5

``

    play_pattern_timed [40, 42, 44], [1, 2, 3], sustain: 0

    play 40
    sleep 1
    play 42
    sleep 2
    play 44
    sleep 3

``

    # effectively same as:

# Display a message in the output pane

``

    print  output (anything)

Displays the information you specify as a string inside the output pane. This can be a number, symbol, or a string itself. Useful for debugging. Synonym for `puts`.

Introduced in v2.0

## Examples

# Example 1

``

    print "hello there"

``

    #=> will print the string "hello there" to the output pane

# Example 2

``

    print 5

``

    #=> will print the number 5 to the output pane

# Example 3

``

    print foo

``

    #=> will print the contents of foo to the output pane

# Display a message in the output pane

``

    puts  output (anything)

Displays the information you specify as a string inside the output pane. This can be a number, symbol, or a string itself. Useful for debugging. Synonym for `print`.

Introduced in v2.0

## Examples

# Example 1

``

    print "hello there"

``

    #=> will print the string "hello there" to the output pane

# Example 2

``

    print 5

``

    #=> will print the number 5 to the output pane

# Example 3

``

    print foo

``

    #=> will print the contents of foo to the output pane

# Quantise a value to resolution

``

    quantise  n (number), step (positive_number)

Round value to the nearest multiple of step resolution.

Introduced in v2.1

## Examples

# Example 1

``

    quantise(10, 1)

``

    # 10 is already a multiple of 1, so returns 10

# Example 2

``

    quantise(10, 1.1)

``

    # Returns 9.9 which is 1.1 * 9

# Example 3

``

    quantise(13.3212, 0.1)

``

    # 13.3

# Example 4

``

    quantise(13.3212, 0.2)

``

    # 13.4

# Example 5

``

    quantise(13.3212, 0.3)

``

    # 13.2

# Example 6

``

    quantise(13.3212, 0.5)

``

    # 13.5

# Create a ramp vector

``

    ramp  list (array)

Create a new immutable ramp vector from args. Indexes always return first or last value if out of bounds.

Introduced in v2.6

## Examples

# Example 1

``

    (ramp 1, 2, 3)[0]

``

    #=> 1

# Example 2

``

    (ramp 1, 2, 3)[1]

``

    #=> 2

# Example 3

``

    (ramp 1, 2, 3)[2]

``

    #=> 3

# Example 4

``

    (ramp 1, 2, 3)[3]

``

    #=> 3

# Example 5

``

    (ramp 1, 2, 3)[1000]

``

    #=> 3

# Example 6

``

    (ramp 1, 2, 3)[-1]

``

    #=> 1

# Example 7

``

    (ramp 1, 2, 3)[-1000]

``

    #=> 1

# Generate a random float below a value

``

    rand  max (number_or_range)

Given a max number, produces a float between `0` and the supplied max value. If max is a range, produces a float within the range. With no args returns a random value between `0` and `1`.

Introduced in v2.0

## Example

# Example 1

``

    print rand(0.5)

``

    #=> will print a number like 0.375030517578125 to the output pane

# Roll back random generator

``

    rand_back  amount (number)

Roll the random generator back essentially ‘undoing’ the last call to `rand`. You may specify an amount to roll back allowing you to skip back n calls to `rand`.

Introduced in v2.7

## Examples

# Example 1

``

      puts rand

      rand_back

      puts rand
      puts rand

``

    # Basic rand stream rollback

    # prints 0.75006103515625

    # roll random stream back one
    # the result of the next call to rand will be
    # exactly the same as the previous call

    # prints 0.75006103515625 again!
    # prints 0.733917236328125

# Example 2

``

      puts rand
      puts rand
      puts rand
      puts rand

      rand_back(3)

      puts rand
      puts rand

``

    # Jumping back multiple places in the rand stream

    # prints 0.75006103515625
    # prints 0.733917236328125
    # prints 0.464202880859375
    # prints 0.24249267578125

    # roll random stream back three places
    # the result of the next call to rand will be
    # exactly the same as the result 3 calls to
    # rand ago.

    # prints  0.733917236328125 again!
    # prints  0.464202880859375

# Generate a random whole number below a value (exclusive)

``

    rand_i  max (number_or_range)

Given a max number, produces a whole number between `0` and the supplied max value exclusively. If max is a range produces an int within the range. With no args returns either `0` or `1`

Introduced in v2.0

## Example

# Example 1

``

    print rand_i(5)

``

    #=> will print either 0, 1, 2, 3, or 4 to the output pane

# Generate a random whole number without consuming a rand

``

    rand_i_look  max (number_or_range)

Given a max number, produces a whole number between `0` and the supplied max value exclusively. If max is a range produces an int within the range. With no args returns either `0` or `1`.

Does not consume a random value from the stream. Therefore, multiple sequential calls to `rand_i_look` will all return the same value.

Introduced in v2.11

## Examples

# Example 1

``

    print rand_i_look(5)

``

    # will print either 0, 1, 2, 3, or 4 to the output pane

# Example 2

``

    print rand_i_look(5)
    print rand_i_look(5)
    print rand_i_look(5)
    print rand_i(5)

    print rand_i_look(5)

``

    # will print either 0, 1, 2, 3, or 4 to the output pane
    # will print the same number again
    # will print the same number again
    # will still print the same number again
    # (this is the number rand_i_look was 'looking ahead' at)
    # the number is now consumed
    # will print either 0, 1, 2, 3, or 4 to the output pane

# Generate a random number without consuming a rand

``

    rand_look  max (number_or_range)

Given a max number, produces a number between `0` and the supplied max value exclusively. If max is a range produces an int within the range. With no args returns a value between `0` and `1`.

Does not consume a random value from the stream. Therefore, multiple sequential calls to `rand_look` will all return the same value.

Introduced in v2.11

## Examples

# Example 1

``

    print rand_look(0.5)

``

    # will print a number like 0.375030517578125 to the output pane

# Example 2

``

    print rand_look(0.5)
    print rand_look(0.5)
    print rand_look(0.5)
    print rand(0.5)

    print rand_look(0.5)

``

    # will print a number like 0.375030517578125 to the output pane
    # will print the same number again
    # will print the same number again
    # will still print the same number again
    # (this is the number rand_look was 'looking ahead' at)
    # the number is now consumed
    # will print a new number like 0.3669586181640625 to the output pane

# Reset rand generator to last seed

``

    rand_reset

Resets the random stream to the last specified seed. See `use_random_seed` for changing the seed.

Introduced in v2.7

## Example

# Example 1

``

    puts rand
      puts rand
      puts rand
      puts rand
      rand_reset
      puts rand

``

    # prints 0.75006103515625
    # prints 0.733917236328125
    # prints 0.464202880859375
    # prints 0.24249267578125
    # reset the random stream
    # prints 0.75006103515625

# Jump forward random generator

``

    rand_skip  amount (number)

Jump the random generator forward essentially skipping the next call to `rand`. You may specify an amount to jump allowing you to skip n calls to `rand`.

Introduced in v2.7

## Examples

# Example 1

``

      puts rand

      rand_skip

      puts rand

``

    # Basic rand stream skip

    # prints 0.75006103515625

    # jump random stream forward one
    # typically the next rand is 0.733917236328125

    # prints 0.464202880859375

# Example 2

``

      puts rand
      puts rand
      puts rand
      puts rand

      rand_reset

      puts rand

      rand_skip(2)

      puts rand 0.24249267578125

``

    # Jumping forward multiple places in the rand stream

    # prints 0.75006103515625
    # prints 0.733917236328125
    # prints 0.464202880859375
    # prints 0.24249267578125

    # reset the random stream

    # prints 0.75006103515625

    # jump random stream forward three places
    # the result of the next call to rand will be
    # exactly the same as if rand had been called
    # three times

# Create a ring buffer with the specified start, finish and step size

``

    range  start (number), finish (number), step_size (number)

Create a new ring buffer from the range arguments (start, finish and step size). Step size defaults to `1`. Indexes wrap around positively and negatively

Introduced in v2.2

## Options

step: | Size of increment between steps; step size.
inclusive: | If set to true, range is inclusive of finish value

## Examples

# Example 1

``

    (range 1, 5)

``

    #=> (ring 1, 2, 3, 4)

# Example 2

``

    (range 1, 5, inclusive: true)

``

    #=> (ring 1, 2, 3, 4, 5)

# Example 3

``

    (range 1, 5, step: 2)

``

    #=> (ring 1, 3)

# Example 4

``

    (range 1, -5, step: 2)

``

    #=> (ring 1, -1, -3)

# Example 5

``

    (range 1, -5, step: 2)[-1]

``

    #=> -3

# Relative frequency ratio to MIDI pitch

``

    ratio_to_pitch  ratio (number)

Convert a frequency ratio to a midi note which when added to a note will transpose the note to match the frequency ratio.

Introduced in v2.7

## Examples

# Example 1

``

    ratio_to_pitch 2

``

    #=> 12.0

# Example 2

``

    ratio_to_pitch 0.5

``

    #=> -12.0

# Random number in centred distribution

``

    rdist  width (number), centre (number)

Returns a random number within the range with width around centre. If optional arg `step:` is used, the result is quantised by step.

Introduced in v2.3

## Options

step: | Step size of value to quantise to.

## Examples

# Example 1

``

    print rdist(1, 0)

``

    #=> will print a number between -1 and 1

# Example 2

``

    print rdist(1)

``

    #=> centre defaults to 0 so this is the same as rdist(1, 0)

# Example 3

``

    loop do
        play :c3, pan: rdist(1)
        sleep 0.125
      end

``

    #=> Will play :c3 with random L/R panning

# Reset all thread locals

``

    reset

All settings such as the current synth, BPM, random stream and tick values will be reset to the values inherited from the parent thread. Consider using `clear` to reset all these values to their defaults.

Introduced in v2.11

## Examples

# Example 1

``

    use_synth :blade
    use_octave 3

    puts "before"
    puts current_synth
    puts current_octave
    puts rand
    puts tick

    reset

    puts "after"
    puts current_synth
    puts current_octave
    puts rand
    puts tick

``

    # Basic Reset

    #=> "before"
    #=> :blade
    #=> 3
    #=> 0.75006103515625
    #=> 0

    #=> "after"
    #=> :beep
    #=> 0
    #=> 0.75006103515625
    #=> 0

# Example 2

``

    Reset remembers defaults from when the thread was created:
    use_synth :blade
    use_octave 3

    puts "before"
    puts current_synth
    puts current_octave
    puts rand
    puts tick

    at do
      use_synth :tb303
      puts rand
      reset
      puts "thread"

      puts current_synth
      puts current_octave

      puts rand
      puts tick
    end

``

    #=> "before"
    #=> :blade
    #=> 3
    #=> 0.75006103515625
    #=> 0

    #=> 0.9287109375

    #=> "thread"

    # The call to reset ensured that the current
    # synth was returned to the the state at the
    # time this thread was started. Thus any calls
    # to use_synth between this line and the start
    # of the thread are ignored
    #=> :blade
    #=> 3

    # The call to reset ensured
    # that the random stream was reset
    # to the same state as it was when
    # the current thread was started
    #=> 0.9287109375
    #=> 0

# Reset main mixer

``

    reset_mixer!

The main mixer is the final mixer that all sound passes through. This fn resets it to its default set - undoing any changes made via set_mixer_control!

Introduced in v2.9

## Example

# Example 1

``

    set_mixer_control! lpf: 70
    sample :loop_amen
    sleep 3
    reset_mixer!
    sample :loop_amen

``

    # LPF cutoff value of main mixer is now 70
    # :loop_amen sample is played with low cutoff

    # mixer is now reset to default values
    # :loop_amen sample is played with normal cutoff

# Determine if note or args is a rest

``

    rest?  note_or_args (number_symbol_or_map)

Given a note or an args map, returns true if it represents a rest and false if otherwise

Introduced in v2.1

## Examples

# Example 1

``

    puts rest? nil

``

    # true

# Example 2

``

    puts rest? :r

``

    # true

# Example 3

``

    puts rest? :rest

``

    # true

# Example 4

``

    puts rest? 60

``

    # false

# Example 5

``

    puts rest? {}

``

    # false

# Example 6

``

    puts rest? {note: :rest}

``

    # true

# Example 7

``

    puts rest? {note: nil}

``

    # true

# Example 8

``

    puts rest? {note: 50}

``

    # false

# Create a ring buffer

``

    ring  list (array)

Create a new immutable ring buffer from args. Indexes wrap around positively and negatively

Introduced in v2.2

## Examples

# Example 1

``

    (ring 1, 2, 3)[0]

``

    #=> 1

# Example 2

``

    (ring 1, 2, 3)[1]

``

    #=> 2

# Example 3

``

    (ring 1, 2, 3)[3]

``

    #=> 1

# Example 4

``

    (ring 1, 2, 3)[-1]

``

    #=> 3

# Generate a random float between two numbers

``

    rrand  min (number), max (number)

Given two numbers, this produces a float between the supplied min and max values exclusively. Both min and max need to be supplied. For random integers, see `rrand_i`. If optional arg `step:` is used, the result is quantised by step.

Introduced in v2.0

## Options

step: | Step size of value to quantise to.

## Examples

# Example 1

``

    print rrand(0, 10)

``

    #=> will print a number like 8.917730007820797 to the output pane

# Example 2

``

    loop do
        play rrand(60, 72)
        sleep 0.125
      end

``

    #=> Will play a random non-integer midi note between C4 (60) and C5 (72) such as 67.3453 or 71.2393

# Generate a random whole number between two points inclusively

``

    rrand_i  min (number), max (number)

Given two numbers, this produces a whole number between the min and max you supplied inclusively. Both min and max need to be supplied. For random floats, see `rrand`

Introduced in v2.0

## Examples

# Example 1

``

    print rrand_i(0, 10)

``

    #=> will print a random number between 0 and 10 (e.g. 4, 0 or 10) to the output pane

# Example 2

``

    loop do
        play rrand_i(60, 72)
        sleep 0.125
      end

``

    #=> Will play a random midi note between C4 (60) and C5 (72)

# Real time conversion

``

    rt  seconds (number)

Real time representation. Returns the amount of beats for the value in real-time seconds. Useful for bypassing any bpm scaling

Introduced in v2.0

## Example

# Example 1

``

    use_bpm 120
      play 50
      sleep 1
      play 62
      sleep rt(1)
      play 72

``

    # modifies all time to be half

    # actually sleeps for half of a second

    # bypasses bpm scaling and sleeps for a second

# Evaluate the code passed as a String as a new Run

``

    run_code  code (string)

Executes the code passed as a string in a new Run. This works as if the code was in a buffer and Run button was pressed.

Introduced in v2.11

## Examples

# Example 1

``

    run_code "sample :ambi_lunar_land"

``

    #=> will play the :ambi_lunar_land sample

# Example 2

``

    run_code "8.times do
    play 60
    sleep 1
    end"

``

    # Works with any amount of code:

    # will play 60 8 times

# Evaluate the contents of the file as a new Run

``

    run_file  filename (path)

Reads the full contents of the file with `path` and executes it in a new Run. This works as if the code in the file was in a buffer and Run button was pressed.

Introduced in v2.11

## Example

# Example 1

``

    run_file "~/path/to/sonic-pi-code.rb"

``

    #=> will run the contents of this file

# 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`, `.flac` or `.mp3` 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.015110842894865981, :index=>0}, {:start=>0.015110842894865981, :finish=>0.030374580804422135, :index=>1}...)

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

# Get sample data

``

    sample_buffer  path (string)

Alias for the `load_sample` method. Loads sample if necessary and returns buffer information.

Introduced in v2.0

## Example

# Example 1

``

    see load_sample

``

# Get duration of sample in beats

``

    sample_duration  path (string)

Given the name of a loaded sample, or a path to a `.wav`, `.wave`, `.aif`, `.aiff`, `.ogg`, `.oga`, `.flac` or `.mp3` file returns the length of time in beats that the sample would play for. `sample_duration` understands and accounts for all the opts you can pass to `sample` which have an effect on the playback duration such as `rate:`. The time returned is scaled to the current BPM.

Note: avoid using `sample_duration` to set the sleep time in `live_loop`s, prefer stretching the sample with the `beat_stretch:` opt or changing the BPM instead. See the examples below for details.

Introduced in v2.0

## Options

rate: | Rate modifier. For example, doubling the rate will halve the duration.
start: | Start position of sample playback as a value from 0 to 1
finish: | Finish position of sample playback as a value from 0 to 1
attack: | Duration of the attack phase of the envelope.
decay: | Duration of the decay phase of the envelope.
sustain: | Duration of the sustain phase of the envelope.
release: | Duration of the release phase of the envelope.
beat_stretch: | Change the rate of the sample so that its new duration matches the specified number of beats.
pitch_stretch: | Change the rate of the sample so that its new duration matches the specified number of beats but attempt to preserve pitch.
rpitch: | Change the rate to shift the pitch up or down the specified number of MIDI notes.

## Examples

# Example 1

``

    puts sample_duration(:loop_garzul)

``

    # Simple use
    # returns 8.0 because this sample is 8 seconds long

# Example 2

``

    use_bpm 120
    puts sample_duration(:loop_garzul)
    use_bpm 90
    puts sample_duration(:loop_garzul)
    use_bpm 21
    puts sample_duration(:loop_garzul)

``

    # The result is scaled to the current BPM

    # => 16.0

    # => 12.0

    # => 2.8

# Example 3

``

    live_loop :avoid_this do
      with_fx :slicer do
        sample :loop_amen
        sleep sample_duration(:loop_amen)
      end
    end

    live_loop :prefer_this do
      use_sample_bpm :loop_amen
      with_fx :slicer do
        sample :loop_amen
        sleep 1
      end
    end

    live_loop :or_this do
      with_fx :slicer do
        sample :loop_amen, beat_stretch: 1
        sleep 1
      end
    end

``

    # Avoid using sample_duration to set the sleep time in live_loops

    # It is possible to use sample_duration to drive the frequency of a live loop.
    # However, if you're using a rhythmical sample such as a drum beat and it isn't
    # in the same BPM as the current BPM, then the FX such as this slicer will be
    # badly out of sync. This is because the slicer slices at the current BPM and
    # this live_loop is looping at a different BPM (that of the sample)

    # Instead prefer to set the BPM of the live_loop to match the sample. It has
    # two benefits. Now our sleep is a nice and simple 1 (as it's one beat).
    # Also, our slicer now works with the beat and sounds much better.

    # Alternatively we can beat_stretch the sample to match the current BPM. This has the
    # side effect of changing the rate of the sample (and hence the pitch). However, the
    # FX works nicely in time and the sleep time is also a simple 1.

# Example 4

``

    sample_duration :loop_garzul, rate: 1

    sample_duration :loop_garzul, rate: 0.5

    sample_duration :loop_garzul, rate: 2

    sample_duration :loop_garzul, rate: -2

    sample_duration :loop_garzul, attack: 1
    sample_duration :loop_garzul, attack: 100
    sample_duration :loop_garzul, attack: 0

    sample_duration :loop_garzul, release: 1
    sample_duration :loop_garzul, release: 100
    sample_duration :loop_garzul, release: 0

    sample_duration :loop_garzul, decay: 1
    sample_duration :loop_garzul, decay: 100
    sample_duration :loop_garzul, decay: 0

    sample_duration :loop_garzul, sustain: 0, attack: 0.5
    sample_duration :loop_garzul, sustain: 0, decay: 0.1
    sample_duration :loop_garzul, sustain: 0, release: 1
    sample_duration :loop_garzul, sustain: 2, attack: 0.5, release: 1

    sample_duration :loop_garzul, sustain: 0, attack: 8, release: 3

    sample_duration :loop_garzul, rate: 10
    sample_duration :loop_garzul, sustain: 0, attack: 0.9, rate: 10

    sample_duration :loop_garzul, rpitch: 12
    sample_duration :loop_garzul, rpitch: -12

    sample_duration :loop_garzul, rpitch: 12, rate: 2

    sample_duration :loop_garzul, beat_stretch: 3
    sample_duration :loop_garzul, beat_stretch: 3, rate: 0.5

    sample_duration :loop_garzul, pitch_stretch: 3
    sample_duration :loop_garzul, pitch_stretch: 3, rate: 0.5

    sample_duration :loop_garzul, start: 0.5
    sample_duration :loop_garzul, start: 0.5, finish: 0.75
    sample_duration :loop_garzul, finish: 0.5, start: 0.75
    sample_duration :loop_garzul, rate: 2, finish: 0.5, start: 0.75

``

    # The standard sample opts are also honoured

    # Playing a sample at standard speed will return standard length
    # => 8.0

    # Playing a sample at half speed will double duration
    # => 16.0

    # Playing a sample at double speed will halve duration
    # => 4.0

    # Playing a sample backwards at double speed will halve duration
    # => 4.0

    # Without an explicit sustain: opt attack: just affects amplitude not duration
    # => 8.0
    # => 8.0
    # => 8.0

    # Without an explicit sustain: opt release: just affects amplitude not duration
    # => 8.0
    # => 8.0
    # => 8.0

    # Without an explicit sustain: opt decay: just affects amplitude not duration
    # => 8.0
    # => 8.0
    # => 8.0

    # With an explicit sustain: opt, if the attack + decay + sustain + release envelope
    # duration is less than the sample duration time, the envelope will shorten the
    # sample time.
    # => 0.5
    # => 0.1
    # => 1.0
    # => 3.5

    # If the envelope duration is longer than the sample it will not affect the
    # sample duration
    # => 8

    # All other opts are taken into account before the comparison with the envelope opts.
    # => 0.8
    # => 0.8 (The duration of the sample is less than the envelope length so wins)

    # The rpitch: opt will modify the rate to shift the pitch of the sample up and down
    # and therefore affects duration.
    # => 4.0
    # => 16

    # The rpitch: and rate: opts combine together.
    # => 2.0

    # The beat_stretch: opt stretches the sample so that its duration matches the value.
    # It also combines with rate:
    # => 3.0
    # => 6.0

    # The pitch_stretch: opt acts identically to beat_stretch when just considering sample
    # duration.
    # => 3.0
    # => 6.0

    # The start: and finish: opts can also shorten the sample duration and also combine
    # with other opts such as rate:
    # => 4.0
    # => 2.0
    # => 2.0
    # => 1.0

# Example 5

``

    sample :loop_amen
    sleep sample_duration(:loop_amen)
    sample :loop_amen

``

    # Triggering samples one after another

    # start the :loop_amen sample
    # wait for the duration of :loop_amen before
    # starting it again

# Free a sample on the synth server

``

    sample_free  path (string)

Frees the memory and resources consumed by loading the sample on the server. Subsequent calls to `sample` and friends will re-load the sample on the server.

You may also specify the same set of source and filter pre-args available to `sample` itself. `sample_free` will then free all matching samples. See `sample`’s docs for more information.

Introduced in v2.9

## Examples

# Example 1

``

    sample :loop_amen
    sleep 2
    sample :loop_amen
    sleep 2
    sample_free :loop_amen
    sample :loop_amen

``

    # The Amen break is now loaded into memory and played

    # The Amen break is not loaded but played from memory

    # The Amen break is freed from memory
    # the Amen break is re-loaded and played

# Example 2

``

    puts sample_info(:loop_amen).to_i
    puts sample_info(:loop_amen).to_i

    sample_free :loop_amen
    puts sample_info(:loop_amen).to_i

``

    # This returns the buffer id of the sample i.e. 1
    # The buffer id remains constant whilst the sample
    # is loaded in memory

    # The Amen break is re-loaded and gets a *new* id.

# Example 3

``

    sample :loop_amen
    sample :ambi_lunar_land
    sleep 2
    sample_free :loop_amen, :ambi_lunar_land
    sample :loop_amen
    sample :ambi_lunar_land

``

    # re-loads and plays amen
    # re-loads and plays lunar land

# Example 4

``

    dir = "/path/to/sample/dir"
    sample_free dir
    sample_free dir, 1
    sample_free dir, :foo
    sample_free dir, /[Bb]ar/

``

    # Using source and filter pre-args

    # frees any loaded samples in "/path/to/sample/dir"
    # frees sample with index 1 in "/path/to/sample/dir"
    # frees sample with name "foo" in "/path/to/sample/dir"
    # frees sample which matches regex /[Bb]ar/ in "/path/to/sample/dir"

# Free all loaded samples on the synth server

``

    sample_free_all

Unloads all samples therefore freeing the memory and resources consumed. Subsequent calls to `sample` and friends will re-load the sample on the server.

Introduced in v2.9

## Example

# Example 1

``

    sample :loop_amen
    sample :ambi_lunar_land
    sleep 2
    sample_free_all
    sample :loop_amen

``

    # load and play :loop_amen
    # load and play :ambi_lunar_land

    # re-loads and plays amen

# Get all sample groups

``

    sample_groups

Return a list of all the sample groups available

Introduced in v2.0

# Get sample information

``

    sample_info  path (string)

Alias for the `load_sample` method. Loads sample if necessary and returns sample information.

Introduced in v2.0

## Example

# Example 1

``

    see load_sample

``

# Test if sample was pre-loaded

``

    sample_loaded?  path (string)

Given a path to a `.wav`, `.wave`, `.aif`, `.aiff`, `.ogg`, `.oga`, `.flac` or `.mp3` file, returns `true` if the sample has already been loaded.

Introduced in v2.2

## Example

# Example 1

``

    load_sample :elec_blip
    puts sample_loaded? :elec_blip
    puts sample_loaded? :misc_burp

``

    # :elec_blip is now loaded and ready to play as a sample
    # prints true because it has been pre-loaded
    # prints false because it has not been loaded

# Get sample names

``

    sample_names  group (symbol)

Return a ring of sample names for the specified group

Introduced in v2.0

# Sample Pack Filter Resolution

``

    sample_paths  pre_args (source_and_filter_types)

Accepts the same pre-args and opts as `sample` and returns a ring of matched sample paths.

Introduced in v2.10

## Examples

# Example 1

``

    sample_paths "/path/to/samples/"

``

    #=> ring of all top-level samples in /path/to/samples

# Example 2

``

    sample_paths "/path/to/samples/**"

``

    #=> ring of all nested samples in /path/to/samples

# Example 3

``

    sample_paths "/path/to/samples/", "foo"
                                                    containing the string "foo" in their filename.

``

    #=> ring of all samples in /path/to/samples

# Create scale

``

    scale  tonic (symbol), name (symbol)

Creates a ring of MIDI note numbers when given a tonic note and a scale name. Also takes an optional `num_octaves:` parameter (octave `1` is the default). If only passed the scale name, the tonic defaults to 0. See examples.

Introduced in v2.0

## Options

num_octaves: | The number of octaves you’d like the scale to consist of. More octaves means a larger scale. Default is 1.

## Examples

# Example 1

``

    puts (scale :C, :major)

``

    # returns the following ring of MIDI note numbers: (ring 60, 62, 64, 65, 67, 69, 71, 72)

# Example 2

``

    play_pattern (scale :C, :major)

``

    # anywhere you can use a list or ring of notes, you can also use scale

# Example 3

``

    play_pattern (scale :C, :major, num_octaves: 2)

``

    # you can use the :num_octaves parameter to get more notes

# Example 4

``

    puts (scale 50, :minor)
    puts (scale 50.1, :minor)
    puts (scale :minor)

``

    # Scales can start with any note:
    #=> (ring 50, 52, 53, 55, 57, 58, 60, 62)
    #=> (ring 50.1, 52.1, 53.1, 55.1, 57.1, 58.1, 60.1, 62.1)
    #=> (ring 0, 2, 3, 5, 7, 8, 10, 12)

# Example 5

``

    live_loop :scale_player do
      play (scale :Eb3, :super_locrian).tick, release: 0.1
      sleep 0.125
    end

``

    # scales are also rings

# Example 6

``

    live_loop :scaled_sample do
      sample :bass_trance_c, rpitch: (scale 0, :minor).tick
      sleep 1
    end

``

    # scales starting with 0 are useful in combination with sample's rpitch:

# Example 7

``

    (scale :C, :diatonic)
    (scale :C, :ionian)
    (scale :C, :major)
    (scale :C, :dorian)
    (scale :C, :phrygian)
    (scale :C, :lydian)
    (scale :C, :mixolydian)
    (scale :C, :aeolian)
    (scale :C, :minor)
    (scale :C, :locrian)
    (scale :C, :hex_major6)
    (scale :C, :hex_dorian)
    (scale :C, :hex_phrygian)
    (scale :C, :hex_major7)
    (scale :C, :hex_sus)
    (scale :C, :hex_aeolian)
    (scale :C, :minor_pentatonic)
    (scale :C, :yu)
    (scale :C, :major_pentatonic)
    (scale :C, :gong)
    (scale :C, :egyptian)
    (scale :C, :shang)
    (scale :C, :jiao)
    (scale :C, :zhi)
    (scale :C, :ritusen)
    (scale :C, :whole_tone)
    (scale :C, :whole)
    (scale :C, :chromatic)
    (scale :C, :harmonic_minor)
    (scale :C, :melodic_minor_asc)
    (scale :C, :hungarian_minor)
    (scale :C, :octatonic)
    (scale :C, :messiaen1)
    (scale :C, :messiaen2)
    (scale :C, :messiaen3)
    (scale :C, :messiaen4)
    (scale :C, :messiaen5)
    (scale :C, :messiaen6)
    (scale :C, :messiaen7)
    (scale :C, :super_locrian)
    (scale :C, :hirajoshi)
    (scale :C, :kumoi)
    (scale :C, :neapolitan_major)
    (scale :C, :bartok)
    (scale :C, :bhairav)
    (scale :C, :locrian_major)
    (scale :C, :ahirbhairav)
    (scale :C, :enigmatic)
    (scale :C, :neapolitan_minor)
    (scale :C, :pelog)
    (scale :C, :augmented2)
    (scale :C, :scriabin)
    (scale :C, :harmonic_major)
    (scale :C, :melodic_minor_desc)
    (scale :C, :romanian_minor)
    (scale :C, :hindu)
    (scale :C, :iwato)
    (scale :C, :melodic_minor)
    (scale :C, :diminished2)
    (scale :C, :marva)
    (scale :C, :melodic_major)
    (scale :C, :indian)
    (scale :C, :spanish)
    (scale :C, :prometheus)
    (scale :C, :diminished)
    (scale :C, :todi)
    (scale :C, :leading_whole)
    (scale :C, :augmented)
    (scale :C, :purvi)
    (scale :C, :chinese)
    (scale :C, :lydian_minor)
    (scale :C, :blues_major)
    (scale :C, :blues_minor)
    (scale :C, :cargah)
    (scale :C, :buselik)
    (scale :C, :buselik_2)
    (scale :C, :kurdi)
    (scale :C, :rast)
    (scale :C, :acemli_rast)
    (scale :C, :ussak)
    (scale :C, :bayati)
    (scale :C, :bayati_2)
    (scale :C, :isfahan)
    (scale :C, :isfahan_2)
    (scale :C, :hicaz_humayun)
    (scale :C, :hicaz_humayun_2)
    (scale :C, :hicaz)
    (scale :C, :hicaz_2)
    (scale :C, :uzzal)
    (scale :C, :uzzal_2)
    (scale :C, :zirguleli_hicaz)
    (scale :C, :zirguleli_hicaz_2)
    (scale :C, :huseyni)
    (scale :C, :huseyni_2)
    (scale :C, :muhayyer)
    (scale :C, :gulizar)
    (scale :C, :neva)
    (scale :C, :neva_2)
    (scale :C, :tahir)
    (scale :C, :tahir_2)
    (scale :C, :karcigar)
    (scale :C, :suznak)
    (scale :C, :suznak_2)
    (scale :C, :mahur)
    (scale :C, :acem_asiran)
    (scale :C, :nihavend)
    (scale :C, :nihavend_2)
    (scale :C, :sultani_yegah)
    (scale :C, :sultani_yegah_2)
    (scale :C, :kurdili_hicazkar)
    (scale :C, :kurdili_hicazkar_2)
    (scale :C, :kurdili_hicazkar_3)
    (scale :C, :kurdili_hicazkar_4)
    (scale :C, :kurdili_hicazkar_5)
    (scale :C, :zirguleli_suznak)
    (scale :C, :zirguleli_suznak_2)
    (scale :C, :zirguleli_suznak_3)
    (scale :C, :hicazkar)
    (scale :C, :hicazkar_2)
    (scale :C, :evcara)
    (scale :C, :evcara_2)
    (scale :C, :evcara_3)
    (scale :C, :evcara_4)
    (scale :C, :suzidil)
    (scale :C, :suzidil_2)
    (scale :C, :sedaraban)
    (scale :C, :sedaraban_2)
    (scale :C, :segah)
    (scale :C, :segah_2)
    (scale :C, :huzzam)
    (scale :C, :huzzam_2)
    (scale :C, :bayati_araban)
    (scale :C, :acem_kurdi)
    (scale :C, :sehnaz)
    (scale :C, :sehnaz_2)
    (scale :C, :sehnaz_3)
    (scale :C, :sehnaz_4)
    (scale :C, :saba)
    (scale :C, :dugah)
    (scale :C, :dugah_2)
    (scale :C, :evic)
    (scale :C, :evic_2)
    (scale :C, :bestenigar)
    (scale :C, :ferahnak)
    (scale :C, :sevkefza)
    (scale :C, :sevkefza_2)
    (scale :C, :sevkefza_3)
    (scale :C, :ferahfeza)
    (scale :C, :ferahfeza_2)
    (scale :C, :yegah)
    (scale :C, :yegah_2)

``

    # Sonic Pi supports a large range of scales:

# All scale names

``

    scale_names

Returns a ring containing all scale names known to Sonic Pi

Introduced in v2.6

## Example

# Example 1

``

    puts scale_names

``

    #=>  prints a list of all the scales

# Return information about the internal SuperCollider sound server

``

    scsynth_info

Create a map of information about the running audio synthesiser SuperCollider.

Introduced in v2.11

## Example

# Example 1

``

    puts scsynth_info

``

    #=>  (map sample_rate: 44100.0,
    #         sample_dur: 2.2675736545352265e-05,
    #         radians_per_sample: 0.00014247585204429924,
    #         control_rate: 689.0625,
    #         control_dur: 0.001451247138902545,
    #         subsample_offset: 0.0,
    #         num_output_busses: 16.0,
    #         num_input_busses: 16.0,
    #         num_audio_busses: 1024.0,
    #         num_control_busses: 4096.0,
    #         num_buffers: 4096.0)

# Store information in the Time State

``

    set  time_state_key (default), value (anything)

Store information in the Time State for the current time for either the current or any other thread. If called multiple times without an intervening call to `sleep`, `sync`, `set` or `cue`, the last value set will prevail. The value will remain in the Time State until overwritten by another call to `set`, or until Sonic Pi quits.

May be used within a `time_warp` to set past/future events. Does not affect time.

Introduced in v3.0

## Examples

# Example 1

``

    set :foo, 1

``

    #=> Stores the value 1 with key :foo

# Example 2

``

    set :foo, 3
    get[:foo]

``

    # Set :foo to 3
    #=> returns 3

# Example 3

``

    in_thread do
      set :foo, 3
    end

    in_thread do
      puts get[:foo]
    end

``

    # Set :foo to 3

    #=> always returns 3 (no race conditions here!)

# Globally modify audio latency

``

    set_audio_latency!  milliseconds (number)

On some systems with certain configurations (such as wireless speakers, and even a typical Windows environment with the default audio drivers) the audio latency can be large. If all the user is doing is generating audio via calls such as `play`, `synth` and `sample`, then this latency essentially adds to the schedule ahead time and for the most part can be ignored. However, if the user is combining audio with external MIDI/OSC triggered events, this latency can result in a noticeable offset. This function allows you to address this offset by moving the audio events forwards and backwards in time.

So, for example, if your audio system has an audio latency of 150ms, you can compensate for this by setting Sonic Pi’s latency to be a negative value: `set_audio_latency! -150`.

Introduced in v3.1

## Examples

# Example 1

``

    set_audio_latency! 100

``

    # Audio events will now be scheduled 100ms
    # after the schedule ahead time

# Example 2

``

    set_audio_latency! -200

``

    # Audio events will now be scheduled 200ms
    # before the schedule ahead time

# Global Cent tuning

``

    set_cent_tuning!  cent_shift (number)

Globally tune Sonic Pi to play with another external instrument.

Uniformly tunes your music by shifting all notes played by the specified number of cents. To shift up by a cent use a cent tuning of 1. To shift down use negative numbers. One semitone consists of 100 cents.

See `use_cent_tuning` for setting the cent tuning value locally for a specific thread or `live_loop`. This is a global value and will shift the tuning for all notes. It will also persist for the entire session.

Important note: the cent tuning set by `set_cent_tuning!` is independent of any thread-local cent tuning values set by `use_cent_tuning` or `with_cent_tuning`.

Introduced in v2.10

## Example

# Example 1

``

    play 50
    set_cent_tuning! 1
    play 50

``

    # Plays note 50

    # Plays note 50.01

# Set control delta globally

``

    set_control_delta!  time (number)

Specify how many seconds between successive modifications (i.e. trigger then controls) of a specific node on a specific thread. Set larger if you are missing control messages sent extremely close together in time.

Introduced in v2.1

## Example

# Example 1

``

    set_control_delta! 0.1

    s = play 70, release: 8, note_slide: 8
    control s, note: 82

``

    # Set control delta to 0.1

    # Play a note and set the slide time
    # immediately start sliding note.
    # This control message might not be
    # correctly handled as it is sent at the
    # same virtual time as the trigger.
    # If you don't hear a slide, try increasing the
    # control delta until you do.

# Set the tempo for the link metronome.

``

    set_link_bpm!  bpm (number)

Set the tempo for the link metronome in BPM. This is ‘global’ in that the BPM of all threads/live_loops in Link BPM mode will be affected.

Note that this will also change the tempo of all link metronomes connected to the local network. This includes other instances of Sonic Pi, Music Production tools like Ableton Live, VJ tools like Resolume, DJ hardware like the MPC and many iPad music apps.

For a full list of link-compatible apps and devices see: https://www.ableton.com/en/link/products/

Also note that the current thread does not have to be in Link BPM mode for this function to affect the Link clock’s BPM.

To change the current thread/live_loop to Link BPM mode see: `use_bpm :link`

Introduced in v4.0

## Example

# Example 1

``

    use_bpm :link
    set_link_bpm! 30

    8.times do
      bpm += 10
      set_link_bpm! bpm
      sample :loop_amen, beat_stretch: 2
      sleep 2
    end

``

    # Switch to Link BPM mode
    # Change Link BPM to 30

    # Gradually increase the Link BPM

# Control main mixer

``

    set_mixer_control!

The main mixer is the final mixer that all sound passes through. This fn gives you control over the main mixer allowing you to manipulate all the sound playing through Sonic Pi at once. For example, you can sweep a lpf or hpf over the entire sound. You can reset the controls back to their defaults with `reset_mixer!`.

Introduced in v2.7

## Options

pre_amp: | Controls the amplitude of the signal prior to the FX stage of the mixer (prior to lpf/hpf stages). Has slide opts. Default 1.
amp: | Controls the amplitude of the signal after the FX stage. Has slide opts. Default 1.
hpf: | Global hpf FX. Has slide opts. Default 0.
lpf: | Global lpf FX. Has slide opts. Default 135.5.
hpf_bypass: | Bypass the global hpf. 0=no bypass, 1=bypass. Default 0.
lpf_bypass: | Bypass the global lpf. 0=no bypass, 1=bypass. Default 0.
limiter_bypass: | Bypass the final limiter. 0=no bypass, 1=bypass. Default 0.
leak_dc_bypass: | Bypass the final DC leak correction FX. 0=no bypass, 1=bypass. Default 0.

## Example

# Example 1

``

    set_mixer_control! lpf: 30, lpf_slide: 16

``

    # slide the global lpf to 30 over 16 beats.

# Set the bit depth for recording wav files

``

    set_recording_bit_depth!  bit_depth (number)

When you hit the record button, Sonic Pi saves all the audio you can hear into a wav file. By default, this file uses a resolution of 16 bits which is the same as CD audio and good enough for most use cases. However, when working with professional equipment, it is common to want to work with even higher quality files such as 24 bits and even 32 bits. This function allows you to switch the default from 16 to one of 8, 16, 24 or 32.

Introduced in v2.11

## Example

# Example 1

``

    set_recording_bit_depth! 24

``

    # Set recording bit depth to 24

# Set sched ahead time globally

``

    set_sched_ahead_time!  time (number)

Specify how many seconds ahead of time the synths should be triggered. This represents the amount of time between pressing ‘Run’ and hearing audio. A larger time gives the system more room to work with and can reduce performance issues in playing fast sections on slower platforms. However, a larger time also increases latency between modifying code and hearing the result whilst live coding.

Introduced in v2.0

## Example

# Example 1

``

    set_sched_ahead_time! 1

``

    # Code will now run approximately 1 second ahead of audio.

# Set Volume globally

``

    set_volume!  vol (number)

Set the main system volume to `vol`. Accepts a value between `0` and `5` inclusive. Vols greater or smaller than the allowed values are trimmed to keep them within range. Default is `1`.

Introduced in v2.0

## Examples

# Example 1

``

    set_volume! 2

``

    # Set the main system volume to 2

# Example 2

``

    set_volume! -1

``

    # Out of range, so sets main system volume to 0

# Example 3

``

    set_volume! 7

``

    # Out of range, so sets main system volume to 5

# Randomise order of a list

``

    shuffle  list (array)

Returns a new list with the same elements as the original but with their order shuffled. Also works for strings

Introduced in v2.1

## Examples

# Example 1

``

    shuffle [1, 2, 3, 4]

``

    #=> Would return something like: [3, 4, 2, 1]

# Example 2

``

    shuffle "foobar"

``

    #=> Would return something like: "roobfa"

# Wait for beat duration

``

    sleep  beats (number)

Wait for a number of beats before triggering the next command. Beats are converted to seconds by scaling to the current bpm setting.

Introduced in v2.0

## Examples

# Example 1

``

      play 50
      play 55
      play 62

      sleep 1

      play 50
      sleep 0.5
      play 55
      sleep 0.5
      play 62

``

    # Without calls to sleep, all sounds would happen at once:

    # This is actually a chord with all notes played simultaneously

    # Create a gap, to allow a moment's pause for reflection...

    # Let's try the chord again, but this time with sleeps:
    # With the sleeps, we turn a chord into an arpeggio

# Example 2

``

      use_bpm 120
      play 50
      sleep 1
      play 55
      sleep 1
      play 62

      use_bpm 30
      play 50
      sleep 1
      play 55
      sleep 1
      play 62

``

    # The amount of time sleep pauses for is scaled to match the current bpm. The default bpm is 60. Let's double it:

    # This actually sleeps for 0.5 seconds as we're now at double speed

    # Let's go down to half speed:

    # This now sleeps for 2 seconds as we're now at half speed.

# Print a string representing a list of numeric values as a spark graph/bar chart

``

    spark

Given a list of numeric values, this method turns them into a string of bar heights and prints them out. Useful for quickly graphing the shape of an array.

Introduced in v2.5

## Examples

# Example 1

``

    spark (range 1, 5)

``

    #=> ▁▃▅█

# Example 2

``

    spark (range 1, 5).shuffle

``

    #=> ▃█▅▁

# Returns a string representing a list of numeric values as a spark graph/bar chart

``

    spark_graph

Given a list of numeric values, this method turns them into a string of bar heights. Useful for quickly graphing the shape of an array. Remember to use puts so you can see the output. See `spark` for a simple way of printing a spark graph.

Introduced in v2.5

## Examples

# Example 1

``

    puts (spark_graph (range 1, 5))

``

    #=> ▁▃▅█

# Example 2

``

    puts (spark_graph (range 1, 5).shuffle)

``

    #=> ▃█▅▁

# Euclidean distribution for beats

``

    spread  num_accents (number), size (number)

Creates a new ring of boolean values which space a given number of accents as evenly as possible throughout a bar. This is an implementation of the process described in ‘The Euclidean Algorithm Generates Traditional Musical Rhythms’ (Toussaint 2005).

Introduced in v2.4

## Options

rotate: | rotate to the next strong beat allowing for easy permutations of the original rhythmic grouping (see example)

## Examples

# Example 1

``

    (spread 3, 8)

``

    #=> (ring true, false, false, true, false, false, true, false) a spacing of 332

# Example 2

``

    (spread 3, 8, rotate: 1)

``

    #=> (ring true, false, false, true, false, true, false, false) a spacing of 323

# Example 3

``

      live_loop :euclid_beat do
        sample :elec_bong, amp: 1.5 if (spread 3, 8).tick
        sample :perc_snap, amp: 0.8 if (spread 7, 11).look
        sample :bd_haus, amp: 2 if (spread 1, 4).look
        sleep 0.125
      end

``

    # Easily create interesting polyrhythmic beats

    # Spread 3 bongs over 8
    # Spread 7 snaps over 11
    # Spread 1 bd over 4

# Example 4

``

      (spread 2, 5)

      (spread 3, 4)

      (spread 3, 5)

      (spread 3, 7)

      (spread 3, 8)

      (spread 4, 7)

      (spread 4, 9)

      (spread 4, 11)

      (spread 5, 6)

      (spread 5, 7)

      (spread 5, 8)

      (spread 5, 9)

      (spread 5, 11)

      (spread 5, 12)

      (spread 5, 16)

      (spread 7, 8)

      (spread 7, 12)

      (spread 7, 16)

      (spread 9, 16)

      (spread 11, 24)

      (spread 13, 24)

``

    # Spread descriptions from
    # 'The Euclidean Algorithm Generates Traditional Musical Rhythms' (Toussaint 2005).
    # A thirteenth century Persian rhythm called Khafif-e-ramal.

    # The archetypal pattern of the Cumbria from Columbia, as well
    # as a Calypso rhythm from Trinidad

    # When started on the second onset, is another thirteenth
    # century Persian rhythm by the name of Khafif-e-ramal, as well
    # as a Romanian folk-dance rhythm.

    # A ruchenitza rhythm used in a Bulgarian folk-dance.

    # The Cuban tresillo pattern

    # Another Ruchenitza Bulgarian folk-dance rhythm

    # The Aksak rhythm of Turkey.

    # The metric pattern used by Frank Zappa in his piece Outside Now

    # Yields the York-Samai pattern, a popular Arab rhythm, when
    # started on the second onset.

    # The Nawakhat pattern, another popular Arab rhythm.

    # The Cuban cinquillo pattern.

    # A popular Arab rhythm called Agsag-Samai.

    # The metric pattern used by Moussorgsky in Pictures at an
    # Exhibition

    # The Venda clapping pattern of a South African children's
    # song.

    # The Bossa-Nova rhythm necklace of Brazil.

    # A typical rhythm played on the Bendir (frame drum)

    # A common West African bell pattern.

    # A Samba rhythm necklace from Brazil.

    # A rhythm necklace used in the Central African Republic.

    # A rhythm necklace of the Aka Pygmies of Central Africa.

    # Another rhythm necklace of the Aka Pygmies of the upper
    # Sangha.

# Get server status

``

    status

This returns a Hash of information about the synthesis environment. Mostly used for debugging purposes.

Introduced in v2.0

## Example

# Example 1

``

    puts status

``

    # Returns something similar to:
    # {
    #   :ugens=>10,
    #   :synths=>1,
    #   :groups=>7,
    #   :sdefs=>61,
    #   :avg_cpu=>0.20156468451023102,
    #   :peak_cpu=>0.36655542254447937,
    #   :nom_samp_rate=>44100.0,
    #   :act_samp_rate=>44099.9998411752,
    #   :audio_busses=>2,
    #   :control_busses=>0
    # }

# Stop current thread or run

``

    stop

Stops the current thread or if not in a thread, stops the current run. Does not stop any running synths triggered previously in the run/thread or kill any existing sub-threads.

Introduced in v2.5

## Examples

# Example 1

``

    sample :loop_amen
      sleep 0.5
      stop
      sample :loop_garzul

``

    #=> this sample is played until completion

    #=> signal to stop executing this run
    #=> this never executes

# Example 2

``

    in_thread do
        play 60
        stop
        sleep 0.5
        play 72
      end

      play 80

``

    #=> this note plays

    #=> this sleep never happens
    #=> this play never happens

    #=> this plays as the stop only affected the above thread

# Example 3

``

      live_loop :foo
        sample :bd_haus
        sleep 1
        stop
      end

      live_loop :bar
        sample :elec_blip
        sleep 0.25
      end

``

    # Stopping live loops

    # live loop :foo will now stop and no longer loop

    # live loop :bar will continue looping

# Stretch a sequence of values

``

    stretch  list (anything), count (number)

Stretches a list of values each value repeated count times. Always returns a ring regardless of the type of the list that is stretched. To preserve type, consider using `.stretch` i.e. `(ramp 1, 2, 3).stretch(2) #=> (ramp 1, 1, 2, 2, 3, 3)`

Introduced in v2.6

## Examples

# Example 1

``

    (stretch [1,2], 3)

``

    #=> (ring 1, 1, 1, 2, 2, 2)

# Example 2

``

    (stretch [:e2, :c3], 1, [:c2, :d3], 2)

``

    #=> (ring :e2, :c3, :c2, :c2, :d3, :d3)

# Sync with other threads

``

    sync  cue_id (symbol)

Pause/block the current thread until a `cue` heartbeat with a matching `cue_id` is received. When a matching `cue` message is received, unblock the current thread, and continue execution with the virtual time set to match the thread that sent the `cue` heartbeat. The current thread is therefore synced to the `cue` thread. If multiple cue ids are passed as arguments, it will `sync` on the first matching `cue_id`. The BPM of the cueing thread can optionally be inherited by using the bpm_sync: opt.

Introduced in v2.0

## Options

bpm_sync: | Inherit the BPM of the cueing thread. Default is false

## Examples

# Example 1

``

    in_thread do
        sync :foo
        sample :ambi_lunar_land
      end

      sleep 5

      cue :foo

``

    # this parks the current thread waiting for a foo sync message to be received.

    # We send a sync message from the main thread.
    # This then unblocks the thread above and we then hear the sample

# Example 2

``

    in_thread do
        loop do
          cue :tick
          sleep 0.5
        end
      end

      loop do
        sync :tick
        sample :drum_heavy_kick
      end

``

    # Start a metronome thread
    # Loop forever:
    # sending tick heartbeat messages
    # and sleeping for 0.5 beats between ticks

    # We can now play sounds using the metronome.
    # In the main thread, just loop
    # waiting for :tick sync messages
    # after which play the drum kick sample

# Example 3

``

    sync :foo, :bar

``

    # Wait for either a :foo or :bar cue

# Example 4

``

    in_thread do
        loop do
          cue [:foo, :bar, :baz].choose
          sleep 0.5
        end
      end

      in_thread do
        loop do
          sync :foo
          sample :elec_beep
        end
      end

      in_thread do
        loop do
          sync :bar
          sample :elec_flip
        end
      end

      in_thread do
        loop do
          sync :baz
          sample :elec_blup
        end
      end

``

    # Start a metronome thread
    # Loop forever:
    # sending one of three tick heartbeat messages randomly
    # and sleeping for 0.5 beats between ticks

    # We can now play sounds using the metronome:

    # In the main thread, just loop
    # waiting for :foo sync messages
    # after which play the elec beep sample

    # In the main thread, just loop
    # waiting for :bar sync messages
    # after which play the elec flip sample

    # In the main thread, just loop
    # waiting for :baz sync messages
    # after which play the elec blup sample

# Sync and inherit BPM from other threads

``

    sync_bpm  cue_id (symbol)

An alias for `sync` with the `bpm_sync:` opt set to true.

Introduced in v2.10

## Example

# Example 1

``

    See examples for sync

``

# Trigger specific synth

``

    synth  synth_name (symbol)

Trigger specified synth with given opts. Bypasses `current_synth` value, yet still honours `current_synth_defaults`. When using `synth`, the note is no longer an explicit argument but an opt with the key `note:`.

If note: opt is `nil`, `:r` or `:rest`, play is ignored and treated as a rest. Also, if the `on:` opt is specified and returns `false`, or `nil` then play is similarly ignored and treated as a rest.

If the synth name is `nil` behaviour is identical to that of `play` in that the `current_synth` will determine the actual synth triggered.

If a block is given, it is assumed to take one arg which will be the controllable synth node and the body of the block is run in an implicit `in_thread`. This allows for asynchronous control of the synth without interfering with time. For synchronous control capture the result of `synth` as a variable and use that.

Note that the default opts listed are only a guide to the most common opts across all the synths. Not all synths support all the default opts and each synth typically supports many more opts specific to that synth. For example, the `:tb303` synth supports 45 unique opts. For a full list of a synth’s opts see its documentation in the Help system. This can be accessed directly by clicking on the name of the synth and using the shortcut `C-i`

Introduced in v2.0

## Options

amp: | The amplitude of the note
amp_slide: | The duration in beats for amplitude changes to take place
pan: | The stereo position of the sound. -1 is left, 0 is in the middle and 1 is on the right. You may use a value in between -1 and 1 such as 0.25
pan_slide: | The duration in beats for the pan value to change
attack: | Amount of time (in beats) for sound to reach full amplitude (attack_level). A short attack (i.e. 0.01) makes the initial part of the sound very percussive like a sharp tap. A longer attack (i.e 1) fades the sound in gently.
decay: | Amount of time (in beats) for the sound to move from full amplitude (attack_level) to the sustain amplitude (sustain_level).
sustain: | Amount of time (in beats) for sound to remain at sustain level amplitude. Longer sustain values result in longer sounds. Full length of sound is attack + decay + sustain + release.
release: | Amount of time (in beats) for sound to move from sustain level amplitude to silent. A short release (i.e. 0.01) makes the final part of the sound very percussive (potentially resulting in a click). A longer release (i.e 1) fades the sound out gently.
attack_level: | Amplitude level reached after attack phase and immediately before decay phase
decay_level: | Amplitude level reached after decay phase and immediately before sustain phase. Defaults to sustain_level unless explicitly set
sustain_level: | Amplitude level reached after decay phase and immediately before release phase.
env_curve: | Select the shape of the curve between levels in the envelope. 1=linear, 2=exponential, 3=sine, 4=welch, 6=squared, 7=cubed
slide: | Default slide time in beats for all slide opts. Individually specified slide opts will override this value
pitch: | Pitch adjustment in semitones. 1 is up a semitone, 12 is up an octave, -12 is down an octave etc. Decimal numbers can be used for fine tuning.
on: | If specified and false/nil/0 will stop the synth from being played. Ensures all opts are evaluated.

## Examples

# Example 1

``

    use_synth :beep
    play 60

    synth :dsaw, note: 60

``

    # Set current synth to :beep
    # Play note 60 with opt defaults

    # Bypass current synth and play :dsaw
    # with note 60 and opt defaults

# Example 2

``

    synth :fm, note: 60, amp: 0.5

``

    # Play note 60 of the :fm synth with an amplitude of 0.5

# Example 3

``

    use_synth_defaults release: 5
    synth :dsaw, note: 50

``

    # Play note 50 of the :dsaw synth with a release of 5

# Example 4

``

    synth :dsaw, notes: (chord :e3, :minor)

``

    # You can play chords with the notes: opt:

# Example 5

``

    notes = (scale :e3, :minor_pentatonic, num_octaves: 2)

    live_loop :rhyth do
      8.times do
        trig = (spread 3, 7).tick(:rhyth)
        synth :tri, on: trig, note: notes.tick, release: 0.1

        sleep 0.125
      end
    end

    live_loop :rhyth2 do
      8.times do
        trig = (spread 3, 7).tick(:rhyth)
        synth :saw, note: notes.tick, release: 0.1 if trig

        sleep 0.125
      end
    end

``

    # on: vs if

    # Here, we're calling notes.tick
    # every time we attempt to play the synth
    # so the notes rise faster than rhyth2

    # Here, we're calling notes.tick
    # only when the spread says to play
    # so the notes rise slower than rhyth

# Example 6

``

    s = synth :beep, note: :e3, release: 4
    sleep 1
    control s, note: :e5
    sleep 0.5
    synth :dsaw, note: :e3

``

    # controlling a synth synchronously

    # This is triggered after 1.5s from start

# Example 7

``

    synth :beep, note: :e3, release: 4 do |s|
      sleep 1
      control s, note: :e5
    end

    sleep 0.5
    synth :dsaw, note: :e3

``

    # Controlling a synth asynchronously

    # This block is run in an implicit in_thread
    # and therefore is asynchronous

    # This is triggered after 0.5s from start

# Get all synth names

``

    synth_names

Return a list of all the synths available

Introduced in v2.9

# Increment a tick and return value

``

    tick  key (symbol)

Increment the default tick by 1 and return value. Successive calls to `tick` will continue to increment the default tick. If a `key` is specified, increment that specific tick. If an increment `value` is specified, increment key by that value rather than 1. Ticks are `in_thread` and `live_loop` local, so incrementing a tick only affects the current thread’s version of that tick. See `tick_reset` and `tick_set` for directly manipulating the tick vals.

Introduced in v2.6

## Options

step: | The amount to tick up by. Default is 1.
offset: | Offset to add to index returned. Useful when calling tick on lists, rings and vectors to offset the returned value. Default is 0.

## Examples

# Example 1

``

    puts tick
      puts tick
      puts tick
      puts tick

``

    #=> 0
    #=> 1
    #=> 2
    #=> 3

# Example 2

``

    puts tick(:foo)
      puts tick(:foo)
      puts tick(:foo)
      puts tick(:bar)

``

    #=> 0 # named ticks have their own counts
    #=> 1
    #=> 2
    #=> 0 # tick :bar is independent of tick :foo

# Example 3

``

      puts tick
      puts tick
      puts tick
      puts tick(step: 2)
      puts tick(step: 2)
      puts tick(step: 10)
      puts tick

``

    # You can tick by more than increments of 1
    # using the step: opt

    #=> 0
    #=> 1
    #=> 2
    #=> 4
    #=> 6
    #=> 16
    #=> 17

# Example 4

``

      live_loop :fast_tick do
        puts tick
        sleep 2
      end

      live_loop :slow_tick do
        puts tick
        sleep 4

      end

``

    # Each_live loop has its own separate ticks

    # the fast_tick live_loop's tick will
    # be updated every 2 seconds

    # the slow_tick live_loop's tick is
    # totally independent from the fast_tick
    # live loop and will be updated every 4
    # seconds

# Example 5

``

    live_loop :regular_tick do
        puts tick
        sleep 1
      end

      live_loop :random_reset_tick do
        if one_in 3
          tick_reset
          puts "reset tick!"
        end
        puts tick
        sleep 1

      end

``

    # the regular_tick live_loop's tick will
    # be updated every second

    # randomly reset tick

    # this live_loop's tick is totally
    # independent and the reset only affects
    # this tick.

# Example 6

``

      live_loop :scale do
        play [:c, :d, :e, :f, :g].tick
        sleep 1
      end

``

    # Ticks work directly on lists, and will tick through each element
    # However, once they get to the end, they'll return nil

    # play all notes just once, then rests

# Example 7

``

      live_loop :odd_scale do
        tick
        play [:c, :d, :e, :f, :g, :a].tick

        sleep 1
      end

``

    # Normal ticks interact directly with list ticks

    # Increment the default tick
    # this now play every *other* note just once,
    # then rests

# Example 8

``

      live_loop :looped_scale do
        play (ring :c, :d, :e, :f, :g).tick
        sleep 1
      end

``

    # Ticks work wonderfully with rings
    # as the ring ensures the tick wraps
    # round internally always returning a
    # value

    # play all notes just once, then repeats

# Example 9

``

      live_loop :looped_scale do
        play (scale :e3, :minor_pentatonic).tick
        sleep 0.25
      end

``

    # Ticks work wonderfully with scales
    # which are also rings

    # play all notes just once, then repeats

# Reset tick to 0

``

    tick_reset

Reset default tick to 0. If a `key` is referenced, set that tick to 0 instead. Same as calling tick_set(0)

Introduced in v2.6

## Examples

# Example 1

``

      tick
      tick
      tick
      puts look
      tick_set 0
      puts look

``

    # increment default tick a few times

    #=> 2 (default tick is now 2)
    # default tick is now 0
    #=> 0 (default tick is now 0

# Example 2

``

      tick :foo
      tick :foo
      tick :foo
      puts look(:foo)
      tick_set 0
      puts look(:foo)
      tick_set :foo, 0
      puts look(:foo)

``

    # increment tick :foo a few times

    #=> 2 (tick :foo is now 2)
    # default tick is now 0
    #=> 2 (tick :foo is still 2)
    #  reset tick :foo
    #=> 0 (tick :foo is now 0)

# Reset all ticks

``

    tick_reset_all

Reset all ticks - default and keyed

Introduced in v2.6

## Example

# Example 1

``

    tick
      tick
      tick :foo
      tick :foo
      tick :foo
      puts look
      puts look(:foo)
      tick_reset_all
      puts look
      puts look(:foo)

``

    # increment default tick and tick :foo

    #=> 1
    #=> 2

    #=> 0
    #=> 0

# Set tick to a specific value

``

    tick_set  value (number)

Set the default tick to the specified `value`. If a `key` is referenced, set that tick to `value` instead. Next call to `look` will return `value`.

Introduced in v2.6

## Examples

# Example 1

``

    tick_set 40
      puts look

``

    # set default tick to 40
    #=> 40

# Example 2

``

    tick_set :foo, 40
      puts look(:foo)
      puts look

``

    # set tick :foo to 40
    #=> 40 (tick :foo is now 40)
    #=> 0 (default tick is unaffected)

# Shift time forwards or backwards for the given block

``

    time_warp  delta_time (number)

The code within the given block is executed with the specified delta time shift specified in beats. For example, if the delta value is 0.1 then all code within the block is executed with a 0.1 beat delay. Negative values are allowed which means you can move a block of code backwards in time. For example a delta value of -0.1 will execute the code in the block 0.1 beats ahead of time. The time before the block started is restored after the execution of the block.

Given a list of times, run the block once after waiting each given time. If passed an optional params list, will pass each param individually to each block call. If size of params list is smaller than the times list, the param values will act as rings (rotate through). If the block is given 1 arg, the times are fed through. If the block is given 2 args, both the times and the params are fed through. A third block arg will receive the index of the time.

Note that the code within the block is executed synchronously with the code before and after, so all thread locals will be modified inline - as is the case for `with_fx`. However, as time is always restored to the value before `time_warp` started, you can use it to schedule events for the future in a similar fashion to a thread (via `at` or `in_thread`) without having to use an entirely fresh and distinct set of thread locals - see examples.

Also, note that you cannot travel backwards in time beyond the `current_sched_ahead_time`.

If the `time_warp` block is within a `density` block, the delta time is not affected (although all the other times such as sleep and phase durations will be affected) - see example.

`time_warp` is ahead-of-time scheduling within the current thread. See `at` for just-in-time scheduling using multiple isolated threads.

Introduced in v2.11

## Examples

# Example 1

``

    play 70
    sleep 1
    play 75

    time_warp 0.1 do

      play 80
      sleep 0.5
      play 80

    end

    play 70

``

    # shift forwards in time
    #=> plays at time 0

    #=> plays at time 1

    # time shifts forward by 0.1 beats
    #=> plays at 1.1

    #=> plays at 1.6

    # time shifts back by 0.6 beats

    # we now honour the original sleep 1 and the
    # sleep 0.5 within the time_warp block is
    # ignored including the 0.1 shift offset

    #=> plays at 1

# Example 2

``

    play 70
    sleep 1
    play 75

    time_warp -0.1 do

      play 80
      sleep 0.5
      play 80

    end

    play 70

``

    # shift backwards in time

    #=> plays at time 0

    #=> plays at time 1

    # time shifts backwards by 0.1 beats
    #=> plays at 0.9

    #=> plays at 1.4
    # time shifts forward by 0.1 beats

    # we now honour the original sleep 1 and the
    # sleep 0.5 within the time_warp block is
    # ignored, including the -0.1 offset
    #=> plays at 1

# Example 3

``

    puts tick

    sleep 1

    time_warp 2 do
      puts tick
    end

    sleep 0.5

    puts tick

``

    # Ticks count linearly through time_warp

    #=> prints 0 (at time 0)

    #=> prints 1 (at time 3)

    #=> prints 2 (at time 1.5)

# Example 4

``

    puts tick
    sleep 0.5
    puts tick

    time_warp 2 do
      puts tick
      sleep 0.5
      puts tick
    end

    at 3 do
      puts tick
      sleep 0.5
      puts tick
    end

    sleep 0.5

    puts tick

``

    # Comparing time_warp with at

    #=> prints 0 (at time 0)

    #=> prints 1 (at time 0.5)

    #=> prints 2 (at time 2.5)

    #=> prints 3 (at time 3)

    # the at will reset all thread locals
    #=> prints 0 (At time 3.5)

    #=> prints 1 (At time 4)

    #=> prints 4 (at time 1)

# Example 5

``

    density 2 do

      time_warp 0.5 do
        with_fx :slicer, phase: 0.5 do
          play 60
          sleep 1
        end
      end

    end

``

    # Time Warp within Density
    # Typically this will double the BPM and affect all times
    # in addition to looping the internal block twice
    # However, this time is *not* affected and will remain 0.5
    # This phase duration *is* affected and will be 0.25

    # This time *will* be affected by the density and be 0.5

# Example 6

``

    time_warp [0, 1, 2, 3] do
      puts "hello"
    end

``

    # Time Warp with lists of times

    # Will print "hello" at 0, 1, 2, and 3 seconds

    # Notice that the run completes before all the
    # messages have been delivered. This is because it
    # schedules all the messages at once so the program
    # can complete immediately. This is unlike at which
    # would appear to behave similarly, but would wait
    # for all messages to be delivered (on time) before
    # allowing the program to complete.

# Example 7

``

    time_warp [1, 2, 4] do
        play 75
      end

``

    # plays a note after waiting 1 beat,
    # then after 1 more beat,
    # then after 2 more beats (4 beats total)

# Example 8

``

    time_warp [1, 2, 3], [75, 76, 77] do |n|
        play n
      end

``

    # plays 3 different notes

# Example 9

``

    time_warp [1, 2, 3],
          [{:amp=>0.5}, {:amp=> 0.8}] do |p|
        sample :drum_cymbal_open, p
      end

``

    # alternate soft and loud
    # cymbal hits three times

# Example 10

``

    time_warp [0, 1, 2] do |t|
        puts t
      end

``

    # when no params are given to at, the times are fed through to the block
    #=> prints 0, 1, then 2

# Example 11

``

    time_warp [0, 1, 2], [:a, :b] do |t, b|
        puts [t, b]
      end

``

    # If you specify the block with 2 args, it will pass through both the time and the param
    #=> prints out [0, :a], [1, :b], then [2, :a]

# Example 12

``

    time_warp [0, 0.5, 2] do |t, idx|
        puts [t, idx]
      end

``

    # If you specify the block with 2 args, and no param list to at, it will pass through both the time and the index
    #=> prints out [0, 0], [0.5, 1], then [2, 2]

# Example 13

``

    time_warp [0, 0.5, 2], [:a, :b] do |t, b, idx|
        puts [t, b, idx]
      end

``

    # If you specify the block with 3 args, it will pass through the time, the param and the index
    #=> prints out [0, :a, 0], [0.5, :b, 1], then [2, :a, 2]

# Example 14

``

    puts "main: ", rand
    rand_back
    time_warp 1 do

      puts "time_warp:", rand
      puts "time_warp:", rand
      rand_back
    end

    sleep 2
    puts "main: ", rand

``

    # time_warp consumes & interferes with the outer random stream
    # 0.75006103515625

    # the random stream inside the at block is the
    # same as the one in the outer block
    # 0.75006103515625
    # 0.733917236328125
    # undo last call to rand

    # value is now 0.733917236328125 again

# Example 15

``

    time_warp [0, 2] do

      puts tick
      puts tick
    end

``

    # Each block run inherits the same thread locals from the previous one.
    # This means things like the thread local counters can flow through
    # time warp iterations:

    # first time round (after 1 beat) prints:
    # 0
    # 1

    # second time round (after 2 beats) prints:
    # 2
    # 3

# Run block with tuplet timing and optional swing

``

    tuplets  tuplet_list (list)

Runs the block with tuplet timing and optional swing. Each element in the list is considered a tuplet. If the element is a list, each element in the list is considered a tuplet. The duration between each tuplet is specified by the `duration` opt. The `swing` opt specifies the amount of swing to apply to the timing. The `swing_pulse` opt specifies the number of beats between each swing. The `swing_offset` opt specifies the offset from the start of the list to apply the swing.

Introduced in v4.6

## Options

duration: | The duration between each tuplet in beats. Defaults to 1.
swing: | The amount of swing to apply to the timing. Defaults to 0. Note, only affects tuplets that are multiples of the swing_pulse.
swing_pulse: | The number of beats between each swing. Defaults to 2.
swing_offset: | The offset from the start of the list to apply the swing. Defaults to 0.

## Examples

# Example 1

``

    tuplets [70, [72, 72], 70, [82, 82, 82]] do |n|
      play n

    end

``

    # plays 70,
    # then at double speed, 72, 72,
    # followed by another 70,
    # then 82, 82, 82 as triplets

# Example 2

``

    tuplets [70, [72, 72], 70, [82, 82, 82]], swing: 0.2 do |n|
      play n

    end

``

    # plays 70,
    # then at double speed, 72, 72 with a swing of 0.2
    # followed by another 70,
    # then 82, 82, 82 as triplets without swing as 3 is not a multiple of 2

# Block level comment ignoring

``

    uncomment

Evaluates all of the code within the block. Use to reverse the effect of the comment without having to explicitly remove it.

Introduced in v2.0

## Example

# Example 1

``

    uncomment do
        play 50
        sleep 1
        play 62
      end

``

    # starting a block level comment:
    # played
    # sleep happens
    # played

# Enable and disable BPM scaling

``

    use_arg_bpm_scaling  bool (boolean)

Turn synth argument bpm scaling on or off for the current thread. This is on by default. Note, using `rt` for args will result in incorrect times when used after turning arg bpm scaling off.

Introduced in v2.0

## Examples

# Example 1

``

    use_bpm 120
    play 50, release: 2
    sleep 2
    use_arg_bpm_scaling false
    play 50, release: 2
    sleep 2

``

    # release is actually 1 due to bpm scaling
    # actually sleeps for 1 second

    # release is now 2
    # still sleeps for 1 second

# Example 2

``

    use_bpm 120
    play 50, release: rt(2)
    sleep rt(2)
    use_arg_bpm_scaling false
    play 50, release: rt(2)
    sleep rt(2)

``

    # Interaction with rt

    # release is 2 seconds
    # sleeps for 2 seconds

    # ** Warning: release is NOT 2 seconds! **
    # still sleeps for 2 seconds

# Enable and disable arg checks

``

    use_arg_checks  true_or_false (boolean)

When triggering synths, each argument is checked to see if it is sensible. When argument checking is enabled and an argument isn’t sensible, you’ll see an error in the debug pane. This setting allows you to explicitly enable and disable the checking mechanism. See with_arg_checks for enabling/disabling argument checking only for a specific `do`/`end` block.

Introduced in v2.0

## Example

# Example 1

``

    play 50, release: 5
    use_arg_checks false
    play 50, release: 5

``

    # Args are checked

    # Args are not checked

# Set the tempo

``

    use_bpm  bpm (number)

Sets the tempo in bpm (beats per minute) for everything afterwards. Affects all subsequent calls to `sleep` and all temporal synth arguments which will be scaled to match the new bpm. If you wish to bypass scaling in calls to sleep, see the fn `rt`. Also, if you wish to bypass time scaling in synth args see `use_arg_bpm_scaling`. See also `with_bpm` for a block scoped version of `use_bpm`.

For dance music here’s a rough guide for which BPM to aim for depending on your genre:

- Dub: 60-90 bpm
- Hip-hop: 60-100 bpm
- Downtempo: 90-120 bpm
- House: 115-130 bpm
- Techno/trance: 120-140 bpm
- Dubstep: 135-145 bpm
- Drum and bass: 160-180 bpm

Introduced in v2.0

## Example

# Example 1

``

      4.times do
        play 50, attack: 0.5, release: 0.25
        sleep 1
      end

      sleep 2

      use_bpm 120
      4.times do
        play 62, attack: 0.5, release: 0.25
        sleep 1
      end

      sleep 2

      use_bpm 240
      8.times do
        play 62, attack: 0.5, release: 0.25
        sleep 1
      end

``

    # default tempo is 60 bpm

    # attack is 0.5s and release is 0.25s
    # sleep for 1 second

    # sleep for 2 seconds

    # Let's make it go faster...
    # double the bpm

    # attack is scaled to 0.25s and release is now 0.125s
    # actually sleeps for 0.5 seconds

    # sleep for 1 second

    # Let's make it go even faster...
    #  bpm is 4x original speed!

    # attack is scaled to 0.125s and release is now 0.0625s
    # actually sleeps for 0.25 seconds

# Set new tempo as a multiple of current tempo

``

    use_bpm_mul  mul (number)

Sets the tempo in bpm (beats per minute) as a multiplication of the current tempo. Affects all containing calls to `sleep` and all temporal synth arguments which will be scaled to match the new bpm. See also `use_bpm`

Introduced in v2.3

## Example

# Example 1

``

    use_bpm 60
      play 50
      sleep 1
      play 62
      sleep 2
      use_bpm_mul 0.5
      play 50
      sleep 1
      play 62

``

    # Set the BPM to 60

    # Sleeps for 1 seconds

    # Sleeps for 2 seconds
    # BPM is now (60 * 0.5) == 30

    # Sleeps for 2 seconds

# Cent tuning

``

    use_cent_tuning  cent_shift (number)

Uniformly tunes your music by shifting all notes played by the specified number of cents. To shift up by a cent use a cent tuning of 1. To shift down use negative numbers. One semitone consists of 100 cents.

See `with_cent_tuning` for setting the cent tuning value only for a specific `do`/`end` block. To transpose entire semitones see `use_transpose`.

Introduced in v2.9

## Example

# Example 1

``

    play 50
    use_cent_tuning 1
    play 50

``

    # Plays note 50

    # Plays note 50.01

# Enable and disable cue logging

``

    use_cue_logging  true_or_false (boolean)

Enable or disable log messages created on cues. This does not disable the cues themselves, it just stops them from being printed to the log

Introduced in v2.6

## Examples

# Example 1

``

    use_cue_logging true

``

    # Turn on cue messages

# Example 2

``

    use_cue_logging false

``

    # Disable cue messages

# Enable and disable debug

``

    use_debug  true_or_false (boolean)

Enable or disable messages created on synth triggers. If this is set to false, the synths will be silent until debug is turned back on. Silencing debug messages can reduce output noise and also increase performance on slower platforms. See `with_debug` for setting the debug value only for a specific `do`/`end` block.

Introduced in v2.0

## Examples

# Example 1

``

    use_debug true

``

    # Turn on debug messages

# Example 2

``

    use_debug false

``

    # Disable debug messages

# Merge MIDI defaults

``

    use_merged_midi_defaults

Specify new default values to be used by all subsequent calls to `midi_*` fns. Merges the specified values with any previous defaults, rather than replacing them

Introduced in v3.0

## Options

channel: | MIDI channel(s) to send event on
port: | MIDI port(s) to send to
velocity: | Note velocity as a MIDI number.
vel_f: | Velocity as a value between 0 and 1 (will be converted to a MIDI velocity between 0 and 127)
on: | If specified and false/nil/0 will stop the midi note on message from being sent out. (Ensures all opts are evaluated in this call to `midi_note_on` regardless of value).

## Example

# Example 1

``

    midi_note_on :e1

    use_midi_defaults channel: 3, port: "foo"

    midi_note_on :e3

    use_merged_midi_defaults channel: 1

    midi_note_on :e2

``

    # Sends MIDI :e1 note_on with default opts

    # Sends MIDI :e3 note_on to channel 3 on port "foo"

    # Sends MIDI :e2 note_on to channel 1 on port "foo".
    # This is because the call to use_merged_midi_defaults overrode the
    # channel but not the port which got merged in.

# Merge new sample defaults

``

    use_merged_sample_defaults

Specify new default values to be used by all subsequent calls to `sample`. Merges the specified values with any previous defaults, rather than replacing them.

Introduced in v2.9

## Example

# Example 1

``

    sample :loop_amen

    use_merged_sample_defaults amp: 0.5, cutoff: 70

    sample :loop_amen

    use_merged_sample_defaults cutoff: 90

    sample :loop_amen

``

    # plays amen break with default arguments

    # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

    # plays amen break with a cutoff of 90 and and an amp of 0.5 with defaults for rest of args

# Merge synth defaults

``

    use_merged_synth_defaults

Specify synth arg values to be used by any following call to play. Merges the specified values with any previous defaults, rather than replacing them.

Introduced in v2.0

## Examples

# Example 1

``

    play 50

    use_merged_synth_defaults amp: 0.5
    play 50

    use_merged_synth_defaults cutoff: 80
    play 50

    use_merged_synth_defaults amp: 0.7
    play 50

``

    #=> Plays note 50

    #=> Plays note 50 with amp 0.5

    #=> Plays note 50 with amp 0.5 and cutoff 80

    #=> Plays note 50 with amp 0.7 and cutoff 80

# Example 2

``

    use_synth_defaults amp: 0.5, cutoff: 80, pan: -1
    use_merged_synth_defaults amp: 0.7
    play 50

``

    #=> Plays note 50 with amp 0.7, cutoff 80 and pan -1

# Use new MIDI defaults

``

    use_midi_defaults

Specify new default values to be used by all subsequent calls to `midi_*` fns. Will remove and override any previous defaults.

Introduced in v3.0

## Options

channel: | MIDI channel(s) to send event on
port: | MIDI port(s) to send to
velocity: | Note velocity as a MIDI number.
vel_f: | Velocity as a value between 0 and 1 (will be converted to a MIDI velocity between 0 and 127)
on: | If specified and false/nil/0 will stop the midi note on message from being sent out. (Ensures all opts are evaluated in this call to `midi_note_on` regardless of value).

## Example

# Example 1

``

    midi_note_on :e1

    use_midi_defaults channel: 3, port: "foo"

    midi_note_on :e3

    use_midi_defaults channel: 1

    midi_note_on :e2

``

    # Sends MIDI :e1 note_on with default opts

    # Sends MIDI :e3 note_on to channel 3 on port "foo"

    # Sends MIDI :e2 note_on to channel 1. Note that the port is back to the default and no longer "foo".

# Enable and disable MIDI logging

``

    use_midi_logging  true_or_false (boolean)

Enable or disable log messages created on MIDI functions. This does not disable the MIDI functions themselves, it just stops them from being printed to the log

Introduced in v3.0

## Examples

# Example 1

``

    use_midi_logging true

``

    # Turn on MIDI logging

# Example 2

``

    use_midi_logging false

``

    # Disable MIDI logging

# Note octave transposition

``

    use_octave  octave_shift (number)

Transposes your music by shifting all notes played by the specified number of octaves. To shift up by an octave use a transpose of 1. To shift down use negative numbers. See `with_octave` for setting the octave shift only for a specific `do`/`end` block. For transposing the notes within the octave range see `use_transpose`.

Introduced in v2.9

## Examples

# Example 1

``

    play 50
    use_octave 1
    play 50

``

    # Plays note 50

    # Plays note 62

# Example 2

``

    play 62
    use_octave -1
    play 62
    use_octave 2
    play 62

``

    # You may change the transposition multiple times:
    # Plays note 62

    # Plays note 50

    # Plays note 86

# Set the default hostname and port number for outgoing OSC messages.

``

    use_osc  hostname (string), port (number)

Sets the destination host and port that `osc` will send messages to. If no port number is specified - will default to port 4560 (Sonic Pi’s default OSC listening port).

OSC (Open Sound Control) is a simple way of passing messages between two separate programs on the same computer or even on different computers via a local network or even the internet. `use_osc` allows you to specify which computer (`hostname`) and program (`port`) to send messages to.

It is possible to send messages to the same computer by using the host name `"localhost"`.

This is a thread-local setting - therefore each thread (or live loop) can have their own separate `use_osc` values.

Note that calls to `osc_send` will ignore these values.

Introduced in v3.0

## Examples

# Example 1

``

    use_osc "localhost", 7000
    osc "/foo/bar"

``

    # Send a simple OSC message to another program on the same machine

    # Specify port 7000 on this machine
    # Send an OSC message with path "/foo/bar"
    # and no arguments

# Example 2

``

    use_osc "localhost", 7000
    osc "/foo/bar" 1, 3.89, "baz"

``

    # Send an OSC message with arguments to another program on the same machine

    # Specify port 7000 on this machine
    # Send an OSC message with path "/foo/bar"
    # and three arguments:
    # 1) The whole number (integer) 1
    # 2) The fractional number (float) 3.89
    # 3) The string "baz"

# Example 3

``

    use_osc "10.0.1.5", 7000
    osc "/foo/bar" 1, 3.89, "baz"

``

    # Send an OSC message with arguments to another program on a different machine

    # Specify port 7000 on the machine with address 10.0.1.5
    # Send an OSC message with path "/foo/bar"
    # and three arguments:
    # 1) The whole number (integer) 1
    # 2) The fractional number (float) 3.89
    # 3) The string "baz"

# Example 4

``

    use_osc "localhost", 7000
    osc "/foo/bar"
    osc "/foo/baz"

    use_osc "localhost", 7005
    osc "/foo/bar"
    osc "/foo/baz"

``

    # use_osc only affects calls to osc until the next call to use_osc

    # Specify port 7000 on this machine
    # Send an OSC message to port 7000
    # Send another OSC message to port 7000

    # Specify port 7005 on this machine
    # Send an OSC message to port 7005
    # Send another OSC message to port 7005

# Example 5

``

    use_osc "localhost", 7000

    live_loop :foo do
      osc "/foo/bar"
      sleep 1
    end

    live_loop :bar do
      use_osc "localhost", 7005

      osc "/foo/bar"
      sleep 1
    end

    use_osc "localhost", 7010
    osc "/foo/baz"

``

    # threads may have their own use_osc value

    # Specify port 7000 on this machine

    # Thread inherits outside use_osc values
    # and therefore sends OSC messages to port 7000

    # Override OSC hostname and port for just this
    # thread (live loop :bar). Live loop :foo is
    # unaffected.

    # Send OSC messages to port 7005

    # Specify port 7010
    # Send another OSC message to port 7010
    # Note that neither live loops :foo or :bar
    # are affected (their use_osc values are
    # independent and isolated.

# Enable and disable OSC logging

``

    use_osc_logging  true_or_false (boolean)

Enable or disable log messages created on OSC functions. This does not disable the OSC functions themselves, it just stops them from being printed to the log

Introduced in v3.0

## Examples

# Example 1

``

    use_osc_logging true

``

    # Turn on OSC logging

# Example 2

``

    use_osc_logging false

``

    # Disable OSC logging

# Set random seed generator to known seed

``

    use_random_seed  seed (number)

Resets the random number generator to the specified seed. All subsequently generated random numbers and randomisation functions such as `shuffle` and `choose` will use this new generator and the current generator is discarded. Use this to change the sequence of random numbers in your piece in a way that can be reproduced. Especially useful if combined with iteration. See examples.

Introduced in v2.0

## Examples

# Example 1

``

      use_random_seed 1
      puts rand
      use_random_seed 1
      puts rand

``

    # Basic usage

    # reset random seed to 1
    # => 0.733917236328125
    # reset random seed back to 1
    #=> 0.733917236328125

# Example 2

``

      notes = (scale :eb3, :minor_pentatonic)

      with_fx :reverb do
        live_loop :repeating_melody do

          use_random_seed 300

          8.times do

            play notes.choose, release: 0.1

            sleep 0.125
          end
        end
      end

``

    # Generating melodies
    # Create a set of notes to choose from.
    # Scales work well for this

    # Create a live loop

    # Set the random seed to a known value every
    # time around the loop. This seed is the key
    # to our melody. Try changing the number to
    # something else. Different numbers produce
    # different melodies

    # Now iterate a number of times. The size of
    # the iteration will be the length of the
    # repeating melody.

    # 'Randomly' choose a note from our ring of
    # notes. See how this isn't actually random
    # but uses a reproducible method! These notes
    # are therefore repeated over and over...

# Change how random numbers are chosen

``

    use_random_source  noise_type (symbol)

Sets the random number source to be one of `:white`, `:pink`, `:light_pink`, `:dark_pink` or `:perlin`.

`:white` is totally random - between 0 and 1, you can expect an even spread of values around 0.1, 0.2, 0.3 etc. This means that jumping around within the range (including large jumps) is expected.

`:pink` is more likely to produce values in the middle of the range and less likely to produce values at the extremes. Between 0 and 1 you expect to see a concentration of values around 0.5. This can make random melodies a little bit more smooth.

`:perlin` is a special kind of noise which produces gradients, a bit like a mountain landscape. Large jumps are much less likely and you will tend to see lots of smooth motion going either up or down

`:light_pink` is halfway between white noise and pink noise - more random and jumpy

`:dark_pink` is halfway between pink noise and brown noise - less jumpy with smoother slopes

You can see the ‘buckets’ that the numbers between 0 and 1 fall into with the following code:

        use_random_source :white
        puts 10000.times.collect { rand.round(1) }.tally.sort
        use_random_source :pink
        puts 10000.times.collect { rand.round(1) }.tally.sort
        use_random_source :perlin
        puts 10000.times.collect { rand.round(1) }.tally.sort

Introduced in v3.3

## Example

# Example 1

``

    use_random_source :white
      rand_reset
      puts rand
      puts rand
      puts rand
      rand_reset
      use_random_source :pink
      puts rand
      puts rand
      rand_reset
      use_random_source :perlin
      puts rand
      puts rand

      with_random_source :white do
        puts rand
      end

      puts rand

``

    # use white noise as the distribution (default)
    # reset random seed
    # => 0.75006103515625
    # => 0.733917236328125
    # => 0.464202880859375
    # reset it again
    # use pink noise as the distribution
    # => 0.47808837890625
    # => 0.56011962890625
    # reset it
    # use perlin noise as the distribution
    # => 0.546478271484375
    # => 0.573150634765625

    # use white noise just for this block
    # => 0.464202880859375

    # => 0.597015380859375
    # notice how the last generator (perlin) is restored

# Set sched ahead time to 0 for the current thread

``

    use_real_time

Set sched ahead time to 0 for the current thread. Shorthand for `use_sched_ahead_time 0`.

See `use_sched_ahead_time` for a version of this function which allows you to set the schedule ahead time to any arbitrary value. Note, `use_real_time` will override any value set with `set_sched_ahead_time!` for the current thread.

Introduced in v3.0

## Example

# Example 1

``

    use_real_time

``

    # Code will now produce sound without a scheduling delay.

# Sample-duration-based bpm modification

``

    use_sample_bpm  string_or_number (sample_name_or_duration)

Modify bpm so that sleeping for 1 will sleep for the duration of the sample.

Introduced in v2.1

## Options

num_beats: | The number of beats within the sample. By default this is 1.

## Examples

# Example 1

``

    use_sample_bpm :loop_amen

    live_loop :dnb do
      sample :bass_dnb_f
      sample :loop_amen
      sleep 1
    end

``

    #Set bpm based on :loop_amen duration

    #`sleep`ing for 1 actually sleeps for duration of :loop_amen

# Example 2

``

    use_sample_bpm :loop_amen, num_beats: 4

    live_loop :dnb do
      sample :bass_dnb_f
      sample :loop_amen
      sleep 4

    end

``

    # Set bpm based on :loop_amen duration
    # but also specify that the sample duration
    # is actually 4 beats long.

    #`sleep`ing for 4 actually sleeps for duration of :loop_amen
    # as we specified that the sample consisted of
    # 4 beats

# Use new sample defaults

``

    use_sample_defaults

Specify new default values to be used by all subsequent calls to `sample`. Will remove and override any previous defaults.

Introduced in v2.5

## Example

# Example 1

``

    sample :loop_amen

    use_sample_defaults amp: 0.5, cutoff: 70

    sample :loop_amen

    use_sample_defaults cutoff: 90

    sample :loop_amen

``

    # plays amen break with default arguments

    # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

    # plays amen break with a cutoff of 90 and defaults for rest of args - note that amp is no longer 0.5

# Set sched ahead time for the current thread

``

    use_sched_ahead_time  time (number)

Specify how many seconds ahead of time the synths should be triggered. This represents the amount of time between pressing ‘Run’ and hearing audio. A larger time gives the system more room to work with and can reduce performance issues in playing fast sections on slower platforms. However, a larger time also increases latency between modifying code and hearing the result whilst live coding.

See `set_sched_ahead_time!` for a global version of this function. Note, `use_sched_ahead_time` will override any value set with `set_sched_ahead_time!` for the current thread.

See `use_real_time` for a simple way of setting the schedule ahead time to 0.

Introduced in v3.0

## Examples

# Example 1

``

    use_sched_ahead_time 1

``

    # Code will now run approximately 1 second ahead of audio.

# Example 2

``

    live_loop :foo do
      use_sched_ahead_time 1
      play 70
      sleep 1
    end

    live_loop :foo do
      use_sched_ahead_time 0.5
      play 82
      sleep 1
    end

``

    # Each thread can have its own sched ahead time

    # Note 70 will be played with 1 second latency

    # Note 70 will be played with 0.5 second latency

# Switch current synth

``

    use_synth  synth_name (symbol)

Switch the current synth to `synth_name`. Affects all further calls to `play`. See `with_synth` for changing the current synth only for a specific `do`/`end` block.

Introduced in v2.0

## Example

# Example 1

``

    play 50
    use_synth :mod_sine
    play 50

``

    # Plays with default synth

    # Plays with mod_sine synth

# Use new synth defaults

``

    use_synth_defaults

Specify new default values to be used by all subsequent calls to `play`. Will remove and override any previous defaults.

Introduced in v2.0

## Example

# Example 1

``

    play 50

    use_synth_defaults amp: 0.5, cutoff: 70

    play 50

    use_synth_defaults cutoff: 90

    play 50

``

    # plays note 50 with default arguments

    # plays note 50 with an amp of 0.5, cutoff of 70 and defaults for rest of args

    # plays note 50 with a cutoff of 90 and defaults for rest of args - note that amp is no longer 0.5

# Inhibit synth triggers if too late

``

    use_timing_guarantees  bool (true_or_false)

If set to true, synths will not trigger if it is too late. If false, some synth triggers may be late.

Introduced in v2.10

## Examples

# Example 1

``

    use_timing_guarantees true

    sample :loop_amen

``

    #=> if time is behind by any margin, this will not trigger

# Example 2

``

    use_timing_guarantees false

    sample :loop_amen

``

    #=> unless time is too far behind, this will trigger even when late.

# Note transposition

``

    use_transpose  note_shift (number)

Transposes your music by shifting all notes played by the specified amount. To shift up by a semitone use a transpose of 1. To shift down use negative numbers. See `with_transpose` for setting the transpose value only for a specific `do`/`end` block. To transpose entire octaves see `use_octave`.

Introduced in v2.0

## Examples

# Example 1

``

    play 50
    use_transpose 1
    play 50

``

    # Plays note 50

    # Plays note 51

# Example 2

``

    play 62
    use_transpose -12
    play 62
    use_transpose 3
    play 62

``

    # You may change the transposition multiple times:
    # Plays note 62

    # Plays note 50

    # Plays note 65

# Use alternative tuning systems

``

    use_tuning  tuning (symbol), fundamental_note (symbol_or_number)

In most music we make semitones by dividing the octave into 12 equal parts, which is known as equal temperament. However there are lots of other ways to tune the 12 notes. This method adjusts each midi note into the specified tuning system. Because the ratios between notes aren’t always equal, be careful to pick a centre note that is in the key of the music you’re making for the best sound. Currently available tunings are `:just`, `:pythagorean`, `:meantone` and the default of `:equal`

Introduced in v2.6

## Examples

# Example 1

``

    play :e4
    use_tuning :just, :c
    play :e4

    play 64

``

    # Plays note 64

    # Plays note 63.8631
    # transparently changes midi notes too
    # Plays note 63.8631

# Example 2

``

    play 64
    use_tuning :just
    play 64
    use_tuning :equal
    play 64

``

    # You may change the tuning multiple times:
    # Plays note 64

    # Plays note 63.8631

    # Plays note 64

# Create a vector

``

    vector  list (array)

Create a new immutable vector from args. Out of range indexes return nil.

Introduced in v2.6

## Examples

# Example 1

``

    (vector 1, 2, 3)[0]

``

    #=> 1

# Example 2

``

    (vector 1, 2, 3)[1]

``

    #=> 2

# Example 3

``

    (vector 1, 2, 3)[2]

``

    #=> 3

# Example 4

``

    (vector 1, 2, 3)[3]

``

    #=> nil

# Example 5

``

    (vector 1, 2, 3)[1000]

``

    #=> nil

# Example 6

``

    (vector 1, 2, 3)[-1]

``

    #=> nil

# Example 7

``

    (vector 1, 2, 3)[-1000]

``

    #=> nil

# Get current version information

``

    version

Return information representing the current version of Sonic Pi. This information may be further inspected with `version.major`, `version.minor`, `version.patch` and `version.dev`

Introduced in v2.0

## Examples

# Example 1

``

    puts version

``

    # => Prints out the current version such as v2.0.1

# Example 2

``

    puts version.major

``

    # => Prints out the major version number such as 2

# Example 3

``

    puts version.minor

``

    # => Prints out the minor version number such as 0

# Example 4

``

    puts version.patch

``

    # => Prints out the patch level for this version such as 0

# Get virtual time

``

    vt

Get the virtual time of the current thread.

Introduced in v2.1

## Example

# Example 1

``

    puts vt
       sleep 1
       puts vt

``

    # prints 0

    # prints 1

# Wait for duration

``

    wait  beats (number)

Synonym for `sleep` - see `sleep`

Introduced in v2.0

# Block-level enable and disable BPM scaling

``

    with_arg_bpm_scaling

Turn synth argument bpm scaling on or off for the supplied block. Note, using `rt` for args will result in incorrect times when used within this block.

Introduced in v2.0

## Examples

# Example 1

``

    use_bpm 120
    play 50, release: 2
    sleep 2
    with_arg_bpm_scaling false do
      play 50, release: 2
      sleep 2
    end

``

    # release is actually 1 due to bpm scaling
    # actually sleeps for 1 second

    # release is now 2
    # still sleeps for 1 second

# Example 2

``

    use_bpm 120
    play 50, release: rt(2)
    sleep rt(2)
    with_arg_bpm_scaling false do
      play 50, release: rt(2)
      sleep rt(2)
    end

``

    # Interaction with rt

    # release is 2 seconds
    # sleeps for 2 seconds

    # ** Warning: release is NOT 2 seconds! **
    # still sleeps for 2 seconds

# Block-level enable and disable arg checks

``

    with_arg_checks  true_or_false (boolean)

Similar to `use_arg_checks` except only applies to code within supplied `do`/`end` block. Previous arg check value is restored after block.

Introduced in v2.0

## Example

# Example 1

``

    use_arg_checks true

    play 80, cutoff: 100

    with_arg_checks false do

      play 50, release: 3
      sleep 1
      play 72
    end

    play 90

``

    # Turn on arg checking:

    # Args are checked

    #Arg checking is now disabled
    # Args are not checked

    # Arg is not checked

    # Arg checking is re-enabled
    # Args are checked

# Set the tempo for the code block

``

    with_bpm  bpm (number)

Sets the tempo in bpm (beats per minute) for everything in the given block. Affects all containing calls to `sleep` and all temporal synth arguments which will be scaled to match the new bpm. See also `use_bpm`

For dance music here’s a rough guide for which BPM to aim for depending on your genre:

- Dub: 60-90 bpm
- Hip-hop: 60-100 bpm
- Downtempo: 90-120 bpm
- House: 115-130 bpm
- Techno/trance: 120-140 bpm
- Dubstep: 135-145 bpm
- Drum and bass: 160-180 bpm

Introduced in v2.0

## Example

# Example 1

``

      4.times do
        sample :drum_bass_hard
        sleep 1
      end

      sleep 5

      with_bpm 120 do
        4.times do
          sample :drum_bass_hard
          sleep 1
        end
      end

      sleep 5

      4.times do
        sample :drum_bass_hard
        sleep 1
      end

``

    # default tempo is 60 bpm

    # sleeps for 1 second

    # sleeps for 5 seconds

    # with_bpm sets a tempo for everything between do ... end (a block)
    # Hear how it gets faster?
    # set bpm to be twice as fast

    # now sleeps for 0.5 seconds

    # bpm goes back to normal

    # sleeps for 1 second

# Set new tempo as a multiple of current tempo for block

``

    with_bpm_mul  mul (number)

Sets the tempo in bpm (beats per minute) for everything in the given block as a multiplication of the current tempo. Affects all containing calls to `sleep` and all temporal synth arguments which will be scaled to match the new bpm. See also `with_bpm`

Introduced in v2.3

## Example

# Example 1

``

    use_bpm 60
      play 50
      sleep 1
      play 62
      sleep 2
      with_bpm_mul 0.5 do
        play 50
        sleep 1
        play 62
      end
      sleep 1

``

    # Set the BPM to 60

    # Sleeps for 1 second

    # Sleeps for 2 seconds
    # BPM is now (60 * 0.5) == 30

    # Sleeps for 2 seconds

    # BPM is now back to 60, therefore sleep is 1 second

# Block-level cent tuning

``

    with_cent_tuning  cent_shift (number)

Similar to `use_cent_tuning` except only applies cent shift to code within supplied `do`/`end` block. Previous cent tuning value is restored after block. One semitone consists of 100 cents. To transpose entire semitones see `with_transpose`.

Introduced in v2.9

## Example

# Example 1

``

    use_cent_tuning 1
    play 50

    with_cent_tuning 2 do
      play 50
    end

    play 50

``

    # Plays note 50.01

    # Plays note 50.02

    # Original cent tuning value is restored
    # Plays note 50.01

# Block-level enable and disable cue logging

``

    with_cue_logging  true_or_false (boolean)

Similar to use_cue_logging except only applies to code within supplied `do`/`end` block. Previous cue log value is restored after block.

Introduced in v2.6

## Example

# Example 1

``

      use_cue_logging true

      cue :foo

      with_cue_logging false do

        cue :bar
      end
      sleep 1

      cue :quux

``

    # Turn on debugging:

    # cue message is printed to log

    #Cue logging is now disabled
    # cue *is* sent but not displayed in log

    # Debug is re-enabled
    # cue is displayed in log

# Block-level enable and disable debug

``

    with_debug  true_or_false (boolean)

Similar to use_debug except only applies to code within supplied `do`/`end` block. Previous debug value is restored after block.

Introduced in v2.0

## Example

# Example 1

``

    use_debug true

    play 80

    with_debug false do

      play 50
      sleep 1
      play 72
    end

    play 90

``

    # Turn on debugging:

    # Debug message is sent

    #Debug is now disabled
    # Debug message is not sent

    # Debug message is not sent

    # Debug is re-enabled
    # Debug message is sent

# Use Studio FX

``

    with_fx  fx_name (symbol)

This applies the named effect (FX) to everything within a given `do`/`end` block. Effects may take extra parameters to modify their behaviour. See FX help for parameter details.

For advanced control, it is also possible to modify the parameters of an effect within the body of the block. If you define the block with a single argument, the argument becomes a reference to the current effect and can be used to control its parameters (see examples).

Introduced in v2.0

## Options

reps: | Number of times to repeat the block in an iteration.
kill_delay: | Amount of time to wait after all synths triggered by the block have completed before stopping and freeing the effect synthesiser.

## Examples

# Example 1

``

    with_fx :distortion do
      play 50
      sleep 1
      sample :loop_amen
    end

``

    # Basic usage
    # Use the distortion effect with default parameters
    # => plays note 50 with distortion

    # => plays the loop_amen sample with distortion too

# Example 2

``

    with_fx :level, amp: 0.3 do
      play 50
      sleep 1
      sample :loop_amen
    end

``

    # Specify effect parameters
    # Use the level effect with the amp parameter set to 0.3

# Example 3

``

    with_fx :reverb, mix: 0.1 do |fx|

      play 60
      sleep 2

      control fx, mix: 0.5
      play 60
      sleep 2

      control fx, mix: 1
      play 60
      sleep 2
    end

``

    # Controlling the effect parameters within the block

    # here we set the reverb level quite low to start with (0.1)
    # and we can change it later by using the 'fx' reference we've set up

    # plays note 60 with a little bit of reverb

    # change the parameters of the effect to add more reverb
    # again note 60 but with more reverb

    # change the parameters of the effect to add more reverb
    # plays note 60 with loads of reverb

# Example 4

``

    with_fx :reverb, reps: 16 do
      play (scale :e3, :minor_pentatonic), release: 0.1
      sleep 0.125
    end

    with_fx :reverb do
      16.times do
        play (scale :e3, :minor_pentatonic), release: 0.1
        sleep 0.125
      end
    end

``

    # Repeat the block 16 times internally

    # The above is a shorthand for this:

# Block-level merge midi defaults

``

    with_merged_midi_defaults

Specify opt values to be used by any following call to the `midi_*` fns within the specified `do`/`end` block. Merges the specified values with any previous midi defaults, rather than replacing them. After the `do`/`end` block has completed, previous defaults (if any) are restored.

Introduced in v3.0

## Options

channel: | MIDI channel(s) to send event on
port: | MIDI port(s) to send to
velocity: | Note velocity as a MIDI number.
vel_f: | Velocity as a value between 0 and 1 (will be converted to a MIDI velocity between 0 and 127)
on: | If specified and false/nil/0 will stop the midi note on message from being sent out. (Ensures all opts are evaluated in this call to `midi_note_on` regardless of value).

## Example

# Example 1

``

    midi_note_on :e1

    use_midi_defaults channel: 3, port: "foo"

    midi_note_on :e3

    with_merged_midi_defaults channel: 1 do

      midi_note_on :e2

    end

    midi_note_on :e2

``

    # Sends MIDI :e1 note_on with default opts

    # Sends MIDI :e3 note_on to channel 3 on port "foo"

    # Sends MIDI :e2 note_on to channel 1 on port "foo".
    # This is because the call to use_merged_midi_defaults overrode the
    # channel but not the port which got merged in.

    # Sends MIDI :e2 note_on to channel 3 on port "foo".
    # This is because the previous defaults were restored after
    # the call to with_merged_midi_defaults.

# Block-level use merged sample defaults

``

    with_merged_sample_defaults

Specify new default values to be used by all subsequent calls to `sample` within the `do`/`end` block. Merges the specified values with any previous sample defaults, rather than replacing them. After the `do`/`end` block has completed, the previous sampled defaults (if any) are restored.

Introduced in v2.9

## Example

# Example 1

``

    sample :loop_amen

    use_merged_sample_defaults amp: 0.5, cutoff: 70

    sample :loop_amen

    with_merged_sample_defaults cutoff: 90 do
      sample :loop_amen
    end

    sample :loop_amen

``

    # plays amen break with default arguments

    # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

    # plays amen break with a cutoff of 90 and amp of 0.5

    # plays amen break with a cutoff of 70 and amp is 0.5 again as the previous defaults are restored.

# Block-level merge synth defaults

``

    with_merged_synth_defaults

Specify synth arg values to be used by any following call to play within the specified `do`/`end` block. Merges the specified values with any previous synth defaults, rather than replacing them. After the `do`/`end` block has completed, previous defaults (if any) are restored.

Introduced in v2.0

## Examples

# Example 1

``

    with_merged_synth_defaults amp: 0.5, pan: 1 do
      play 50
    end

``

    # => plays note 50 with amp 0.5 and pan 1

# Example 2

``

    play 50
    with_merged_synth_defaults amp: 0.5 do
      play 50

      with_merged_synth_defaults pan: -1 do
        with_merged_synth_defaults amp: 0.7 do
          play 50
        end
      end
      play 50
    end

``

    #=> plays note 50

    #=> plays note 50 with amp 0.5

    #=> plays note 50 with amp 0.7 and pan -1

    #=> plays note 50 with amp 0.5

# Block-level use new MIDI defaults

``

    with_midi_defaults

Specify new default values to be used by all calls to `midi_*` fns within the `do`/`end` block. After the `do`/`end` block has completed the previous MIDI defaults (if any) are restored.

Introduced in v3.0

## Options

channel: | MIDI channel(s) to send event on
port: | MIDI port(s) to send to
velocity: | Note velocity as a MIDI number.
vel_f: | Velocity as a value between 0 and 1 (will be converted to a MIDI velocity between 0 and 127)
on: | If specified and false/nil/0 will stop the midi note on message from being sent out. (Ensures all opts are evaluated in this call to `midi_note_on` regardless of value).

## Example

# Example 1

``

    midi_note_on :e1

    with_midi_defaults channel: 3, port: "foo" do
      midi_note_on :e3
    end

    use_midi_defaults channel: 1

    with_midi_defaults channel: 5 do
      midi_note_on :e2

    end

      midi_note_on :e4

``

    # Sends MIDI :e1 note on with default opts

    # Sends MIDI :e3 note on to channel 3 on port "foo"

    # this will be overridden by the following

    # Sends MIDI :e2 note on to channel 5.
    # Note that the port is back to the default

    # Sends MIDI :e4 note on to channel 1
    # Note that the call to use_midi_defaults is now honoured.

# Block-level enable and disable MIDI logging

``

    with_midi_logging  true_or_false (boolean)

Similar to use_midi_logging except only applies to code within supplied `do`/`end` block. Previous MIDI log value is restored after block.

Introduced in v3.0

## Example

# Example 1

``

      use_midi_logging true

      midi :e1

      with_midi_logging false do

        midi :f2
      end
      sleep 1

      midi :G3

``

    # Turn on MIDI logging:

    #  message is printed to log

    #MIDI logging is now disabled
    # MIDI message *is* sent but not displayed in log

    # Debug is re-enabled
    # message is displayed in log

# Block level octave transposition

``

    with_octave  octave_shift (number)

Transposes your music by shifting all notes played by the specified number of octaves within the specified block. To shift up by an octave use a transpose of 1. To shift down use negative numbers. For transposing the notes within the octave range see `with_transpose`.

Introduced in v2.9

## Example

# Example 1

``

    play 50
    sleep 1
    with_octave 1 do
     play 50
    end
    sleep 1
    play 50

``

    # Plays note 50

    # Plays note 62

    # Plays note 50

# Block-level setting for the default hostname and port number of outgoing OSC messages.

``

    with_osc  hostname (string), port (number)

Sets the destination host and port that `osc` will send messages to for the given do/end block.

Introduced in v3.0

## Example

# Example 1

``

    use_osc "localhost", 7000
    osc "/foo/baz"

    with_osc "localhost", 7010 do

       osc "/foo/baz"
    end

    osc "/foo/baz"

``

    # Specify port 7000
    # Send an OSC message to port 7000

    # set hostname and port for the duration
    # of this do/end block
    # Send an OSC message to port 7010

    # Send an OSC message to port 7000
    # as old setting is restored outside
    # do/end block

# Block-level enable and disable OSC logging

``

    with_osc_logging  true_or_false (boolean)

Similar to use_osc_logging except only applies to code within supplied `do`/`end` block. Previous OSC log value is restored after block.

Introduced in v3.0

## Example

# Example 1

``

      use_osc_logging true

      osc "/foo"

      with_osc_logging false do

        osc "/foo"
      end
      sleep 1

      osc "/foo"

``

    # Turn on OSC logging:

    #  message is printed to log

    #OSC logging is now disabled
    # OSC message *is* sent but not displayed in log

    # Debug is re-enabled
    # message is displayed in log

# Specify random seed for code block

``

    with_random_seed  seed (number)

Resets the random number generator to the specified seed for the specified code block. All generated random numbers and randomisation functions such as `shuffle` and `choose` within the code block will use this new generator. Once the code block has completed, the original generator is restored and the code block generator is discarded. Use this to change the sequence of random numbers in your piece in a way that can be reproduced. Especially useful if combined with iteration. See examples.

Introduced in v2.0

## Examples

# Example 1

``

    use_random_seed 1
      puts rand
      puts rand
      use_random_seed 1
      puts rand
      with_random_seed 1 do
        puts rand
        puts rand
      end
      puts rand

``

    # reset random seed to 1
    # => 0.733917236328125
    #=> 0.464202880859375
    # reset it back to 1
    # => 0.733917236328125
    # reset seed back to 1 just for this block
    # => 0.733917236328125
    #=> 0.464202880859375

    # => 0.464202880859375
    # notice how the original generator is restored

# Example 2

``

      notes = (scale :eb3, :minor_pentatonic, num_octaves: 2)

      with_fx :reverb do
        live_loop :repeating_melody do

          with_random_seed 300 do

            8.times do

              play notes.choose, release: 0.1

              sleep 0.125
            end
          end

          play notes.choose, amp: 1.5, release: 0.5

        end
      end

``

    # Generating melodies
    # Create a set of notes to choose from.
    # Scales work well for this

    # Create a live loop

    # Set the random seed to a known value every
    # time around the loop. This seed is the key
    # to our melody. Try changing the number to
    # something else. Different numbers produce
    # different melodies

    # Now iterate a number of times. The size of
    # the iteration will be the length of the
    # repeating melody.

    # 'Randomly' choose a note from our ring of
    # notes. See how this isn't actually random
    # but uses a reproducible method! These notes
    # are therefore repeated over and over...

    # Note that this line is outside of
    # the with_random_seed block and therefore
    # the randomisation never gets reset and this
    # part of the melody never repeats.

# Specify random distribution for code block

``

    with_random_source  noise_type (symbol)

Resets the random number generator to the specified noise type for the specified code block. All generated random numbers and randomisation functions such as `shuffle` and `choose` within the code block will use this new generator. Once the code block has completed, the original generator is restored and the code block generator is discarded. Use this to change the sequence of random numbers in your piece in a way that can be reproduced. Especially useful if combined with iteration. See examples.

Introduced in v3.3

## Example

# Example 1

``

    use_random_source :white
      rand_reset
      puts rand
      puts rand
      puts rand
      rand_reset
      use_random_source :pink
      puts rand
      puts rand
      rand_reset
      use_random_source :perlin
      puts rand
      puts rand

      with_random_source :white do
        puts rand
      end

      puts rand

``

    # use white noise as the distribution (default)
    # reset random seed
    # => 0.75006103515625
    # => 0.733917236328125
    # => 0.464202880859375
    # reset it again
    # use pink noise as the distribution
    # => 0.47808837890625
    # => 0.56011962890625
    # reset it
    # use perlin noise as the distribution
    # => 0.546478271484375
    # => 0.573150634765625

    # use white noise just for this block
    # => 0.464202880859375

    # => 0.597015380859375
    # notice how the last generator (perlin) is restored

# Sets sched ahead time to 0 within the block for the current thread

``

    with_real_time

Sets sched ahead time to 0 within the block for the current thread. Shorthand for `with_sched_ahead_time 0`.

See `with_sched_ahead_time` for a version of this function which allows you to set the schedule ahead time to any arbitrary value. Note, `with_real_time` will override any value set with `set_sched_ahead_time!` for the current thread.

Introduced in v3.0

## Example

# Example 1

``

    with_real_time do
      play 70
    end

    play 70

``

    # Sound will happen without a scheduling delay.

    # Sound will happen with the default latency (0.5s).

# Block-scoped sample-duration-based bpm modification

``

    with_sample_bpm  string_or_number (sample_name_or_duration)

Block-scoped modification of bpm so that sleeping for 1 will sleep for the duration of the sample.

Introduced in v2.1

## Options

num_beats: | The number of beats within the sample. By default this is 1.

## Examples

# Example 1

``

    live_loop :dnb do
      with_sample_bpm :loop_amen do
        sample :bass_dnb_f
        sample :loop_amen
        sleep 1
      end
    end

``

    #Set bpm based on :loop_amen duration

    #`sleep`ing for 1 sleeps for duration of :loop_amen

# Example 2

``

    live_loop :dnb do
      with_sample_bpm :loop_amen, num_beats: 4 do

        sample :bass_dnb_f
        sample :loop_amen
        sleep 4

      end
    end

``

    # Set bpm based on :loop_amen duration
    # but also specify that the sample duration
    # is actually 4 beats long.

    #`sleep`ing for 4 sleeps for duration of :loop_amen
    # as we specified that the sample consisted of
    # 4 beats

# Block-level use new sample defaults

``

    with_sample_defaults

Specify new default values to be used by all subsequent calls to `sample` within the `do`/`end` block. After the `do`/`end` block has completed, the previous sampled defaults (if any) are restored. For the contents of the block, will remove and override any previous defaults.

Introduced in v2.5

## Example

# Example 1

``

    sample :loop_amen

    use_sample_defaults amp: 0.5, cutoff: 70

    sample :loop_amen

    with_sample_defaults cutoff: 90 do
      sample :loop_amen
    end

    sample :loop_amen

``

    # plays amen break with default arguments

    # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

    # plays amen break with a cutoff of 90 and defaults for rest of args - note that amp is no longer 0.5

    # plays amen break with a cutoff of 70 and amp is 0.5 again as the previous defaults are restored.

# Block-level set sched ahead time for the current thread

``

    with_sched_ahead_time  time (number)

Specify how many seconds ahead of time the synths should be triggered for the block. See `use_sched_ahead_time` for further information.

See `set_sched_ahead_time!` for a global version of this function. Note, `with_sched_ahead_time` will override any value set with `set_sched_ahead_time!` for the given block within the current thread.

See `with_real_time` for a simple way of setting the schedule ahead time to 0.

Introduced in v3.0

## Example

# Example 1

``

    with_sched_ahead_time 1 do
      play 70
    end

    play 70

``

    # Sound will happen with a latency of 1

    # Sound will happen with the default latency (0.5s)

# Add swing to successive calls to do/end block

``

    with_swing  shift (beats), pulse (number), tick (symbol), offset (number)

Runs block within a `time_warp` except for once every `pulse` consecutive runs (defaulting to 4). When used for rhythmical purposes this results in one in every `pulse` calls of the block being ‘on beat’ and the rest shifted forward or backwards in time by `shift` beats.

Introduced in v3.0

## Options

shift: | How much time to delay/forward the block. Greater values produce more emphasised swing. Defaults to 0.1 beats.
pulse: | How often to apply the swing. Defaults to 4.
tick: | A key for the tick with which to count pulses. Override this if you have more than one `with_swing` block in your `live_loop` or thread to stop them interfering with each other.
offset: | Count offset - before modding the count with the pulse size - integer offset to add to the result of calling `tick` with the specified tick key (via the `tick:` opt)

## Examples

# Example 1

``

    live_loop :foo do
      with_swing 0.1 do
        sample :elec_beep
      end
      sleep 0.25
    end

``

    # plays the :elec_beep sample late except on the 1st beat of every 4

# Example 2

``

    live_loop :foo do
      with_swing -0.1 do
        sample :elec_beep
      end
      sleep 0.25
    end

``

    # plays the :elec_beep sample slightly early
    # on the 1st beat of every 4

# Example 3

``

    live_loop :foo do
      with_swing -0.1, pulse: 8 do
        sample :elec_beep
      end
      sleep 0.25
    end

``

    # plays the :elec_beep sample slightly early
    #  on the 1st beat of every 8

# Example 4

``

    live_loop :foo do
      with_swing 0.14, tick: :a do
        sample :elec_beep
      end

      with_swing -0.1, tick: :b do
        sample :elec_beep, rate: 2
      end
      sleep 0.25
    end

``

    # Use unique tick names if you plan on using with_swing
    # more than once in any given live_loop or thread.

    # plays the :elec_beep sample slightly late
    #  on the 1st beat of every 4

    # plays the :elec_beep sample at double rate
    #  slightly early except  on the 1st beat of every 4

# Example 5

``

    live_loop :foo do
      with_swing 0.1 do
        cue :tick
      end
      sleep 0.25
    end

    live_loop :bar do
      sync :tick
      sample :elec_beep

    end

``

    # send out cue messages with swing timing

    # sync on the swing cue messages to bring the swing into
    # another live loop (sync will match the timing and clock of
    # the sending live loop)

# Example 6

``

    live_loop :foo do
      with_swing 0.1, offset: 2 do
        sample :elec_beep
      end
      sleep 0.25
    end

``

    # plays the :elec_beep sample slightly late
    # on the the 3rd beat of every 4

# Example 7

``

    live_loop :foo do
      with_swing 0.1, pulse: 2, offset: 1 do
        sample :elec_beep
      end
      sleep 0.25
    end

``

    # plays the :elec_beep sample slightly late
    # on the 2nd beat of every 2

# Block-level synth switching

``

    with_synth  synth_name (symbol)

Switch the current synth to `synth_name` but only for the duration of the `do`/`end` block. After the `do`/`end` block has completed, the previous synth is restored.

Introduced in v2.0

## Example

# Example 1

``

    play 50
    sleep 2
    use_synth :supersaw
    play 50
    sleep 2
    with_synth :saw_beep do
      play 50
    end
    sleep 2

    play 50

``

    # Plays with default synth

    # Plays with supersaw synth

    # Plays with saw_beep synth

    # Previous synth is restored
    # Plays with supersaw synth

# Block-level use new synth defaults

``

    with_synth_defaults

Specify new default values to be used by all calls to `play` within the `do`/`end` block. After the `do`/`end` block has completed the previous synth defaults (if any) are restored.

Introduced in v2.0

## Example

# Example 1

``

    play 50

    use_synth_defaults amp: 0.5, pan: -1

    play 50

    with_synth_defaults amp: 0.6, cutoff: 80 do
      play 50
    end

    play 60

``

    # plays note 50 with default arguments

    # plays note 50 with an amp of 0.5, pan of -1 and defaults for rest of args

    # plays note 50 with an amp of 0.6, cutoff of 80 and defaults for rest of args (including pan)

    # plays note 60 with an amp of 0.5, pan of -1 and defaults for rest of args

# Block-scoped inhibition of synth triggers if too late

``

    with_timing_guarantees  bool (true_or_false)

For the given block, if set to true, synths will not trigger if it is too late. If false, some synth triggers may be late. After the block has completed, the previous value is restored.

Introduced in v2.10

## Examples

# Example 1

``

    with_timing_guarantees true do
      sample :loop_amen
    end

``

    #=> if time is behind by any margin, this will not trigger

# Example 2

``

    with_timing_guarantees false do
      sample :loop_amen
    end

``

    #=> unless time is too far behind, this will trigger even when late.

# Block-level note transposition

``

    with_transpose  note_shift (number)

Similar to use_transpose except only applies to code within supplied `do`/`end` block. Previous transpose value is restored after block. To transpose entire octaves see `with_octave`.

Introduced in v2.0

## Example

# Example 1

``

    use_transpose 3
    play 62

    with_transpose 12 do
      play 50
      sleep 1
      play 72
    end

    play 80

``

    # Plays note 65

    # Plays note 62

    # Plays note 84

    # Original transpose value is restored
    # Plays note 83

# Block-level tuning modification

``

    with_tuning  tuning (symbol), fundamental_note (symbol_or_number)

Similar to use_tuning except only applies to code within supplied `do`/`end` block. Previous tuning value is restored after block.

Introduced in v2.6

## Example

# Example 1

``

    use_tuning :equal, :c
    play :e4
    with_tuning :just, :c do
      play :e4
      sleep 1
      play :c4
    end

    play :e4

``

    # Plays note 64

    # Plays note 63.8631

    # Plays note 60

    # Original tuning value is restored
    # Plays note 64