Muzyka algorytmiczna

Dokumentacja funkcji Sonic Pi

231 funkcji

all_sample_names Get all sample names
assert Ensure arg is valid
assert_equal Ensure args are equal
assert_error Ensure block throws an error
assert_not Ensure arg is not valid
assert_not_equal Ensure args are not equal
assert_similar Ensure args are similar
at Asynchronous Time. Run a block at the given time(s)
beat Get current beat
block_duration Return block duration
block_slept? Determine if block contains sleep time
bools Create a ring of boolean values
bt Beat time conversion
buffer Initialise or return named buffer
choose Random list selection
chord Create chord
chord_degree Construct chords of stacked thirds, based on scale degrees
chord_invert Chord inversion
chord_names All chord names
clear Clear all thread locals to defaults
comment Block level commenting
control Control running synth
cue Cue other threads
current_arg_checks Get current arg checking status
current_beat_duration Duration of current beat
current_bpm Get current tempo
current_bpm_mode Get current tempo mode
current_cent_tuning Get current cent shift
current_debug Get current debug status
current_midi_defaults Get current MIDI defaults
current_octave Get current octave shift
current_random_seed Get current random seed
current_random_source Get current random source
current_sample_defaults Get current sample defaults
current_sched_ahead_time Get current sched ahead time
current_synth Get current synth
current_synth_defaults Get current synth defaults
current_time Get current (logically quantized) time
current_transpose Get current transposition
current_volume Get current volume
dec Decrement
define Define a new function
defonce Define a named value only once
degree Convert a degree into a note
density Squash and repeat time
dice Random dice throw
doubles Create a ring of successive doubles
eval_file Evaluate the contents of the file inline in the current thread like a function.
factor? Factor test
fx_names Get all FX names
get Get information from the Time State
halves Create a ring of successive halves
hz_to_midi Hz to MIDI conversion
in_thread Run code block at the same time
inc Increment
kill Kill synth
knit Knit a sequence of repeated values
line Create a ring buffer representing a straight line
link Use Ableton Link network metronome with automatic phase syncing.
link_sync Use Ableton Link network metronome with automatic session and phase syncing.
live_audio A named audio stream live from your soundcard
live_loop A loop for live coding
load_buffer Load the contents of a file to the current buffer
load_example Load a built-in example
load_sample Pre-load first matching sample
load_samples Pre-load all matching samples
load_synthdef Load a single external synthdef
load_synthdefs Load external synthdefs
look Obtain value of a tick
loop Repeat do/end block forever
map Create an immutable map
math_scale Linear scaling algorithm
midi Trigger and release an external synth via MIDI
midi_all_notes_off Turn off all notes on MIDI devices
midi_cc Send MIDI control change message
midi_channel_pressure Send MIDI channel pressure (aftertouch) message
midi_clock_beat Send a quarter-note's worth of MIDI clock ticks
midi_clock_tick Send an individual MIDI clock tick
midi_continue Send MIDI system message - continue
midi_local_control_off Disable local control on MIDI devices
midi_local_control_on Enable local control on MIDI devices
midi_mode Set Omni/Mono/Poly mode
midi_note_off Send MIDI note off message
midi_note_on Send MIDI note on message
midi_notes Create a ring buffer of midi note numbers
midi_pc Send MIDI program change message
midi_pitch_bend Send MIDI pitch bend message
midi_poly_pressure Send a MIDI polyphonic key pressure message
midi_raw Send raw MIDI message
midi_reset Reset MIDI devices
midi_sound_off Silence all MIDI devices
midi_start Send MIDI system message - start
midi_stop Send MIDI system message - stop
midi_sysex Send MIDI System Exclusive (SysEx) message
midi_to_hz MIDI to Hz conversion
ndefine Define a new function
note Describe note
note_info Get note info
note_range Get a range of notes
octs Create a ring of octaves
on Optionally evaluate block
one_in Random true value with specified probability
osc Send an OSC message (Open Sound Control)
osc_send Send an OSC message to a specific host and port
pick Randomly pick from list (with duplicates)
pitch_to_ratio relative MIDI pitch to frequency ratio
play Play current synth
play_chord Play notes simultaneously
play_pattern Play pattern of notes
play_pattern_timed Play pattern of notes with specific times
print Display a message in the output pane
puts Display a message in the output pane
quantise Quantise a value to resolution
ramp Create a ramp vector
rand Generate a random float below a value
rand_back Roll back random generator
rand_i Generate a random whole number below a value (exclusive)
rand_i_look Generate a random whole number without consuming a rand
rand_look Generate a random number without consuming a rand
rand_reset Reset rand generator to last seed
rand_skip Jump forward random generator
range Create a ring buffer with the specified start, finish and step size
ratio_to_pitch relative frequency ratio to MIDI pitch
rdist Random number in centred distribution
reset Reset all thread locals
reset_mixer! Reset main mixer
rest? Determine if note or args is a rest
ring Create a ring buffer
rrand Generate a random float between two numbers
rrand_i Generate a random whole number between two points inclusively
rt Real time conversion
run_code Evaluate the code passed as a String as a new Run
run_file Evaluate the contents of the file as a new Run
sample Trigger sample
sample_buffer Get sample data
sample_duration Get duration of sample in beats
sample_free Free a sample on the synth server
sample_free_all Free all loaded samples on the synth server
sample_groups Get all sample groups
sample_info Get sample information
sample_loaded? Test if sample was pre-loaded
sample_names Get sample names
sample_paths Sample Pack Filter Resolution
scale Create scale
scale_names All scale names
scsynth_info Return information about the internal SuperCollider sound server
set Store information in the Time State
set_audio_latency! Globally modify audio latency
set_cent_tuning! Global Cent tuning
set_control_delta! Set control delta globally
set_link_bpm! Set the tempo for the link metronome.
set_mixer_control! Control main mixer
set_recording_bit_depth! Set the bit depth for recording wav files
set_sched_ahead_time! Set sched ahead time globally
set_volume! Set Volume globally
shuffle Randomise order of a list
sleep Wait for beat duration
spark Print a string representing a list of numeric values as a spark graph/bar chart
spark_graph Returns a string representing a list of numeric values as a spark graph/bar chart
spread Euclidean distribution for beats
status Get server status
stop Stop current thread or run
stretch Stretch a sequence of values
sync Sync with other threads
sync_bpm Sync and inherit BPM from other threads
synth Trigger specific synth
synth_names Get all synth names
tick Increment a tick and return value
tick_reset Reset tick to 0
tick_reset_all Reset all ticks
tick_set Set tick to a specific value
time_warp Shift time forwards or backwards for the given block
uncomment Block level comment ignoring
use_arg_bpm_scaling Enable and disable BPM scaling
use_arg_checks Enable and disable arg checks
use_bpm Set the tempo
use_bpm_mul Set new tempo as a multiple of current tempo
use_cent_tuning Cent tuning
use_cue_logging Enable and disable cue logging
use_debug Enable and disable debug
use_merged_midi_defaults Merge MIDI defaults
use_merged_sample_defaults Merge new sample defaults
use_merged_synth_defaults Merge synth defaults
use_midi_defaults Use new MIDI defaults
use_midi_logging Enable and disable MIDI logging
use_octave Note octave transposition
use_osc Set the default hostname and port number for outgoing OSC messages.
use_osc_logging Enable and disable OSC logging
use_random_seed Set random seed generator to known seed
use_random_source Change how random numbers are chosen
use_real_time Set sched ahead time to 0 for the current thread
use_sample_bpm Sample-duration-based bpm modification
use_sample_defaults Use new sample defaults
use_sched_ahead_time Set sched ahead time for the current thread
use_synth Switch current synth
use_synth_defaults Use new synth defaults
use_timing_guarantees Inhibit synth triggers if too late
use_transpose Note transposition
use_tuning Use alternative tuning systems
vector Create a vector
version Get current version information
vt Get virtual time
wait Wait for duration
with_arg_bpm_scaling Block-level enable and disable BPM scaling
with_arg_checks Block-level enable and disable arg checks
with_bpm Set the tempo for the code block
with_bpm_mul Set new tempo as a multiple of current tempo for block
with_cent_tuning Block-level cent tuning
with_cue_logging Block-level enable and disable cue logging
with_debug Block-level enable and disable debug
with_fx Use Studio FX
with_merged_midi_defaults Block-level merge midi defaults
with_merged_sample_defaults Block-level use merged sample defaults
with_merged_synth_defaults Block-level merge synth defaults
with_midi_defaults Block-level use new MIDI defaults
with_midi_logging Block-level enable and disable MIDI logging
with_octave Block level octave transposition
with_osc Block-level setting for the default hostname and port number of outgoing OSC messages.
with_osc_logging Block-level enable and disable OSC logging
with_random_seed Specify random seed for code block
with_random_source Specify random distribution for code block
with_real_time Sets sched ahead time to 0 within the block for the current thread
with_sample_bpm Block-scoped sample-duration-based bpm modification
with_sample_defaults Block-level use new sample defaults
with_sched_ahead_time Block-level set sched ahead time for the current thread
with_swing Add swing to successive calls to do/end block
with_synth Block-level synth switching
with_synth_defaults Block-level use new synth defaults
with_timing_guarantees Block-scoped inhibition of synth triggers if too late
with_transpose Block-level note transposition
with_tuning Block-level tuning modification

Get all sample names

all_sample_names

Return a list of all the sample names available

Examples

Introduced in 2.0.0

Ensure arg is valid

assert arg (anything)

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

Examples

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

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

# More interesting assertions
assert (1 + 1) == 2 # Ensure that arithmetic is sane!
assert [:a, :b, :c].size == 3 # ensure lists can be correctly counted

Introduced in 2.8.0

Ensure args are equal

assert_equal arg1 (anything), arg2 (anything)

Raises an exception if both arguments aren’t equal.

Examples

# Simple assertions
assert_equal 1, 1

# More interesting assertions
assert_equal 1 + 1, 2 # Ensure that arithmetic is sane!
assert_equal [:a, :b, :c].size,  3 # ensure lists can be correctly counted

# Add messages to the exceptions
assert_equal 3, 5, "something is seriously wrong!"

Introduced in 2.8.0

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.

Examples

assert_error do
  play 70
end                         # Will throw an exception: "Assert error failed!" as the block
                            # contains no errors.

assert_error do
  1 / 0
end                         # Will not throw an exception as the block contains an error.

assert_error ZeroDivisionError do
  1 / 0
end                         # Will not throw an exception as the block contains a ZeroDivisionError.

assert_error ThreadError do
  1 / 0
end                         # Will throw an exception as the block contains a ZeroDivisionError rather than
                            # a ThreadError.

Introduced in 3.0.0

Ensure arg is not valid

assert_not arg (anything)

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

Examples

# Simple assertions
assert_not false   # As false is either nil or false, this assertion passes
assert_not nil     # As nil is either nil or false, this assertion passes
assert_not 1 == 5  # These numbers are not equal
assert true  # This will raise an exception

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

Introduced in 3.3.0

Ensure args are not equal

assert_not_equal arg1 (anything), arg2 (anything)

Raises an exception if both arguments are qual.

Examples

# Simple assertions
assert_not_equal 1, 3
assert_not_equal 1, -1
assert_not_equal 1, :foo

# Add messages to the exceptions
assert_not_equal 3, 3, "something is seriously wrong!"

Introduced in 3.3.0

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.

Examples

# Simple assertions
assert_similar 1, 1 #=> True

# Handles floating point imprecision
assert_similar(4.9999999999, 5.0) #=> True

Introduced in 3.0.0

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.

Examples

  at 4 do
    sample :ambi_choir    # play sample after waiting for 4 beats
  end
  

  at [1, 2, 4] do  # plays a note after waiting 1 beat,
    play 75           # then after 1 more beat,
  end                 # then after 2 more beats (4 beats total)
  

  at [1, 2, 3], [75, 76, 77] do |n|  # plays 3 different notes
    play n
  end
  

  at [1, 2, 3],
      [{:amp=>0.5}, {:amp=> 0.8}] do |p| # alternate soft and loud
    sample :drum_cymbal_open, p          # cymbal hits three times
  end
  

  at [0, 1, 2] do |t| # when no params are given to at, the times are fed through to the block
    puts t #=> prints 0, 1, then 2
  end
  

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

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

  at [0, 0.5, 2], [:a, :b] do |t, b, idx|  #If you specify the block with 3 args, it will pass through the time, the param and the index
    puts [t, b, idx] #=> prints out [0, :a, 0], [0.5, :b, 1], then [2, :a, 2]
  end
  
 # at does not consume & interfere with the outer random stream
puts "main: ", rand  # 0.75006103515625
rand_back
at 1 do         # the random stream inside the at block is separate and
                # isolated from the outer stream.
  puts "at:", rand # 0.9287109375
  puts "at:", rand # 0.1043701171875
end

sleep 2
puts "main: ", rand # value is still 0.75006103515625

            # Each block run within at has its own isolated random stream:
at [1, 2] do
            # first time round (after 1 beat) prints:
  puts rand # 0.9287109375
  puts rand # 0.1043701171875
end
            # second time round (after 2 beats) prints:
            # 0.1043701171875
            # 0.764617919921875

Introduced in 2.1.0

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.

Examples

use_bpm 120  #=> The initial beat does not start at 0
puts beat    #=> 109252.703125
sleep 1
puts beat    #=> 109253.703125
use_bpm 2000 # Changing the BPM makes no difference
sleep 2
puts beat    #=> 109255.703125

Introduced in 2.10.0

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.

Examples

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

Introduced in 2.9.0

Determine if block contains sleep time

block_slept?

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

Examples

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

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

in_thread do
  sleep 1
  cue :foo  # trigger a cue on a different thread
end

slept = block_slept? do
  sync :foo  # wait for the cue before playing the note
  play 62
end

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

slept = block_slept? do
  play 50
  play 62
end

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

Introduced in 2.9.0

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.

Examples
(bools 1, 0)    #=> (ring true, false)
(bools 1, 0, true, false, nil) #=> (ring true, false, true, false, false)

Introduced in 2.2.0

Beat time conversion

bt seconds (number)

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

Examples

  use_bpm 120  # Set the BPM to be double the default
  puts bt(1) # 0.5
  use_bpm 60   # BPM is now default
  puts bt(1) # 1
  use_bpm 30   # BPM is now half the default
  puts bt(1) # 2

Introduced in 2.8.0

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.

Examples

buffer(:foo) # load a 8s buffer and name it :foo
b = buffer(:foo) # return cached buffer and bind it to b
puts b.duration  #=> 8.0

buffer(:foo, 16) # load a 16s buffer and name it :foo

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)

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

Introduced in 3.0.0

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)

Examples

  loop do
    play choose([60, 64, 67]) #=> plays one of 60, 64 or 67 at random
    sleep 1
    play chord(:c, :major).choose #=> You can also call .choose on the list
    sleep 1
  end

# Using choose for random sample onsets
live_loop :foo do
  sample :loop_amen, onset: choose   # choose a random onset value each time
  sleep 0.125
end

Introduced in 2.0.0

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.

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

puts (chord :e, :minor) # returns a ring of midi notes - (ring 64, 67, 71)
# Play all the notes together
play (chord :e, :minor)

# Chord inversions (see the fn chord_invert)
play (chord :e3, :minor, invert: 0) # Play the basic :e3, :minor chord - (ring 52, 55, 59)
play (chord :e3, :minor, invert: 1) # Play the first inversion of :e3, :minor - (ring 55, 59, 64)
play (chord :e3, :minor, invert: 2) # Play the first inversion of :e3, :minor - (ring 59, 64, 67)
# You can create a chord without a tonic:
puts (chord :minor) #=> (ring 0, 3, 7)
# chords are great for arpeggiators
live_loop :arp do
  play chord(:e, :minor, num_octaves: 2).tick, release: 0.1
  sleep 0.125
end
# Sonic Pi supports a large range of chords
 # Notice that the more exotic ones have to be surrounded by ' quotes
(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)

Introduced in 2.0.0

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.

invert Apply the specified num inversions to chord. See the fn `chord_invert`.
Options for chord_degree
Examples
puts (chord_degree :i, :A3, :major) # returns a ring of midi notes - (ring 57, 61, 64, 68) - an A major 7 chord
play (chord_degree :i, :A3, :major, 3)
play (chord_degree :ii, :A3, :major, 3) # Chord ii in A major is a B minor chord
play (chord_degree :iii, :A3, :major, 3) # Chord iii in A major is a C# minor chord
play (chord_degree :iv, :A3, :major, 3) # Chord iv in A major is a D major chord
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
play (chord_degree :i, :C4, :major, 5) # Taking five notes gives us 9th chords - here it plays a C major 9 chord
play (chord_degree :i, :C4, :major, 3, invert: 1) # Play the first inversion of chord i in C major - (ring 64, 67, 72)

Introduced in 2.1.0

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)

Examples

play (chord_invert (chord :A3, "M"), 0) #No inversion     - (ring 57, 61, 64)
sleep 1
play (chord_invert (chord :A3, "M"), 1) #First inversion  - (ring 61, 64, 69)
sleep 1
play (chord_invert (chord :A3, "M"), 2) #Second inversion - (ring 64, 69, 73)

Introduced in 2.6.0

All chord names

chord_names

Returns a ring containing all chord names known to Sonic Pi

Examples
puts chord_names #=>  prints a list of all the chords

Introduced in 2.6.0

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.

Examples
Clear wipes out the threads locals
use_synth :blade
use_octave 3

puts "before"         #=> "before"
puts current_synth      #=> :blade
puts current_octave     #=> 3
puts rand               #=> 0.75006103515625
puts tick               #=> 0

at do
  use_synth :tb303
  puts rand               #=> 0.9287109375
  clear
  puts "thread"         #=> "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.
  puts current_synth      #=> :beep

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

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

Introduced in 2.11.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.

Examples

  comment do # starting a block level comment:
    play 50 # not played
    sleep 1 # no sleep happens
    play 62 # not played
  end

Introduced in 2.0.0

Control running synth

control node (synth_node)

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

Options for control
Examples

## Basic control

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

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

s = synth :prophet, note: :e1, cutoff: 70, cutoff_slide: 8, release: 8 # start synth and specify slide time for cutoff opt
control s, cutoff: 130 # Change the cutoff value with a control.
                       # Cutoff will now slide over 8 beats from 70 to 130

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

notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle # get a random ordering of a scale

s = synth :beep, note: :e3, sustain: 8, note_slide: 0.05 # Start our synth running with a long sustain and short note slide time
64.times do
  control s, note: notes.tick                            # Keep quickly changing the note by ticking through notes repeatedly
  sleep 0.125
end

## Controlling FX

with_fx :bitcrusher, sample_rate: 1000, sample_rate_slide: 8 do |bc| # 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
  sample :loop_garzul, rate: 1
  control bc, sample_rate: 5000                                      # We can use our handle bc now just like we used s in the
                                                                     # previous example to modify the FX as it runs.
end

## Controlling chords

cg = play (chord :e4, :minor), sustain: 2  # start a chord
sleep 1
control cg, notes: (chord :c3, :major)     # transition to new chord.
                                           # Each note in the original chord is mapped onto
                                           # the equivalent in the new chord.

## Sliding between chords

cg = play (chord :e4, :minor), sustain: 4, note_slide: 3  # start a chord
sleep 1
control cg, notes: (chord :c3, :major)                    # slide to new chord.
                                                          # Each note in the original chord is mapped onto
                                                          # the equivalent in the new chord.

## Sliding from a larger to smaller chord

cg = play (chord :e3, :m13), sustain: 4, note_slide: 3  # start a chord with 7 notes
sleep 1
control cg, notes: (chord :c3, :major)                    # 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.

## Sliding from a smaller to larger chord
cg = play (chord :c3, :major), sustain: 4, note_slide: 3  # start a chord with 3 notes
sleep 1
control cg, notes: (chord :e3, :m13)                     # 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.

## Changing the slide rate

s = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 8 # Start a synth playing with a long cutoff slide
sleep 1                                                                # wait a beat
control s, cutoff: 130                                                 # change the cutoff so it starts sliding slowly
sleep 3                                                                # wait for 3 beats
control s, cutoff_slide: 1                                             # 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

## Controlling the last triggered synth

synth :prophet, note: :e1, release: 8                                  # Every time a synth is triggered, Sonic Pi automatically remembers the node
sleep 1
16.times do
  control note: (octs :e1, 3).tick                                     # This means we don't need to use an explicit variable to control the synth
  sleep 0.125                                                          # we last triggered.
end

## Controlling multiple synths without variables

synth :beep, release: 4                  # Trigger a beep synth
sleep 0.1
control note: :e5                        # Control last triggered synth (:beep)
sleep 0.5
synth :dsaw, release: 4                  # Next, trigger a dsaw synth
sleep 0.1
control note: :e4                        # Control last triggered synth (:dsaw)

Introduced in 2.0.0

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.

your_key Your value
another_key Another value
key All these opts are passed through to the thread which syncs
Options for cue
Examples

  in_thread do
    sync :foo # this parks the current thread waiting for a foo cue message to be received.
    sample :ambi_lunar_land
  end

  sleep 5

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

  in_thread do   # Start a metronome thread
    loop do      # Loop forever:
      cue :tick  # sending tick heartbeat messages
      sleep 0.5  # and sleeping for 0.5 beats between ticks
    end
  end

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

  in_thread do   # Start a metronome thread
    loop do      # Loop forever:
      cue [:foo, :bar, :baz].choose # sending one of three tick heartbeat messages randomly
      sleep 0.5  # and sleeping for 0.5 beats between ticks
    end
  end

  # We can now play sounds using the metronome:

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

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

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

  in_thread do
    loop do
      cue :tick, foo: 64  # sending tick heartbeat messages with a value :foo
      sleep 0.5
    end
  end

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

  loop do
    values = sync :tick
    play values[:foo]    # play the note value from :foo
  end

Introduced in 2.0.0

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.

Examples

puts current_arg_checks # Print out the current arg check setting

Introduced in 2.0.0

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.

Examples

  use_bpm 60
  puts current_beat_duration #=> 1

  use_bpm 120
  puts current_beat_duration #=> 0.5

Introduced in 2.6.0

Get current tempo

current_bpm

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.

Examples

  use_bpm 60
  puts current_bpm_mode    # => 60
  use_bpm 70
  puts current_bpm_mode    # => 70
  use_bpm :link
  puts current_bpm_mode    # => 120 (or whatever the current Link BPM value is)

Introduced in 2.0.0

Get current tempo mode

current_bpm_mode

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.

Examples

  use_bpm 60
  puts current_bpm_mode    # => 60
  use_bpm 70
  puts current_bpm_mode    # => 70
  use_bpm :link
  puts current_bpm_mode    # => :link

Introduced in 4.0.0

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.

Examples

puts current_cent_tuning # Print out the current cent shift

Introduced in 2.9.0

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.

Examples

puts current_debug # Print out the current debug setting

Introduced in 2.0.0

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.

Examples

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

Introduced in 3.0.0

Get current octave shift

current_octave

Returns the octave shift value.

This can be set via the fns use_octave and with_octave.

Examples

puts current_octave # Print out the current octave shift

Introduced in 2.9.0

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.

Examples

  puts current_random_seed # Print out the current random seed

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

Introduced in 2.10.0

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.

Examples

  puts current_random_source # Print out the current random source

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

Introduced in 4.0.0

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.

Examples

use_sample_defaults amp: 0.5, cutoff: 80
sample :loop_amen # Plays amen break with amp 0.5 and cutoff 80
puts current_sample_defaults #=> Prints {amp: 0.5, cutoff: 80}

Introduced in 2.5.0

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!.

Examples

set_sched_ahead_time! 0.5
puts current_sched_ahead_time # Prints 0.5

Introduced in 2.0.0

Get current synth

current_synth

Returns the current synth name.

This can be set via the fns use_synth and with_synth.

Examples

puts current_synth # Print out the current synth name

Introduced in 2.0.0

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.

Examples

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

Introduced in 2.0.0

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.

Examples

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

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

Introduced in 3.0.0

Get current transposition

current_transpose

Returns the current transpose value.

This can be set via the fns use_transpose and with_transpose.

Examples

puts current_transpose # Print out the current transpose value

Introduced in 2.0.0

Get current volume

current_volume

Returns the current volume.

This can be set via the fn set_volume!.

Examples

puts current_volume # Print out the current volume
set_volume! 2
puts current_volume #=> 2

Introduced in 2.0.0

Decrement

dec n (number)

Decrement a number by 1. Equivalent to n - 1

Options for dec
Examples
dec 1 # returns 0
dec -1 # returns -2

Introduced in 2.1.0

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.

Examples

  # Define a new function called foo
  define :foo do
    play 50
    sleep 1
  end

  # Call foo on its own
  foo

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

  # Define a new function called play2, taking one parameter
  define :play2 do |x|
    play x, release: 2
  end

  # Call play2, passing in a value for the parameter
  play2 42

Introduced in 2.0.0

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

override If set to true, re-definitions are allowed and this acts like define
Options for defonce
Examples


  defonce :foo do  # Define a new function called foo
    sleep 1        # 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.
    puts "hello" # Print hello
    10             # Return a value of 10
  end

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

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



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

  puts 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:
  3.times do
    play foo  # play 10
  end

  defonce :bar do
    50
  end

  play bar # plays 50

  defonce :bar do # This redefinition doesn't work due to the behaviour of defonce
    70
  end

  play bar # Still plays 50

  defonce :bar, override: true do  # Force definition to take place with override option
    80
  end

  play bar # plays 80

Introduced in 2.0.0

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

Examples

play degree(:iii, :D3, :major) # major third up from :D3
play degree(3, :C3, :minor) # minor third up from :C3
play degree('d5', :B3, :major) # diminished fifth up from :B3

chrd = []
[:i, :iii, :v, :dvii, :dix, :Axi, :xiii].each do |d|  # for each degree in the chord
  chrd.append (degree d, :Fs, :major)  # add the corresponding note
end
play chrd  # play an F# 13+11-9 chord, using roman numeral symbols

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

Introduced in 2.1.0

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.

Examples

  use_bpm 60   # Set the BPM to 60

  density 2 do       # BPM for block is now 120
                     # block is called 2.times
    sample :bd_haus # sample is played twice
    sleep 0.5        # sleep is 0.25s
  end

  density 2 do |idx| # You may also pass a param to the block similar to n.times
    puts idx         # prints out 0, 1
    sleep 0.5        # sleep is 0.25s
  end
  

  density 0.5 do          # 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.
    play 80, release: 1   # plays note 80 with 2s release
    sleep 0.5             # sleep is 1s
  end
  

Introduced in 2.3.0

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.

Examples

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

  dice 3 # will return a number between 1 and 3 inclusively

Introduced in 2.0.0

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.

Examples
(doubles 60, 2)  #=> (ring 60, 120)
(doubles 1.5, 3) #=> (ring 1.5, 3, 6)
(doubles 1.5, 5) #=> (ring 1.5, 3, 6, 12, 24)
(doubles 100, -4) #=> (ring 100, 50, 25, 12.5)

Introduced in 2.10.0

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.

Examples

eval_file "~/path/to/sonic-pi-code.rb" #=> will run the contents of this file

Introduced in 3.2.0

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.

Examples

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

  factor?(11, 2) #false - 11 is not a multiple of 2
  

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

Introduced in 2.1.0

Get all FX names

fx_names

Return a list of all the FX available

Examples

Introduced in 2.10.0

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.

Examples

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

set :foo, 3
get[:foo] #=> returns 3

in_thread do
  set :foo, 3
end

in_thread do
  puts get[:foo]  #=> always returns 3 (no race conditions here!)
end

Introduced in 3.0.0

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.

Examples
(halves 60, 2)  #=> (ring 60, 30)
(halves 120, 3) #=> (ring 120, 60, 30)
(halves 120, 5) #=> (ring 120, 60, 30, 15, 7.5)
(halves 30, -5) #=> (ring 30, 60, 120, 240, 480)

Introduced in 2.10.0

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.

Examples
hz_to_midi(261.63) #=> 60.0003

Introduced in 2.0.0

Run code block at the same time

in_thread

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.

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.
Options for in_thread
Examples

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

  loop do      # This code is never executed.
    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.

  in_thread do
    # (a)
    loop do
      # (a)
      play 50
      sleep 1
    end
  end

  # (b)

  loop do      # This loop is executed thanks to the thread above
    play 55
    sleep 0.5
  end

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

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

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

  in_thread(name: :foo) do # Here we've created a named thread
    loop do
      sample :drum_bass_hard
      sleep 1
    end
  end

  in_thread(name: :foo) do # This thread isn't created as the name is
    loop do                # the same as the previous thread which is
      sample :elec_chime   # still executing.
      sleep 0.5
    end
  end

   # Named threads work well with functions for live coding:
  define :foo do  # Create a function foo
    play 50       # which does something simple
    sleep 1       # and sleeps for some time
  end

  in_thread(name: :main) do  # Create a named thread
    loop do                  # which loops forever
      foo                    # calling our function
    end
  end

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

  #Delaying the start of a thread
  in_thread delay: 1 do
    sample :ambi_lunar_land # this sample is not triggered at time 0 but after 1 beat
  end

  play 80                   # Note 80 is played at time 0
  

Introduced in 2.0.0

Increment

inc n (number)

Increment a number by 1. Equivalent to n + 1

Options for inc
Examples
inc 1 # returns 2
inc -1 # returns 0

Introduced in 2.1.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.

Options for kill
Examples

# store a reference to a running synth in a variable called foo:
foo = play 50, release: 4
sleep 1
# foo is still playing, but we can kill it early:
kill foo
bar = sample :loop_amen
sleep 0.5
kill bar

Introduced in 2.0.0

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.

Examples
(knit 1, 5)    #=> (ring 1, 1, 1, 1, 1)
(knit :e2, 2, :c2, 3) #=> (ring :e2, :e2, :c2, :c2, :c2)

Introduced in 2.2.0

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.

steps number of slices or segments along the line
inclusive boolean value representing whether or not to include finish value in line
Options for line
Examples
(line 0, 4, steps: 4)    #=> (ring 0.0, 1.0, 2.0, 3.0)
(line 5, 0, steps: 5)    #=> (ring 5.0, 4.0, 3.0, 2.0, 1.0)
(line 0, 3, inclusive: true) #=> (ring 0.0, 1.0, 2.0, 3.0)

Introduced in 2.5.0

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 linksync, usebpm :link, setlinkbpm!

Examples

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

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

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

Introduced in 4.0.0

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.

Examples

Introduced in 4.0.0

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. .

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.
Options for live_audio
Examples

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

# Specify an input
live_audio :foo, input: 3  # Play whatever audio is coming into the sound card on input 3

# Work with stereo input
live_audio :foo, input: 3, stereo: true  # Play whatever audio is coming into the sound card on inputs 3 and 4
                                         # as a stereo stream
# Switching audio contexts (i.e. changing FX)
live_audio :guitar     # Play whatever audio is coming into the sound card on input 1

sleep 2                # Wait for 2 seconds then...

with_fx :reverb do
  live_audio :guitar   # Add reverb to the audio from input 1
end

sleep 2                # Wait for another 2 seconds then...

live_audio :guitar     # Remove the reverb from input 1

# Working with live_loops

live_loop :foo do
  with_fx [:reverb, :distortion, :echo].choose do   # chooses a new FX each time round the live loop
    live_audio :voice                               # the audio stream from input 1 will be moved to the
  end                                               # new FX and the old FX will complete and finish as normal.
  sleep 8
end

# Stopping

live_audio :foo            #=> start playing audio from input 1
live_audio :bar, input: 2  #=> start playing audio from input 2

sleep 3                    #=> wait for 3s...

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

Introduced in 3.0.0

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 inthread, they behave similarly. See the inthread 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_loops called :foo only one will be running. Another important aspect of live_loops 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_loops 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_loops.

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 liveloop on creation with both the delay: and sync: opts. See their respective docstrings. If both delay: and sync: are specified, on initial liveloop creation first the delay will be honoured and then the sync.

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.
Options for live_loop
Examples

## Define and start a simple live loop

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

## Every live loop must sleep or sync

live_loop :ping do  # Create a live loop called :ping
  sample :elec_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.
end

## Multiple live loops will play at the same time
live_loop :foo do  # Start a live loop called :foo
  play 70
  sleep 1
end

live_loop :bar do  # Start another live loop called :bar
  sample :bd_haus  # Both :foo and :bar will be playing
  sleep 0.5        # at the same time.
end

## Live loops inherit external use_* thread locals
use_bpm 30
live_loop :foo do
  play 70           # live loop :foo now has a BPM of 30
  sleep 1           # This sleep will be for 2 seconds
end

## Live loops can have their own thread locals
live_loop :foo do
  use_bpm 30       # Set the BPM of live loop :foo to 30
  play 70
  sleep 1          # This sleep will be for 2 seconds
end

live_loop :bar do
  use_bpm 120      # Set the BPM of live loop :bar to 120
  play 82
  sleep 1          # This sleep will be for 0.5 seconds
end

## Live loops can pass values between iterations
live_loop :foo do |a|  # pass a param (a) to the block (inits to 0)
  puts a               # prints out all the integers
  sleep 1
  a += 1               # increment a by 1 (last value is passed back into the loop)
end
  

## Live loop names must be unique
live_loop :foo do  # Start a live loop called :foo
  play 70
  sleep 1
end

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

## You can sync multiple live loops together
live_loop :foo, sync: :bar do # Wait for a :bar cue event before starting :foo
 play 70                      # Live loop :foo is therefore blocked and does
 sleep 1                      # not make a sound initially
end

sleep 4                       # Wait for 4 beats

live_loop :bar do             # Start a live loop called :foo which will emit a :bar
  sample :bd_haus             # cue message therefore releasing the :foo live loop.
  sleep 0.5                   # Live loop :foo therefore starts and also inherits the
end                           # 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.

Introduced in 2.1.0

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.

Examples

load_buffer "~/sonic-pi-tracks/phat-beats.rb" # will replace content of current buffer with contents of the file

Introduced in 2.10.0

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.

Examples

load_example :rerezzed # will replace content of current buffer with the rerezzed example

Introduced in 2.10.0

Pre-load first matching sample

load_sample path (string)

Given a path to a .wav, .wave, .aif, .aiff, .ogg, .oga or .flac 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.

Examples

load_sample :elec_blip # :elec_blip is now loaded and ready to play as a sample
sample :elec_blip # No delay takes place when attempting to trigger it
# Using source and filter pre-args
dir = "/path/to/sample/dir"
load_sample dir # loads first matching sample in "/path/to/sample/dir"
load_sample dir, 1 # loads sample with index 1 in "/path/to/sample/dir"
load_sample dir, :foo # loads sample with name "foo" in "/path/to/sample/dir"
load_sample dir, "quux" # loads first sample with file name containing "quux" in "/path/to/sample/dir"
load_sample dir, /[Bb]ar/ # loads first sample which matches regex /[Bb]ar/ in "/path/to/sample/dir"

Introduced in 2.0.0

Pre-load all matching samples

load_samples paths (list)

Given a directory containing multiple .wav, .wave, .aif, .aiff, .ogg, .oga or .flac 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.

Examples

 load_sample :elec_blip # :elec_blip is now loaded and ready to play as a sample
 sample :elec_blip # No delay takes place when attempting to trigger it
# Using source and filter pre-args
 dir = "/path/to/sample/dir"
 load_sample dir # loads all samples in "/path/to/sample/dir"
 load_sample dir, 1 # loads sample with index 1 in "/path/to/sample/dir"
 load_sample dir, :foo # loads sample with name "foo" in "/path/to/sample/dir"
 load_sample dir, "quux" # loads all samples with file names containing "quux" in "/path/to/sample/dir"
 load_sample dir, /[Bb]ar/ # loads all samples which match regex /[Bb]ar/ in "/path/to/sample/dir"

 

Introduced in 2.0.0

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/")
)
Examples
load_synthdef "~/Desktop/my_noises/whoosh.scsyndef" # Load whoosh synthdef design.

Introduced in 4.0.0

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/")
)
Examples
load_synthdefs "~/Desktop/my_noises" # Load all synthdefs in my_noises folder

Introduced in 2.0.0

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.

offset Offset to add to index returned. Useful when calling look on lists, rings and vectors to offset the returned value
Options for look
Examples

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

  puts look #=> 0 # A look is always 0 before the first tick
  tick # advance the tick
  puts look #=> 0 # Note: a look is still 0 after the first tick.
  tick
  puts look #=> 1
  puts look #=> 1 # making multiple calls to look doesn't affect tick value
  tick
  puts look #=> 2
  

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

  # You can call look on lists and rings
  live_loop :foo do
    tick                                      # advance the default tick
    use_synth :beep
    play (scale :e3, :minor_pentatonic).look  # look into the default tick to play all notes in sequence
    sleep 0.5
    use_synth :square
    play (ring :e1, :e2, :e3).look, release: 0.25 # use the same look on another ring
    sleep 0.25
  end
  

# Returns numbers unchanged if single argument
puts look(0)     #=> 0
puts look(4)     #=> 4
puts look(-4)    #=> -4
puts look(20.3)  #=> 20.3

Introduced in 2.6.0

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.

Examples


play 70       # note 70 is played

loop do
  play 50     # This loop will repeat notes 50 and 62 forever
  sleep 1
  play 62
  sleep 2
end

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

Introduced in 2.0.0

Create an immutable map

map list (array)

Create a new immutable key/value map from args.

Examples
(map foo: 1, bar: 2)[:foo] #=> 1
(map foo: 1, bar: 2)[:bar] #=> 2
(map foo: 1, bar: 2)[:quux] #=> nil

Introduced in 2.11.0

Linear scaling algorithm

math_scale ()

Scales a given input value within the specified input range to a corresponding value in the specified output range using the formula:

       (out_max - out_min) (val - in_min)

f (x) = ——————————– + outmin inmax - in_min

Examples
math_scale 0.5, 0, 1, 10, 20 #=> 15

Introduced in 3.0.0

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

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).
Options for midi
Examples
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.
midi :off, channel: 3 #=> Turn off all notes on channel 3 on all connected MIDI ports
midi :e1, channel: 3, port: "foo" #=> Play note :E1 for 1 beats on channel 3 on MIDI port named "foo" only

live_loop :arp do
  midi (octs :e1, 3).tick, sustain: 0.1 # repeatedly play a ring of octaves
  sleep 0.125
end

Introduced in 3.0.0

Turn off all notes on MIDI devices

midi_all_notes_off

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

MIDI 1.0 Specification - Channel Mode Messages - All Notes Off

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).
Options for midi_all_notes_off
Examples
midi_all_notes_off #=> Turn off all notes on MIDI devices on all channels (and ports)
midi_all_notes_off channel: 2 #=> Turn off all notes on MIDI devices on channel 2

Introduced in 3.0.0

Send MIDI control change message

midi_cc control_num (midi), value (midi)

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

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).
Options for midi_cc
Examples
midi_cc 100, 32  #=> Sends MIDI cc message to control 100 with value 32 to all ports and channels
midi_cc :e7, 32  #=> Sends MIDI cc message to control 100 with value 32 to all ports and channels
midi_cc 100, 32, channel: 5  #=> Sends MIDI cc message to control 100 with value 32 on channel 5 to all ports
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
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

Introduced in 3.0.0

Send MIDI channel pressure (aftertouch) message

midi_channel_pressure val (midi)

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)

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).
Options for midi_channel_pressure
Examples
midi_channel_pressure 50  #=> Sends MIDI channel pressure message with value 50 to all ports and channels
midi_channel_pressure :C4  #=> Sends MIDI channel pressure message with value 60 to all ports and channels
midi_channel_pressure 0.5  #=> Sends MIDI channel pressure message with value 63.5 to all ports and channels
midi_channel_pressure 30, channel: [1, 5]  #=> Sends MIDI channel pressure message with value 30 on channel 1 and 5 to all ports

Introduced in 3.0.0

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

midi_clock_beat duration (beats)

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_warps.

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).
Options for midi_clock_beat
Examples
midi_clock_beat #=> Send 24 clock ticks over a period of 1 beat to all connected MIDI devices
midi_clock_beat 0.5 #=> Send 24 clock ticks over a period of 0.5 beats to all connected MIDI devices
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

live_loop :clock do  # Create a live loop which continually sends out MIDI clock
  midi_clock_beat    # events at the current BPM
  sleep 1
end
# Ensuring Clock Phase is Correct
live_loop :clock do
  midi_start if tick == 0 # Send a midi_start event the first time round the live loop only
  midi_clock_beat         # this will not just send a steady clock beat, but also ensure
  sleep 1                 # the clock phase of the MIDI device matches Sonic Pi.
end

Introduced in 3.0.0

Send an individual MIDI clock tick

midi_clock_tick

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

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).
Options for midi_clock_tick
Examples
midi_clock_tick #=> Send an individual clock tick to all connected MIDI devices on all ports.

Introduced in 3.0.0

Send MIDI system message - continue

midi_continue

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

port MIDI Port(s) to send the continue message to
Options for midi_continue
Examples
midi_continue #=> Send continue message to all connected MIDI devices

Introduced in 3.0.0

Disable local control on MIDI devices

midi_local_control_off

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

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).
Options for midi_local_control_off
Examples
midi_local_control_off #=> Disable local control on MIDI devices on all channels (and ports)
midi_local_control_off channel: 2 #=> Disable local control on MIDI devices on channel 2

Introduced in 3.0.0

Enable local control on MIDI devices

midi_local_control_on

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

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).
Options for midi_local_control_on
Examples
midi_local_control_on #=> Enable local control on MIDI devices on all channels (and ports)
midi_local_control_on channel: 2 #=> Enable local control on MIDI devices on channel 2

Introduced in 3.0.0

Set Omni/Mono/Poly mode

midi_mode mode (mode_keyword)

Valid modes are:

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

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).
Options for midi_mode
Examples
midi_mode :omni_on #=> Turn Omni Mode On on all ports and channels
midi_mode :mono, num_chans: 5 #=> Mono Mode On, Omni off using 5 channels.
midi_mode :mono, num_chans: 0 #=> Mono Mode On, Omni on.
midi_mode :mono #=> Mono Mode On, Omni off using 16 channels (the default) .

Introduced in 3.0.0

Send MIDI note off message

midi_note_off note (midi), release_velocity (midi)

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

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).
Options for midi_note_off
Examples
midi_note_off :e3 #=> Sends MIDI note off for note :e3 with the default release velocity of 127 to all ports and channels
midi_note_off :e3, 12  #=> Sends MIDI note off for note :e3 with velocity 12 on all channels
midi_note_off :e3, 12, channel: 3  #=> Sends MIDI note off for note :e3 with velocity 12 to channel 3
midi_note_off :e3, velocity: 100 #=> Sends MIDI note off for note :e3 with release velocity 100
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
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
midi_note_off :e3, channel: [1, 3, 5] #=> Send MIDI note off for note :e3 to channels 1, 3, 5 on all connected ports
midi_note_off :e3, port: ["foo", "bar"] #=> Send MIDI note off for note :e3 to all channels on ports named "foo" and "bar"
midi_note_off :e3, channel: 1, port: "foo" #=> Send MIDI note off for note :e3 only on channel 1 on port "foo"

Introduced in 3.0.0

Send MIDI note on message

midi_note_on note (midi), velocity (midi)

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

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).
Options for midi_note_on
Examples
midi_note_on :e3  #=> Sends MIDI note on for note :e3 with the default velocity of 12 to all ports and channels
midi_note_on :e3, 12  #=> Sends MIDI note on for note :e3 with velocity 12 to all channels
midi_note_on :e3, 12, channel: 3  #=> Sends MIDI note on for note :e3 with velocity 12 on channel 3
midi_note_on :e3, velocity: 100 #=> Sends MIDI note on for note :e3 with velocity 100
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
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
midi_note_on :e3, channel: [1, 3, 5] #=> Send MIDI note on for note :e3 to channels 1, 3, 5 on all connected ports
midi_note_on :e3, port: ["foo", "bar"] #=> Send MIDI note on for note :e3 to all channels on ports named "foo" and "bar"
midi_note_on :e3, channel: 1, port: "foo" #=> Send MIDI note on for note :e3 only on channel 1 on port "foo"

Introduced in 3.0.0

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.

Examples
(midi_notes :d3, :d4, :d5) #=> (ring 50, 62, 74)
(midi_notes :d3, 62,  nil) #=> (ring 50, 62, nil)

Introduced in 2.7.0

Send MIDI program change message

midi_pc program_num (midi)

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

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).
Options for midi_pc
Examples
midi_pc 100  #=> Sends MIDI pc message to all ports and channels
midi_pc :e7  #=> Sends MIDI pc message to all ports and channels
midi_pc 100, channel: 5  #=> Sends MIDI pc message on channel 5 to all ports
midi_pc 100, port: ["foo", "bar"], channel: 5  #=> Sends MIDI pc message on channel 5 to ports named "foo" and "bar"
midi_pc 100, channel: [1, 5]  #=> Sends MIDI pc message on channel 1 and 5 to all ports

Introduced in 3.1.0

Send MIDI pitch bend message

midi_pitch_bend delta (float01)

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

MIDI 1.0 Specification - Channel Voice Messages - Pitch Bend Change

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).
Options for midi_pitch_bend
Examples
midi_pitch_bend 0  #=> Sends MIDI pitch bend message with value 0 to all ports and channels
midi_pitch_bend 1  #=> Sends MIDI pitch bend message with value 16383 to all ports and channels
midi_pitch_bend 0.5  #=> Sends MIDI pitch bend message with value 8192 to all ports and channels
midi_pitch_bend delta_midi: 8192  #=> Sends MIDI pitch bend message with value 8192 to all ports and channels
midi_pitch_bend 0, channel: [1, 5]  #=> Sends MIDI pitch bend message with value 0 on channel 1 and 5 to all ports

Introduced in 3.0.0

Send a MIDI polyphonic key pressure message

midi_poly_pressure note (midi), value (midi)

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)

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).
Options for midi_poly_pressure
Examples
midi_poly_pressure 100, 32  #=> Sends a MIDI poly key pressure message to control note 100 with value 32 to all ports and channels
midi_poly_pressure :e7, 32  #=> Sends a MIDI poly key pressure message to control note 100 with value 32 to all ports and channels
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
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
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

Introduced in 3.0.0

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.

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).
Options for midi_raw
Examples
midi_raw 176, 121, 0  #=> Sends the MIDI reset command
midi_raw 176.1, 120.5, 0.49  #=> Sends the MIDI reset command (values are rounded down, up and down respectively)
midi_raw 0xb0, 0x79, 0x0  #=> Sends the MIDI reset command
midi_raw 0b10110000, 0b01111001, 0b00000000  #=> Sends the MIDI reset command

Introduced in 3.0.0

Reset MIDI devices

midi_reset value (number)

All controller values are reset to their defaults.

MIDI 1.0 Specification - Channel Mode Messages - Reset All Controllers

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).
Options for midi_reset
Examples
midi_reset #=> Reset MIDI devices on all channels (and ports)
midi_reset channel: 2 #=> Reset MIDI devices on channel 2

Introduced in 3.0.0

Silence all MIDI devices

midi_sound_off

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

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).
Options for midi_sound_off
Examples
midi_sound_off #=> Silence MIDI devices on all ports and channels
midi_sound_off channel: 2 #=> Silence MIDI devices on channel 2

Introduced in 3.0.0

Send MIDI system message - start

midi_start

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

Examples
midi_start #=> Send start message to all connected MIDI devices

Introduced in 3.0.0

Send MIDI system message - stop

midi_stop

Stops the current sequence.

MIDI 1.0 Specification - System Real-Time Messages - Start

port MIDI Port(s) to send the stop message to
Options for midi_stop
Examples
midi_stop #=> Send stop message to all connected MIDI devices

Introduced in 3.0.0

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

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).
Options for midi_sysex
Examples
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

Introduced in 3.2.0

MIDI to Hz conversion

midi_to_hz note (symbol_or_number)

Convert a midi note to hz

Examples
midi_to_hz(60) #=> 261.6256

Introduced in 2.0.0

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.

Examples

Introduced in 2.1.0

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)

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

# These all return 60 which is the midi number for middle C (octave 4)
puts note(60)
puts note(:C)
puts note(:C4)
puts note('C')
# returns 60 - octave param has no effect if we pass in a number
puts note(60, octave: 2)

# These all return 36 which is the midi number for C2 (two octaves below middle C)
puts note(:C, octave: 2)
puts note(:C4, octave: 2) # note the octave param overrides any octaves specified in a symbol
puts note('C', octave: 2)

Introduced in 2.0.0

Get note info

note_info note (symbol_or_number)

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

octave The octave of the note. Overrides any octave declaration in the note symbol such as :c2. Default is 4
Options for note_info
Examples

puts note_info(:C, octave: 2)
# returns #

Introduced in 2.0.0

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!

pitches An array of notes (symbols or ints) to filter on. Octave information is ignored.
Options for note_range
Examples
(note_range :c4, :c5) # => (ring 60,61,62,63,64,65,66,67,68,69,70,71,72)
(note_range :c5, :c4) # => (ring 72,71,70,69,68,67,66,65,64,63,62,61,60)
(note_range :c4, :c5, pitches: (chord :c, :major)) # => (ring 60,64,67,72)
(note_range :c4, :c6, pitches: (chord :c, :major)) # => (ring 60,64,67,72,76,79,84)
(note_range :c4, :c5, pitches: (scale :c, :major)) # => (ring 60,62,64,65,67,69,71,72)
(note_range :c4, :c5, pitches: [:c4, :g2]) # => (ring 60,67,72)
live_loop :arpeggiator do
  # try changing the chord
  play (note_range :c4, :c5, pitches: (chord :c, :major)).tick
  sleep 0.125
end

Introduced in 2.6.0

Create a ring of octaves

octs start (note), num_octaves (pos_int)

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

Examples
(octs 60, 2)  #=> (ring 60, 72)
(octs :e3, 3) #=> (ring 52, 64, 76)

Introduced in 2.8.0

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.

Examples

on true do
  play 70     #=> will play 70 as true is truthy
end

on 1 do
  play 70     #=> will play 70 as 1 is truthy
end

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

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

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

on lambda{true} do
  play 70     #=> will play 70 as the lambda returns a truthy value
end

on lambda{false} do
  play 70     #=> will *not* play 70 as the lambda does not return a truthy value
end

on lambda{[true, false].choose} do
  play 70     #=> will maybe play 70 depending on the choice in the lambda
end

Introduced in 2.10.0

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

Examples

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

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

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

Introduced in 2.0.0

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

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

use_osc "localhost", 7000  # Specify port 7000 on this machine
osc "/foo/bar"             # Send an OSC message with path "/foo/bar"
                             # and no arguments
 # Send an OSC message with arguments to another program on the same machine

use_osc "localhost", 7000        # Specify port 7000 on this machine
osc "/foo/bar", 1, 3.89, "baz" # 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"
 # Send an OSC message with arguments to another program on a different machine

use_osc "10.0.1.5", 7000         # Specify port 7000 on the machine with address 10.0.1.5
osc "/foo/bar", 1, 3.89, "baz" # 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"
 # OSC messages honour the timing system

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

sleep 1                # Wait for 1 beat

osc "/baz/quux"       # Send an OSC message with path /baz/quux at *exactly* the
play 72                 # same time as note 72 is played
 # Send a incrementing OSC counter

live_loop :foo do             # Start a live loop called :foo
  osc "/counter", tick      # Send an OSC message with the path /counter
                              # with successive whole numbers (0, 1, 2, 3.. etc.)
                              # each time round the live loop
  sleep 1                     # Repeat the live loop every 1 beat
end
 # OSC messages can be sent from within time_warp

time_warp 0.5 do
  osc "/foo/bar"       # Send an OSC message with path /foo/bar at 0.5 beats
end

sleep 1                  # Wait for 1 beat

time_warp -0.1 do
  osc "/baz/quux"      # Send an OSC message with path /baz/quux at 0.9 beats
end

Introduced in 3.0.0

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.

Examples

osc_send "localhost", 7000, "/foo/baz"  # Send an OSC message to port 7000 on the same machine

use_osc "localhost", 7010                 # set hostname and port
osc "/foo/baz"                            # Send an OSC message to port 7010

osc_send "localhost", 7000, "/foo/baz"  # Send an OSC message to port 7000
                                            # (ignores use_osc settings)

Introduced in 3.0.0

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)

skip Number of rands to skip over with each successive pick
Options for pick
Examples

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

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

puts (ring 1, 2).pick(5) #=> (ring 2, 2, 1, 1, 1)

puts (ring 1, 2, 3).pick #=> (ring 3)

# Using pick for random sample onsets
live_loop :foo do
  sample :loop_amen, onset: pick   # pick a random onset value each time
  sleep 0.125
end

Introduced in 2.10.0

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.

Examples
pitch_to_ratio 12 #=> 2.0
pitch_to_ratio 1 #=> 1.05946
pitch_to_ratio -12 #=> 0.5
sample :ambi_choir, rate: pitch_to_ratio(3) # Plays :ambi_choir 3 semitones above default.

# Play a chromatic scale of semitones
(range 0, 16).each do |n|                  # For each note in the range 0->16
  sample :ambi_choir, rate: pitch_to_ratio(n) # play :ambi_choir at the relative pitch
  sleep 0.5                                # and wait between notes
end

Introduced in 2.5.0

Play current synth

play note (symbol_or_number)

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.

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.
Options for play
Examples

play 50 # Plays note 50 on the current synth
play 50, attack: 1 # Plays note 50 with a fade-in time of 1s
play 62, pan: -1, release: 3 # Play note 62 in the left ear with a fade-out time of 3s.
 # controlling a synth synchronously
s = play :e3, release: 4
sleep 1
control s, note: :e5
sleep 0.5
use_synth :dsaw
play :e3   # This is triggered after 1.5s from start
 # Controlling a synth asynchronously
play :e3, release: 4 do |s|
  sleep 1                                               # This block is run in an implicit in_thread
  control s, note: :e5                                  # and therefore is asynchronous
end

sleep 0.5
use_synth :dsaw
play :e3 # This is triggered after 0.5s from start

Introduced in 2.0.0

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.

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.
Options for play_chord
Examples

play_chord [40, 45, 47]

# same as:

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

# same as:

play 40, amp: 0.5
play 45, amp: 0.5
play 47, amp: 0.5
play_chord chord(:e3, :minor)

Introduced in 2.0.0

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 usesynth and withsynth for changing the current synth.

Options for play_pattern
Examples

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
play_pattern [:d3, :c1, :Eb5] # You can use keyword notes
play_pattern [:d3, :c1, :Eb5], amp: 0.5, cutoff: 90 # Supports the same arguments as play:

Introduced in 2.0.0

Play pattern of notes with specific times

play_pattern_timed notes (list), times (list_or_number)

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.

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.
Options for play_pattern_timed
Examples

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

# same as:

play 40, sustain: 1
sleep 1
play 42, sustain: 2
sleep 2
play 44, sustain: 3
sleep 3
play_pattern_timed [40, 42, 44, 46, 49], [1, 0.5]

# same as:

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
play_pattern_timed [40, 42, 44, 46], [0.5]

# same as:

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
play_pattern_timed [40, 42, 44], [1, 2, 3, 4, 5]

# same as:

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

# effectively same as:

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

Introduced in 2.0.0

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.

Examples
print "hello there"   #=> will print the string "hello there" to the output pane
print 5               #=> will print the number 5 to the output pane
print foo             #=> will print the contents of foo to the output pane

Introduced in 2.0.0

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.

Examples
print "hello there"   #=> will print the string "hello there" to the output pane
print 5               #=> will print the number 5 to the output pane
print foo             #=> will print the contents of foo to the output pane

Introduced in 2.0.0

Quantise a value to resolution

quantise n (number), step (positive_number)

Round value to the nearest multiple of step resolution.

Examples

  quantise(10, 1) # 10 is already a multiple of 1, so returns 10

  quantise(10, 1.1) # Returns 9.9 which is 1.1 * 9

  quantise(13.3212, 0.1) # 13.3

  quantise(13.3212, 0.2) # 13.4

  quantise(13.3212, 0.3) # 13.2

  quantise(13.3212, 0.5) # 13.5

Introduced in 2.1.0

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.

Examples
(ramp 1, 2, 3)[0] #=> 1
(ramp 1, 2, 3)[1] #=> 2
(ramp 1, 2, 3)[2] #=> 3
(ramp 1, 2, 3)[3] #=> 3
(ramp 1, 2, 3)[1000] #=> 3
(ramp 1, 2, 3)[-1] #=> 1
(ramp 1, 2, 3)[-1000] #=> 1

Introduced in 2.6.0

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.

Examples

  print rand(0.5) #=> will print a number like 0.375030517578125 to the output pane

Introduced in 2.0.0

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.

Examples

  # Basic rand stream rollback

  puts rand # prints 0.75006103515625

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

  puts rand # prints 0.75006103515625 again!
  puts rand # prints 0.733917236328125

  # Jumping back multiple places in the rand stream

  puts rand # prints 0.75006103515625
  puts rand # prints 0.733917236328125
  puts rand # prints 0.464202880859375
  puts rand # prints 0.24249267578125

  rand_back(3) # 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.

  puts rand # prints  0.733917236328125 again!
  puts rand # prints  0.464202880859375

Introduced in 2.7.0

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

Examples

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

Introduced in 2.0.0

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.

Examples

print rand_i_look(5) # will print either 0, 1, 2, 3, or 4 to the output pane

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

Introduced in 2.11.0

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.

Examples

print rand_look(0.5) # will print a number like 0.375030517578125 to the output pane

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

Introduced in 2.11.0

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.

Examples

  puts rand # prints 0.75006103515625
  puts rand # prints 0.733917236328125
  puts rand # prints 0.464202880859375
  puts rand # prints 0.24249267578125
  rand_reset  # reset the random stream
  puts rand # prints 0.75006103515625
  

Introduced in 2.7.0

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.

Examples

  # Basic rand stream skip

  puts rand # prints 0.75006103515625

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

  puts rand # prints 0.464202880859375

  # Jumping forward multiple places in the rand stream

  puts rand # prints 0.75006103515625
  puts rand # prints 0.733917236328125
  puts rand # prints 0.464202880859375
  puts rand # prints 0.24249267578125

  rand_reset  # reset the random stream

  puts rand # prints 0.75006103515625

  rand_skip(2) # 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

  puts rand 0.24249267578125

Introduced in 2.7.0

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

step Size of increment between steps; step size.
inclusive If set to true, range is inclusive of finish value
Options for range
Examples
(range 1, 5)    #=> (ring 1, 2, 3, 4)
(range 1, 5, inclusive: true) #=> (ring 1, 2, 3, 4, 5)
(range 1, 5, step: 2) #=> (ring 1, 3)
(range 1, -5, step: 2) #=> (ring 1, -1, -3)
(range 1, -5, step: 2)[-1] #=> -3

Introduced in 2.2.0

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.

Examples
ratio_to_pitch 2 #=> 12.0
ratio_to_pitch 0.5 #=> -12.0

Introduced in 2.7.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.

step Step size of value to quantise to.
Options for rdist
Examples

  print rdist(1, 0) #=> will print a number between -1 and 1
  

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

  loop do
    play :c3, pan: rdist(1) #=> Will play :c3 with random L/R panning
    sleep 0.125
  end

Introduced in 2.3.0

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.

Examples

# Basic Reset
use_synth :blade
use_octave 3

puts "before"         #=> "before"
puts current_synth      #=> :blade
puts current_octave     #=> 3
puts rand               #=> 0.75006103515625
puts tick               #=> 0

reset

puts "after"          #=> "after"
puts current_synth      #=> :beep
puts current_octave     #=> 0
puts rand               #=> 0.75006103515625
puts tick               #=> 0
Reset remembers defaults from when the thread was created:
use_synth :blade
use_octave 3

puts "before"         #=> "before"
puts current_synth      #=> :blade
puts current_octave     #=> 3
puts rand               #=> 0.75006103515625
puts tick               #=> 0

at do
  use_synth :tb303
  puts rand               #=> 0.9287109375
  reset
  puts "thread"          #=> "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
  puts current_synth      #=> :blade
  puts current_octave     #=> 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
  puts rand               #=> 0.9287109375
  puts tick               #=> 0
end

Introduced in 2.11.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 setmixercontrol!

Options for reset_mixer!
Examples

set_mixer_control! lpf: 70 # LPF cutoff value of main mixer is now 70
sample :loop_amen          # :loop_amen sample is played with low cutoff
sleep 3
reset_mixer!               # mixer is now reset to default values
sample :loop_amen          # :loop_amen sample is played with normal cutoff

Introduced in 2.9.0

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

Examples
puts rest? nil # true
puts rest? :r # true
puts rest? :rest # true
puts rest? 60 # false
puts rest? {} # false
puts rest? {note: :rest} # true
puts rest? {note: nil} # true
puts rest? {note: 50} # false

Introduced in 2.1.0

Create a ring buffer

ring list (array)

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

Examples
(ring 1, 2, 3)[0] #=> 1
(ring 1, 2, 3)[1] #=> 2
(ring 1, 2, 3)[3] #=> 1
(ring 1, 2, 3)[-1] #=> 3

Introduced in 2.2.0

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.

step Step size of value to quantise to.
Options for rrand
Examples

  print rrand(0, 10) #=> will print a number like 8.917730007820797 to the output pane

  loop do
    play rrand(60, 72) #=> Will play a random non-integer midi note between C4 (60) and C5 (72) such as 67.3453 or 71.2393
    sleep 0.125
  end

Introduced in 2.0.0

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

Examples

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

  loop do
    play rrand_i(60, 72) #=> Will play a random midi note between C4 (60) and C5 (72)
    sleep 0.125
  end

Introduced in 2.0.0

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

Examples

  use_bpm 120  # modifies all time to be half
  play 50
  sleep 1      # actually sleeps for half of a second
  play 62
  sleep rt(1)  # bypasses bpm scaling and sleeps for a second
  play 72

Introduced in 2.0.0

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.

Examples

run_code "sample :ambi_lunar_land" #=> will play the :ambi_lunar_land sample
# Works with any amount of code:
run_code "8.times do
play 60
sleep 1
end" # will play 60 8 times

Introduced in 2.11.0

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.

Examples

run_file "~/path/to/sonic-pi-code.rb" #=> will run the contents of this file

Introduced in 2.11.0

Trigger sample

sample name_or_path (symbol_or_string)

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.

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.
Options for sample
Examples

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

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

# Create a simple repeating bass drum
live_loop :bass do
  sample :bd_haus
  sleep 0.5
end

# Create a more complex rhythm with multiple live loops:
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

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

# Speed things up
sample :loop_amen, rate: 1.5 # Play the Amen break at 1.5x speed
                             # for a jungle/gabba sound

# Go backwards
sample :loop_amen, rate: -1 # Negative rates play the sample backwards

# Fast rewind
sample :loop_amen, rate: -3 # Play backwards at 3x speed for a fast rewind effect

# Start mid sample
sample :loop_amen, start: 0.5 # Start playback half way through

# Finish mid sample
sample :loop_amen, finish: 0.5 # Finish playback half way through

# Play part of a sample
sample :loop_amen, start: 0.125, finish: 0.25 # Play the second eighth of the sample

# Finishing before the start plays backwards
sample :loop_amen, start: 0.25, finish: 0.125 # Play the second eighth of the sample backwards

# Play a section of a sample at quarter speed backwards
sample :loop_amen, start: 0.125, finish: 0.25, rate: -0.25 # Play the second eighth of the
                                                           # amen break backwards at a
                                                           # quarter speed

# Control a sample synchronously
s = sample :loop_amen, lpf: 70
sleep 0.5
control s, lpf: 130
sleep 0.5
synth :dsaw, note: :e3 # This is triggered 1s from start
 # Controlling a sample asynchronously
sample :loop_amen, lpf: 70 do |s|
  sleep 1                                # This block is run in an implicit in_thread
  control s, lpf: 130                    # and therefore is asynchronous
end
sleep 0.5
synth :dsaw, note: :e3 # This is triggered 0.5s from start

# Play with slices
sample :loop_garzul, slice: 0      # => play the first 16th of the sample
sleep 0.5
4.times do
  sample :loop_garzul, slice: 1    # => play the second 16th of the sample 4 times
  sleep 0.125
end
sample :loop_garzul, slice: 4, num_slices: 4, rate: -1      # => play the final quarter backwards

# Build a simple beat slicer
use_sample_bpm :loop_amen                    # Set the BPM to match the amen break sample
live_loop :beat_slicer do
  n = 8                                      # Specify number of slices
                                             # (try changing to 2, 4, 6, 16 or 32)
  s = rand_i n                               # Choose a random slice within range
  sample :loop_amen, slice: s, num_slices: n # Play the specific part of the sample
  sleep 1.0/n                                # Sleep for the duration of the slice
end

# Play with the built-in low pass filter, high pass filter and compressor
sample :loop_amen, lpf: 80, hpf: 70, compress: 1, pre_amp: 10 # Make the amen break sound punchy.

# Use the cutoff filter envelopes
sample :loop_garzul, lpf_attack: 8 # Sweep the low pass filter up over 8 beats
sleep 8
sample :loop_garzul, hpf_attack: 8 # Sweep the high pass filter down over 8 beats

# Sample stretching
puts sample_duration :loop_industrial                   # => 0.88347
puts sample_duration :loop_industrial, beat_stretch: 1  # => 1
live_loop :industrial do
  sample :loop_industrial, beat_stretch: 1              # Stretch the sample to make it 1 beat long
  sleep 1                                               # This now loops perfectly.
                                                        # However, note that stretching/shrinking
                                                        # also modifies the pitch.
end

# Sample shrinking
puts sample_duration :loop_garzul                       # => 8
puts sample_duration :loop_garzul, beat_stretch: 6      # => 6
live_loop :garzul do
  sample :loop_garzul, beat_stretch: 6                  # As :loop_garzul is longer than 6 beats
                                                        # it is shrunk to fit. This increases the
                                                        # pitch.
  sleep 6
end

# Sample stretching matches the BPM
use_bpm 30                                              # Set the BPM to 30
puts sample_duration :loop_garzul                       # => 4.0 (at 30 BPM the sample lasts for 4 beats)
puts sample_duration :loop_garzul, beat_stretch: 6      # => 6.0
live_loop :garzul do
  sample :loop_garzul, beat_stretch: 6                  # The sample is stretched to match 6 beats at 30 BPM
  sleep 6
end

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

# Sample pack filtering
dir = "/path/to/dir/of/samples"                       # You can easily work with a directory of samples
sample dir                                              # Play the first sample in the directory
                                                        # (it is sorted alphabetically)
sample dir, 1                                           # Play the second sample in the directory
sample dir, 99                                          # 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).
sample dir, "120"                                     # Play the first sample in the directory that contains
                                                        # the substring "120".
                                                        # For example, this may be "beat1_120_rave.wav"
sample dir, "120", 1                                  # Play the second sample in the directory that contains
                                                        # the substring "120".
                                                        # For example, this may be "beat2_120_rave.wav"
sample dir, /beat[0-9]/                                 # 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
sample dir, /beat[0-9]0/, "100"                       # 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"

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

# Play with whole directories of samples
load_samples "tabla_"                                 # 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_"
live_loop :tabla do
  sample "tabla_", tick                               # Treat the matching samples as a ring and tick through them
  sleep 0.125
end

# Specify multiple sources
dir1 = "/path/to/sample/directory"
dir2 = "/path/to/other/sample/directory"
sample dir1, dir2, "foo"                              # 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.

# List contents recursively
dir = "/path/to/sample/directory"                     # By default the list of all top-level samples within the directory
                                                        # is considered.
dir_recursive = "/path/to/sample/directory/**"        # 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.
sample dir, 0                                           # Play the first top-level sample in the directory
sample dir_recursive, 0                                 # 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.

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

# Basic Onset Detection

sample :loop_tabla, start: 0, finish: 0.00763           # 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.
sleep 1
                                                        # Instead of specifying the start: and finish: values manually you can
                                                        # use the onset: option to find them for you using an integer index.
sample :loop_tabla, onset: 0                            # 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.
sleep 1

sample :loop_tabla, onset: 1                            # We can easily find the second percussive sound in the sample with
                                                        # onset: 1


# 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


live_loop :tabla do
  use_bpm 50                                            # We can choose our own BPM here - it doesn't need to match the sample
  sample :loop_tabla, onset: tick                       # tick through each onset in sequence
  sleep [0.125, 0.25].choose                            # randomly choose a delay between onset triggers
end

# Random Onset Triggering
                                                        # We can easily pick a random onset using the pick fn
use_bpm 50
live_loop :tabla do
  sample :loop_tabla, onset: pick                       # Each time round the live loop we now trigger a random onset
  sleep [0.125, 0.25].choose                            # creating an infinite stream of randomly selected drums
end


        

# Repeatable Random Onsets
                                                        # Instead of an infinite stream of choices, we can combine iteration
                                                        # and use_random_seed to create repeatable riffs:
live_loop :tabla do
  use_random_seed 30000                                 # every 8 times, reset the random seed, this resets the riff
  8.times do
    sample :loop_tabla, onset: pick
    sleep [0.125, 0.25].choose
  end
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.
live_loop :tabla do
  sample :loop_tabla, onset: pick, sustain: 0, release: 0.1 # 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.
  sleep [0.125, 0.25].choose
end

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

l = lambda {|c| puts c ; c[0]}                          # 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:

sample :loop_tabla, onset: l                            # (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.

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)

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)

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)

sample :loop_tabla, onset: 1, slice: 0, num_slices: 4                # 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)

sample :loop_tabla, onset: 1, slice: 0, num_slices: 4, finish: 0.5   # 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)

sample :loop_tabla, onset: 1, slice: 0, num_slices: 4, finish: 0.0, start: 0.5   # 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)

Introduced in 2.0.0

Get sample data

sample_buffer path (string)

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

Examples
see load_sample

Introduced in 2.0.0

Get duration of sample in beats

sample_duration path (string)

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

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.
Options for sample_duration
Examples

# Simple use
puts sample_duration(:loop_garzul) # returns 8.0 because this sample is 8 seconds long

# The result is scaled to the current BPM
use_bpm 120
puts sample_duration(:loop_garzul) # => 16.0
use_bpm 90
puts sample_duration(:loop_garzul) # => 12.0
use_bpm 21
puts sample_duration(:loop_garzul) # => 2.8

# Avoid using sample_duration to set the sleep time in live_loops

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

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

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

# The standard sample opts are also honoured

                                                                  # Playing a sample at standard speed will return standard length
sample_duration :loop_garzul, rate: 1                             # => 8.0

                                                                  # Playing a sample at half speed will double duration
sample_duration :loop_garzul, rate: 0.5                           # => 16.0

                                                                  # Playing a sample at double speed will halve duration
sample_duration :loop_garzul, rate: 2                             # => 4.0

                                                                  # Playing a sample backwards at double speed will halve duration
sample_duration :loop_garzul, rate: -2                            # => 4.0

                                                                  # Without an explicit sustain: opt attack: just affects amplitude not duration
sample_duration :loop_garzul, attack: 1                           # => 8.0
sample_duration :loop_garzul, attack: 100                         # => 8.0
sample_duration :loop_garzul, attack: 0                           # => 8.0

                                                                  # Without an explicit sustain: opt release: just affects amplitude not duration
sample_duration :loop_garzul, release: 1                          # => 8.0
sample_duration :loop_garzul, release: 100                        # => 8.0
sample_duration :loop_garzul, release: 0                          # => 8.0

                                                                  # Without an explicit sustain: opt decay: just affects amplitude not duration
sample_duration :loop_garzul, decay: 1                            # => 8.0
sample_duration :loop_garzul, decay: 100                          # => 8.0
sample_duration :loop_garzul, decay: 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.
sample_duration :loop_garzul, sustain: 0, attack: 0.5             # => 0.5
sample_duration :loop_garzul, sustain: 0, decay: 0.1              # => 0.1
sample_duration :loop_garzul, sustain: 0, release: 1              # => 1.0
sample_duration :loop_garzul, sustain: 2, attack: 0.5, release: 1 # => 3.5

                                                                  # If the envelope duration is longer than the sample it will not affect the
                                                                  # sample duration
sample_duration :loop_garzul, sustain: 0, attack: 8, release: 3   # => 8


                                                                  # All other opts are taken into account before the comparison with the envelope opts.
sample_duration :loop_garzul, rate: 10                            # => 0.8
sample_duration :loop_garzul, sustain: 0, attack: 0.9, rate: 10   # => 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.
sample_duration :loop_garzul, rpitch: 12                          # => 4.0
sample_duration :loop_garzul, rpitch: -12                         # => 16

                                                                  # The rpitch: and rate: opts combine together.
sample_duration :loop_garzul, rpitch: 12, rate: 2                 # => 2.0

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

                                                                  # The pitch_stretch: opt acts identically to beat_stretch when just considering sample
                                                                  # duration.
sample_duration :loop_garzul, pitch_stretch: 3                    # => 3.0
sample_duration :loop_garzul, pitch_stretch: 3, rate: 0.5         # => 6.0

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

# Triggering samples one after another

sample :loop_amen                    # start the :loop_amen sample
sleep sample_duration(:loop_amen)    # wait for the duration of :loop_amen before
sample :loop_amen                    # starting it again

Introduced in 2.0.0

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.

Examples

sample :loop_amen # The Amen break is now loaded into memory and played
sleep 2
sample :loop_amen # The Amen break is not loaded but played from memory
sleep 2
sample_free :loop_amen # The Amen break is freed from memory
sample :loop_amen # the Amen break is re-loaded and played

puts sample_info(:loop_amen).to_i # This returns the buffer id of the sample i.e. 1
puts sample_info(:loop_amen).to_i # The buffer id remains constant whilst the sample
                                  # is loaded in memory
sample_free :loop_amen
puts sample_info(:loop_amen).to_i # The Amen break is re-loaded and gets a *new* id.

sample :loop_amen
sample :ambi_lunar_land
sleep 2
sample_free :loop_amen, :ambi_lunar_land
sample :loop_amen                        # re-loads and plays amen
sample :ambi_lunar_land                  # re-loads and plays lunar land
# Using source and filter pre-args
dir = "/path/to/sample/dir"
sample_free dir # frees any loaded samples in "/path/to/sample/dir"
sample_free dir, 1 # frees sample with index 1 in "/path/to/sample/dir"
sample_free dir, :foo # frees sample with name "foo" in "/path/to/sample/dir"
sample_free dir, /[Bb]ar/ # frees sample which matches regex /[Bb]ar/ in "/path/to/sample/dir"

Introduced in 2.9.0

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.

Examples

sample :loop_amen        # load and play :loop_amen
sample :ambi_lunar_land  # load and play :ambi_lunar_land
sleep 2
sample_free_all
sample :loop_amen        # re-loads and plays amen

Introduced in 2.9.0

Get all sample groups

sample_groups

Return a list of all the sample groups available

Examples

Introduced in 2.0.0

Get sample information

sample_info path (string)

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

Examples
see load_sample

Introduced in 2.0.0

Test if sample was pre-loaded

sample_loaded? path (string)

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

Examples

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

Introduced in 2.2.0

Get sample names

sample_names group (symbol)

Return a ring of sample names for the specified group

Examples

Introduced in 2.0.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.

Examples

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

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

sample_paths "/path/to/samples/", "foo" #=> ring of all samples in /path/to/samples
                                                containing the string "foo" in their filename.

Introduced in 2.10.0

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.

num_octaves The number of octaves you'd like the scale to consist of. More octaves means a larger scale. Default is 1.
Options for scale
Examples

puts (scale :C, :major) # returns the following ring of MIDI note numbers: (ring 60, 62, 64, 65, 67, 69, 71, 72)
# anywhere you can use a list or ring of notes, you can also use scale
play_pattern (scale :C, :major)
# you can use the :num_octaves parameter to get more notes
play_pattern (scale :C, :major, num_octaves: 2)
# Scales can start with any note:
puts (scale 50, :minor) #=> (ring 50, 52, 53, 55, 57, 58, 60, 62)
puts (scale 50.1, :minor) #=> (ring 50.1, 52.1, 53.1, 55.1, 57.1, 58.1, 60.1, 62.1)
puts (scale :minor) #=> (ring 0, 2, 3, 5, 7, 8, 10, 12)
 # scales are also rings
live_loop :scale_player do
  play (scale :Eb3, :super_locrian).tick, release: 0.1
  sleep 0.125
end
 # scales starting with 0 are useful in combination with sample's rpitch:
live_loop :scaled_sample do
  sample :bass_trance_c, rpitch: (scale 0, :minor).tick
  sleep 1
end
# Sonic Pi supports a large range of scales:

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

Introduced in 2.0.0

All scale names

scale_names

Returns a ring containing all scale names known to Sonic Pi

Examples
puts scale_names #=>  prints a list of all the scales

Introduced in 2.6.0

Return information about the internal SuperCollider sound server

scsynth_info

Create a map of information about the running audio synthesiser SuperCollider.

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

Introduced in 2.11.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.

Examples

  set :foo, 1 #=> Stores the value 1 with key :foo

set :foo, 3  # Set :foo to 3
get[:foo] #=> returns 3

in_thread do
  set :foo, 3  # Set :foo to 3
end

in_thread do
  puts get[:foo]  #=> always returns 3 (no race conditions here!)
end

Introduced in 3.0.0

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.

Examples
set_audio_latency! 100 # Audio events will now be scheduled 100ms
                                                  # after the schedule ahead time
set_audio_latency! -200 # Audio events will now be scheduled 200ms
                                                  # before the schedule ahead time

Introduced in 3.1.0

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.

Examples

play 50 # Plays note 50
set_cent_tuning! 1
play 50 # Plays note 50.01

Introduced in 2.10.0

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.

Examples

set_control_delta! 0.1                 # Set control delta to 0.1

s = play 70, release: 8, note_slide: 8 # Play a note and set the slide time
control s, note: 82                    # 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.

Introduced in 2.1.0

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

Examples

use_bpm :link                                 # Switch to Link BPM mode
set_link_bpm! 30                              # Change Link BPM to 30

8.times do
  bpm += 10
  set_link_bpm! bpm                           # Gradually increase the Link BPM
  sample :loop_amen, beat_stretch: 2
  sleep 2
end

Introduced in 4.0.0

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!.

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.
Options for set_mixer_control!
Examples

set_mixer_control! lpf: 30, lpf_slide: 16 # slide the global lpf to 30 over 16 beats.

Introduced in 2.7.0

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.

Examples

set_recording_bit_depth! 24                 # Set recording bit depth to 24

Introduced in 2.11.0

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.

Examples
set_sched_ahead_time! 1 # Code will now run approximately 1 second ahead of audio.

Introduced in 2.0.0

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.

Examples

set_volume! 2 # Set the main system volume to 2
set_volume! -1 # Out of range, so sets main system volume to 0
set_volume! 7 # Out of range, so sets main system volume to 5

Introduced in 2.0.0

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

Examples

  shuffle [1, 2, 3, 4] #=> Would return something like: [3, 4, 2, 1] 

  shuffle "foobar"  #=> Would return something like: "roobfa"

Introduced in 2.1.0

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.

Examples

  # Without calls to sleep, all sounds would happen at once:

  play 50  # This is actually a chord with all notes played simultaneously
  play 55
  play 62

  sleep 1  # Create a gap, to allow a moment's pause for reflection...

  play 50  # Let's try the chord again, but this time with sleeps:
  sleep 0.5 # With the sleeps, we turn a chord into an arpeggio
  play 55
  sleep 0.5
  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:

  use_bpm 120
  play 50
  sleep 1 # This actually sleeps for 0.5 seconds as we're now at double speed
  play 55
  sleep 1
  play 62

  # Let's go down to half speed:

  use_bpm 30
  play 50
  sleep 1 # This now sleeps for 2 seconds as we're now at half speed.
  play 55
  sleep 1
  play 62
  

Introduced in 2.0.0

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.

Examples
spark (range 1, 5)    #=> ▁▃▅█
spark (range 1, 5).shuffle #=> ▃█▅▁

Introduced in 2.5.0

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.

Examples
puts (spark_graph (range 1, 5))    #=> ▁▃▅█
puts (spark_graph (range 1, 5).shuffle) #=> ▃█▅▁

Introduced in 2.5.0

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

rotate rotate to the next strong beat allowing for easy permutations of the original rhythmic grouping (see example)
Options for spread
Examples
(spread 3, 8)    #=> (ring true, false, false, true, false, false, true, false) a spacing of 332
(spread 3, 8, rotate: 1) #=> (ring true, false, false, true, false, true, false, false) a spacing of 323

  # Easily create interesting polyrhythmic beats
  live_loop :euclid_beat do
    sample :elec_bong, amp: 1.5 if (spread 3, 8).tick # Spread 3 bongs over 8
    sample :perc_snap, amp: 0.8 if (spread 7, 11).look # Spread 7 snaps over 11
    sample :bd_haus, amp: 2 if (spread 1, 4).look # Spread 1 bd over 4
    sleep 0.125
  end
  

  # Spread descriptions from
  # 'The Euclidean Algorithm Generates Traditional Musical Rhythms' (Toussaint 2005).
  (spread 2, 5)  # A thirteenth century Persian rhythm called Khafif-e-ramal.

  (spread 3, 4)  # The archetypal pattern of the Cumbria from Columbia, as well
                 # as a Calypso rhythm from Trinidad

  (spread 3, 5)  # 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.

  (spread 3, 7)  # A ruchenitza rhythm used in a Bulgarian folk-dance.

  (spread 3, 8)  # The Cuban tresillo pattern

  (spread 4, 7)  # Another Ruchenitza Bulgarian folk-dance rhythm

  (spread 4, 9)  # The Aksak rhythm of Turkey.

  (spread 4, 11) # The metric pattern used by Frank Zappa in his piece Outside Now

  (spread 5, 6)  # Yields the York-Samai pattern, a popular Arab rhythm, when
                 # started on the second onset.

  (spread 5, 7)  # The Nawakhat pattern, another popular Arab rhythm.

  (spread 5, 8)  # The Cuban cinquillo pattern.

  (spread 5, 9)  # A popular Arab rhythm called Agsag-Samai.

  (spread 5, 11) # The metric pattern used by Moussorgsky in Pictures at an
                 # Exhibition

  (spread 5, 12) # The Venda clapping pattern of a South African children's
                 # song.

  (spread 5, 16) # The Bossa-Nova rhythm necklace of Brazil.

  (spread 7, 8)  # A typical rhythm played on the Bendir (frame drum)

  (spread 7, 12) # A common West African bell pattern.

  (spread 7, 16) # A Samba rhythm necklace from Brazil.

  (spread 9, 16) # A rhythm necklace used in the Central African Republic.

  (spread 11, 24) # A rhythm necklace of the Aka Pygmies of Central Africa.

  (spread 13, 24) # Another rhythm necklace of the Aka Pygmies of the upper
                  # Sangha.
  

Introduced in 2.4.0

Get server status

status

This returns a Hash of information about the synthesis environment. Mostly used for debugging purposes.

Examples

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

Introduced in 2.0.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.

Examples

  sample :loop_amen #=> this sample is played until completion
  sleep 0.5
  stop                #=> signal to stop executing this run
  sample :loop_garzul #=> this never executes
  

  in_thread do
    play 60      #=> this note plays
    stop
    sleep 0.5    #=> this sleep never happens
    play 72      #=> this play never happens
  end

  play 80  #=> this plays as the stop only affected the above thread

  # Stopping live loops
  live_loop :foo
    sample :bd_haus
    sleep 1
    stop               # live loop :foo will now stop and no longer loop
  end

  live_loop :bar       # live loop :bar will continue looping
    sample :elec_blip
    sleep 0.25
  end

Introduced in 2.5.0

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)

Examples
(stretch [1,2], 3)    #=> (ring 1, 1, 1, 2, 2, 2)
(stretch [:e2, :c3], 1, [:c2, :d3], 2) #=> (ring :e2, :c3, :c2, :c2, :d3, :d3)

Introduced in 2.6.0

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.

bpm_sync Inherit the BPM of the cueing thread. Default is false
Options for sync
Examples

  in_thread do
    sync :foo # this parks the current thread waiting for a foo sync message to be received.
    sample :ambi_lunar_land
  end

  sleep 5

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

  in_thread do   # Start a metronome thread
    loop do      # Loop forever:
      cue :tick # sending tick heartbeat messages
      sleep 0.5  # and sleeping for 0.5 beats between ticks
    end
  end

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

  sync :foo, :bar # Wait for either a :foo or :bar cue 

  in_thread do   # Start a metronome thread
    loop do      # Loop forever:
      cue [:foo, :bar, :baz].choose # sending one of three tick heartbeat messages randomly
      sleep 0.5  # and sleeping for 0.5 beats between ticks
    end
  end

  # We can now play sounds using the metronome:

  in_thread do
    loop do                    # In the main thread, just loop
      sync :foo               # waiting for :foo sync messages
      sample :elec_beep  # after which play the elec beep sample
    end
  end

  in_thread do
    loop do                    # In the main thread, just loop
      sync :bar               # waiting for :bar sync messages
      sample :elec_flip  # after which play the elec flip sample
    end
  end

  in_thread do
    loop do                    # In the main thread, just loop
      sync :baz               # waiting for :baz sync messages
      sample :elec_blup  # after which play the elec blup sample
    end
  end

Introduced in 2.0.0

Sync and inherit BPM from other threads

sync_bpm cue_id (symbol)

An alias for sync with the bpm_sync: opt set to true.

Options for sync_bpm
Examples
See examples for sync

Introduced in 2.10.0

Trigger specific synth

synth synth_name (symbol)

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

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.
Options for synth
Examples

use_synth :beep            # Set current synth to :beep
play 60                    # Play note 60 with opt defaults

synth :dsaw, note: 60    # Bypass current synth and play :dsaw
                         # with note 60 and opt defaults 

synth :fm, note: 60, amp: 0.5 # Play note 60 of the :fm synth with an amplitude of 0.5

use_synth_defaults release: 5
synth :dsaw, note: 50 # Play note 50 of the :dsaw synth with a release of 5
# You can play chords with the notes: opt:
synth :dsaw, notes: (chord :e3, :minor)

# on: vs if
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  # Here, we're calling notes.tick
                                                          # every time we attempt to play the synth
                                                          # so the notes rise faster than rhyth2
    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  # Here, we're calling notes.tick
                                                        # only when the spread says to play
                                                        # so the notes rise slower than rhyth
    sleep 0.125
  end
end
 # controlling a synth synchronously
s = synth :beep, note: :e3, release: 4
sleep 1
control s, note: :e5
sleep 0.5
synth :dsaw, note: :e3   # This is triggered after 1.5s from start
 # Controlling a synth asynchronously
synth :beep, note: :e3, release: 4 do |s|
  sleep 1                                               # This block is run in an implicit in_thread
  control s, note: :e5                                  # and therefore is asynchronous
end

sleep 0.5
synth :dsaw, note: :e3 # This is triggered after 0.5s from start

Introduced in 2.0.0

Get all synth names

synth_names

Return a list of all the synths available

Examples

Introduced in 2.9.0

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.

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.
Options for tick
Examples

  puts tick #=> 0
  puts tick #=> 1
  puts tick #=> 2
  puts tick #=> 3
  

  puts tick(:foo) #=> 0 # named ticks have their own counts
  puts tick(:foo) #=> 1
  puts tick(:foo) #=> 2
  puts tick(:bar) #=> 0 # tick :bar is independent of tick :foo
  

  # You can tick by more than increments of 1
  # using the step: opt

  puts tick             #=> 0
  puts tick             #=> 1
  puts tick             #=> 2
  puts tick(step: 2)    #=> 4
  puts tick(step: 2)    #=> 6
  puts tick(step: 10)   #=> 16
  puts tick             #=> 17
  
 # Each_live loop has its own separate ticks
  live_loop :fast_tick do
    puts tick   # the fast_tick live_loop's tick will
    sleep 2     # be updated every 2 seconds
  end

  live_loop :slow_tick do
    puts tick   # the slow_tick live_loop's tick is
    sleep 4     # totally independent from the fast_tick
                # live loop and will be updated every 4
                # seconds
  end
  

  live_loop :regular_tick do
    puts tick   # the regular_tick live_loop's tick will
    sleep 1     # be updated every second
  end

  live_loop :random_reset_tick do
    if one_in 3 # randomly reset tick
      tick_reset
      puts "reset tick!"
    end
    puts tick   # this live_loop's tick is totally
    sleep 1     # independent and the reset only affects
                # this tick.
  end
  

  # Ticks work directly on lists, and will tick through each element
  # However, once they get to the end, they'll return nil
  live_loop :scale do
    play [:c, :d, :e, :f, :g].tick   # play all notes just once, then rests
    sleep 1
  end
  

  # Normal ticks interact directly with list ticks
  live_loop :odd_scale do
    tick  # Increment the default tick
    play [:c, :d, :e, :f, :g, :a].tick   # this now play every *other* note just once,
                                         # then rests
    sleep 1
  end
  

  # Ticks work wonderfully with rings
  # as the ring ensures the tick wraps
  # round internally always returning a
  # value
  live_loop :looped_scale do
    play (ring :c, :d, :e, :f, :g).tick   # play all notes just once, then repeats
    sleep 1
  end
  

  # Ticks work wonderfully with scales
  # which are also rings
  live_loop :looped_scale do
    play (scale :e3, :minor_pentatonic).tick   # play all notes just once, then repeats
    sleep 0.25
  end
  

Introduced in 2.6.0

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)

Examples

           # increment default tick a few times
  tick
  tick
  tick
  puts look #=> 2 (default tick is now 2)
  tick_set 0 # default tick is now 0
  puts look #=> 0 (default tick is now 0
  

                  # increment tick :foo a few times
  tick :foo
  tick :foo
  tick :foo
  puts look(:foo) #=> 2 (tick :foo is now 2)
  tick_set 0 # default tick is now 0
  puts look(:foo) #=> 2 (tick :foo is still 2)
  tick_set :foo, 0 #  reset tick :foo
  puts look(:foo) #=> 0 (tick :foo is now 0)

Introduced in 2.6.0

Reset all ticks

tick_reset_all

Reset all ticks - default and keyed

Examples

  tick      # increment default tick and tick :foo
  tick
  tick :foo
  tick :foo
  tick :foo
  puts look #=> 1
  puts look(:foo) #=> 2
  tick_reset_all
  puts look #=> 0
  puts look(:foo) #=> 0
  

Introduced in 2.6.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.

Examples

  tick_set 40 # set default tick to 40
  puts look   #=> 40

  tick_set :foo, 40 # set tick :foo to 40
  puts look(:foo)   #=> 40 (tick :foo is now 40)
  puts look         #=> 0 (default tick is unaffected)

  

Introduced in 2.6.0

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.

Examples
# shift forwards in time
play 70            #=> plays at time 0
sleep 1
play 75            #=> plays at time 1

time_warp 0.1 do
                   # time shifts forward by 0.1 beats
  play 80          #=> plays at 1.1
  sleep 0.5
  play 80          #=> plays at 1.6

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

play 70            #=> plays at 1
# shift backwards in time

play 70            #=> plays at time 0
sleep 1
play 75            #=> plays at time 1

time_warp -0.1 do
                   # time shifts backwards by 0.1 beats
  play 80          #=> plays at 0.9
  sleep 0.5
  play 80          #=> plays at 1.4
                   # time shifts forward by 0.1 beats
end
                   # we now honour the original sleep 1 and the
                   # sleep 0.5 within the time_warp block is
                   # ignored, including the -0.1 offset
play 70            #=> plays at 1
# Ticks count linearly through time_warp

puts tick          #=> prints 0 (at time 0)

sleep 1

time_warp 2 do
  puts tick        #=> prints 1 (at time 3)
end

sleep 0.5

puts tick          #=> prints 2 (at time 1.5)
# Comparing time_warp with at

puts tick          #=> prints 0 (at time 0)
sleep 0.5
puts tick          #=> prints 1 (at time 0.5)

time_warp 2 do
  puts tick        #=> prints 2 (at time 2.5)
  sleep 0.5
  puts tick        #=> prints 3 (at time 3)
end

at 3 do            # the at will reset all thread locals
  puts tick        #=> prints 0 (At time 3.5)
  sleep 0.5
  puts tick        #=> prints 1 (At time 4)
end

sleep 0.5

puts tick          #=> prints 4 (at time 1)
# Time Warp within Density
density 2 do                        # Typically this will double the BPM and affect all times
                                    # in addition to looping the internal block twice
  time_warp 0.5 do                  # However, this time is *not* affected and will remain 0.5
    with_fx :slicer, phase: 0.5 do  # This phase duration *is* affected and will be 0.25
      play 60
      sleep 1                       # This time *will* be affected by the density and be 0.5
    end
  end

end
 # Time Warp with lists of times

time_warp [0, 1, 2, 3] do
  puts "hello"                # Will print "hello" at 0, 1, 2, and 3 seconds
end
                                # 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. 
time_warp [1, 2, 4] do  # plays a note after waiting 1 beat,
    play 75                # then after 1 more beat,
  end                      # then after 2 more beats (4 beats total)
  

  time_warp [1, 2, 3], [75, 76, 77] do |n|  # plays 3 different notes
    play n
  end
  

  time_warp [1, 2, 3],
      [{:amp=>0.5}, {:amp=> 0.8}] do |p| # alternate soft and loud
    sample :drum_cymbal_open, p          # cymbal hits three times
  end
  

  time_warp [0, 1, 2] do |t| # when no params are given to at, the times are fed through to the block
    puts t #=> prints 0, 1, then 2
  end
  

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

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

  time_warp [0, 0.5, 2], [:a, :b] do |t, b, idx|  # If you specify the block with 3 args, it will pass through the time, the param and the index
    puts [t, b, idx] #=> prints out [0, :a, 0], [0.5, :b, 1], then [2, :a, 2]
  end
  
 # time_warp consumes & interferes with the outer random stream
puts "main: ", rand  # 0.75006103515625
rand_back
time_warp 1 do         # the random stream inside the at block is the
                       # same as the one in the outer block
  puts "time_warp:", rand # 0.75006103515625
  puts "time_warp:", rand # 0.733917236328125
  rand_back           # undo last call to rand
end

sleep 2
puts "main: ", rand # value is now 0.733917236328125 again

            # 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:
time_warp [0, 2] do
            # first time round (after 1 beat) prints:
  puts tick # 0
  puts tick # 1
end
            # second time round (after 2 beats) prints:
            # 2
            # 3

Introduced in 2.11.0

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.

Examples

  uncomment do # starting a block level comment:
    play 50 # played
    sleep 1 # sleep happens
    play 62 # played
  end

Introduced in 2.0.0

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.

Examples

use_bpm 120
play 50, release: 2 # release is actually 1 due to bpm scaling
sleep 2             # actually sleeps for 1 second
use_arg_bpm_scaling false
play 50, release: 2 # release is now 2
sleep 2             # still sleeps for 1 second
                       # Interaction with rt
use_bpm 120
play 50, release: rt(2) # release is 2 seconds
sleep rt(2)             # sleeps for 2 seconds
use_arg_bpm_scaling false
play 50, release: rt(2) # ** Warning: release is NOT 2 seconds! **
sleep rt(2)             # still sleeps for 2 seconds

Introduced in 2.0.0

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 withargchecks for enabling/disabling argument checking only for a specific do/end block.

Examples

play 50, release: 5 # Args are checked
use_arg_checks false
play 50, release: 5 # Args are not checked

Introduced in 2.0.0

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:

Examples

  # default tempo is 60 bpm
  4.times do
    play 50, attack: 0.5, release: 0.25 # attack is 0.5s and release is 0.25s
    sleep 1 # sleep for 1 second
  end

  sleep 2  # sleep for 2 seconds

  # Let's make it go faster...
  use_bpm 120  # double the bpm
  4.times do
    play 62, attack: 0.5, release: 0.25 # attack is scaled to 0.25s and release is now 0.125s
    sleep 1 # actually sleeps for 0.5 seconds
  end

  sleep 2 # sleep for 1 second

  # Let's make it go even faster...
  use_bpm 240  #  bpm is 4x original speed!
  8.times do
    play 62, attack: 0.5, release: 0.25 # attack is scaled to 0.125s and release is now 0.0625s
    sleep 1 # actually sleeps for 0.25 seconds
  end

  

Introduced in 2.0.0

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

Examples

  use_bpm 60   # Set the BPM to 60
  play 50
  sleep 1      # Sleeps for 1 seconds
  play 62
  sleep 2      # Sleeps for 2 seconds
  use_bpm_mul 0.5 # BPM is now (60 * 0.5) == 30
  play 50
  sleep 1           # Sleeps for 2 seconds
  play 62
  

Introduced in 2.3.0

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.

Examples

play 50 # Plays note 50
use_cent_tuning 1
play 50 # Plays note 50.01

Introduced in 2.9.0

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

Examples
use_cue_logging true # Turn on cue messages
use_cue_logging false # Disable cue messages

Introduced in 2.6.0

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.

Examples
use_debug true # Turn on debug messages
use_debug false # Disable debug messages

Introduced in 2.0.0

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

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).
Options for use_merged_midi_defaults
Examples

midi_note_on :e1 # Sends MIDI :e1 note_on with default opts

use_midi_defaults channel: 3, port: "foo"

midi_note_on :e3 # Sends MIDI :e3 note_on to channel 3 on port "foo"

use_merged_midi_defaults channel: 1

midi_note_on :e2 # 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.

Introduced in 3.0.0

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.

Options for use_merged_sample_defaults
Examples

sample :loop_amen # plays amen break with default arguments

use_merged_sample_defaults amp: 0.5, cutoff: 70

sample :loop_amen # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

use_merged_sample_defaults cutoff: 90

sample :loop_amen  # plays amen break with a cutoff of 90 and and an amp of 0.5 with defaults for rest of args

Introduced in 2.9.0

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.

Options for use_merged_synth_defaults
Examples

play 50 #=> Plays note 50

use_merged_synth_defaults amp: 0.5
play 50 #=> Plays note 50 with amp 0.5

use_merged_synth_defaults cutoff: 80
play 50 #=> Plays note 50 with amp 0.5 and cutoff 80

use_merged_synth_defaults amp: 0.7
play 50 #=> Plays note 50 with amp 0.7 and cutoff 80
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

Introduced in 2.0.0

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.

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).
Options for use_midi_defaults
Examples

midi_note_on :e1 # Sends MIDI :e1 note_on with default opts

use_midi_defaults channel: 3, port: "foo"

midi_note_on :e3 # Sends MIDI :e3 note_on to channel 3 on port "foo"

use_midi_defaults channel: 1

midi_note_on :e2 # Sends MIDI :e2 note_on to channel 1. Note that the port is back to the default and no longer "foo".

Introduced in 3.0.0

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

Examples
use_midi_logging true # Turn on MIDI logging
use_midi_logging false # Disable MIDI logging

Introduced in 3.0.0

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.

Examples

play 50 # Plays note 50
use_octave 1
play 50 # Plays note 62

# You may change the transposition multiple times:
play 62 # Plays note 62
use_octave -1
play 62 # Plays note 50
use_octave 2
play 62 # Plays note 86

Introduced in 2.9.0

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.

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

use_osc "localhost", 7000  # Specify port 7000 on this machine
osc "/foo/bar"             # Send an OSC message with path "/foo/bar"
                             # and no arguments
 # Send an OSC message with arguments to another program on the same machine

use_osc "localhost", 7000        # Specify port 7000 on this machine
osc "/foo/bar" 1, 3.89, "baz"  # 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"
 # Send an OSC message with arguments to another program on a different machine

use_osc "10.0.1.5", 7000         # Specify port 7000 on the machine with address 10.0.1.5
osc "/foo/bar" 1, 3.89, "baz"  # 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"
 # use_osc only affects calls to osc until the next call to use_osc

use_osc "localhost", 7000  # Specify port 7000 on this machine
osc "/foo/bar"             # Send an OSC message to port 7000
osc "/foo/baz"             # Send another OSC message to port 7000

use_osc "localhost", 7005  # Specify port 7005 on this machine
osc "/foo/bar"             # Send an OSC message to port 7005
osc "/foo/baz"             # Send another OSC message to port 7005
 # threads may have their own use_osc value

use_osc "localhost", 7000  # Specify port 7000 on this machine

live_loop :foo do
  osc "/foo/bar"             # Thread inherits outside use_osc values
  sleep 1                      # and therefore sends OSC messages to port 7000
end

live_loop :bar do
  use_osc "localhost", 7005  # Override OSC hostname and port for just this
                               # thread (live loop :bar). Live loop :foo is
                               # unaffected.

  osc "/foo/bar"             # Send OSC messages to port 7005
  sleep 1
end

use_osc "localhost", 7010  # Specify port 7010
osc "/foo/baz"             # 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.

Introduced in 3.0.0

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

Examples
use_osc_logging true # Turn on OSC logging
use_osc_logging false # Disable OSC logging

Introduced in 3.0.0

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.

Examples

  ## Basic usage

  use_random_seed 1 # reset random seed to 1
  puts rand # => 0.733917236328125
  use_random_seed 1 # reset random seed back to 1
  puts rand  #=> 0.733917236328125
  

  ## Generating melodies
  notes = (scale :eb3, :minor_pentatonic)  # Create a set of notes to choose from.
                                           # Scales work well for this

  with_fx :reverb do
    live_loop :repeating_melody do         # Create a live loop

      use_random_seed 300                  # 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

      8.times do                           # Now iterate a number of times. The size of
                                           # the iteration will be the length of the
                                           # repeating melody.

        play notes.choose, release: 0.1    # '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...
        sleep 0.125
      end
    end
  end
  

Introduced in 2.0.0

Change how random numbers are chosen

use_random_source noise_type (symbol)

: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:

    rand_type :white
    puts 10000.times.collect { rand.round(1) }.tally.sort
    rand_type :pink
    puts 10000.times.collect { rand.round(1) }.tally.sort
    rand_type :perlin
    puts 10000.times.collect { rand.round(1) }.tally.sort
Examples

  use_random_source :white # use white noise as the distribution (default)
  rand_reset # reset random seed
  puts rand # => 0.75006103515625
  puts rand # => 0.733917236328125
  puts rand # => 0.464202880859375
  rand_reset # reset it again
  use_random_source :pink # use pink noise as the distribution
  puts rand # => 0.47808837890625
  puts rand # => 0.56011962890625
  rand_reset # reset it
  use_random_source :perlin # use perlin noise as the distribution
  puts rand # => 0.546478271484375
  puts rand # => 0.573150634765625

  with_random_source :white do # use white noise just for this block
    puts rand # => 0.464202880859375
  end

  puts rand # => 0.597015380859375
            # notice how the last generator (perlin) is restored

Introduced in 3.3.0

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.

Examples
use_real_time # Code will now produce sound without a scheduling delay.

Introduced in 3.0.0

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.

num_beats The number of beats within the sample. By default this is 1.
Options for use_sample_bpm
Examples
use_sample_bpm :loop_amen  #Set bpm based on :loop_amen duration

live_loop :dnb do
  sample :bass_dnb_f
  sample :loop_amen
  sleep 1                  #`sleep`ing for 1 actually sleeps for duration of :loop_amen
end

use_sample_bpm :loop_amen, num_beats: 4  # Set bpm based on :loop_amen duration
                                         # but also specify that the sample duration
                                         # is actually 4 beats long.

live_loop :dnb do
  sample :bass_dnb_f
  sample :loop_amen
  sleep 4                  #`sleep`ing for 4 actually sleeps for duration of :loop_amen
                           # as we specified that the sample consisted of
                           # 4 beats
end

Introduced in 2.1.0

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.

Options for use_sample_defaults
Examples

sample :loop_amen # plays amen break with default arguments

use_sample_defaults amp: 0.5, cutoff: 70

sample :loop_amen # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

use_sample_defaults cutoff: 90

sample :loop_amen  # plays amen break with a cutoff of 90 and defaults for rest of args - note that amp is no longer 0.5

Introduced in 2.5.0

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.

Examples
use_sched_ahead_time 1 # Code will now run approximately 1 second ahead of audio.
# Each thread can have its own sched ahead time
live_loop :foo do
  use_sched_ahead_time 1
  play 70                 # Note 70 will be played with 1 second latency
  sleep 1
end

live_loop :foo do
  use_sched_ahead_time 0.5 # Note 70 will be played with 0.5 second latency
  play 82
  sleep 1
end

Introduced in 3.0.0

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.

Examples

play 50 # Plays with default synth
use_synth :mod_sine
play 50 # Plays with mod_sine synth

Introduced in 2.0.0

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.

Options for use_synth_defaults
Examples

play 50 # plays note 50 with default arguments

use_synth_defaults amp: 0.5, cutoff: 70

play 50 # plays note 50 with an amp of 0.5, cutoff of 70 and defaults for rest of args

use_synth_defaults cutoff: 90

play 50 # plays note 50 with a cutoff of 90 and defaults for rest of args - note that amp is no longer 0.5

Introduced in 2.0.0

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.

Examples

use_timing_guarantees true

sample :loop_amen  #=> if time is behind by any margin, this will not trigger

use_timing_guarantees false

sample :loop_amen  #=> unless time is too far behind, this will trigger even when late.

Introduced in 2.10.0

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.

Examples

play 50 # Plays note 50
use_transpose 1
play 50 # Plays note 51

# You may change the transposition multiple times:
play 62 # Plays note 62
use_transpose -12
play 62 # Plays note 50
use_transpose 3
play 62 # Plays note 65

Introduced in 2.0.0

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

Examples

play :e4 # Plays note 64
use_tuning :just, :c
play :e4 # Plays note 63.8631
# transparently changes midi notes too
play 64 # Plays note 63.8631

# You may change the tuning multiple times:
play 64 # Plays note 64
use_tuning :just
play 64 # Plays note 63.8631
use_tuning :equal
play 64 # Plays note 64

Introduced in 2.6.0

Create a vector

vector list (array)

Create a new immutable vector from args. Out of range indexes return nil.

Examples
(vector 1, 2, 3)[0] #=> 1
(vector 1, 2, 3)[1] #=> 2
(vector 1, 2, 3)[2] #=> 3
(vector 1, 2, 3)[3] #=> nil
(vector 1, 2, 3)[1000] #=> nil
(vector 1, 2, 3)[-1] #=> nil
(vector 1, 2, 3)[-1000] #=> nil

Introduced in 2.6.0

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

Examples

  puts version # => Prints out the current version such as v2.0.1

  puts version.major # => Prints out the major version number such as 2

  puts version.minor # => Prints out the minor version number such as 0

  puts version.patch # => Prints out the patch level for this version such as 0

Introduced in 2.0.0

Get virtual time

vt

Get the virtual time of the current thread.

Examples

  puts vt # prints 0
   sleep 1
   puts vt # prints 1

Introduced in 2.1.0

Wait for duration

wait beats (number)

Synonym for sleep - see sleep

Examples

Introduced in 2.0.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.

Examples
use_bpm 120
play 50, release: 2   # release is actually 1 due to bpm scaling
sleep 2               # actually sleeps for 1 second
with_arg_bpm_scaling false do
  play 50, release: 2 # release is now 2
  sleep 2             # still sleeps for 1 second
end
                         # Interaction with rt
use_bpm 120
play 50, release: rt(2)   # release is 2 seconds
sleep rt(2)               # sleeps for 2 seconds
with_arg_bpm_scaling false do
  play 50, release: rt(2) # ** Warning: release is NOT 2 seconds! **
  sleep rt(2)             # still sleeps for 2 seconds
end

Introduced in 2.0.0

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.

Examples

# Turn on arg checking:
use_arg_checks true

play 80, cutoff: 100 # Args are checked

with_arg_checks false do
  #Arg checking is now disabled
  play 50, release: 3 # Args are not checked
  sleep 1
  play 72             # Arg is not checked
end

# Arg checking is re-enabled
play 90 # Args are checked

Introduced in 2.0.0

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:

Examples

  # default tempo is 60 bpm
  4.times do
    sample :drum_bass_hard
    sleep 1 # sleeps for 1 second
  end

  sleep 5 # sleeps for 5 seconds

  # with_bpm sets a tempo for everything between do ... end (a block)
  # Hear how it gets faster?
  with_bpm 120 do  # set bpm to be twice as fast
    4.times do
      sample :drum_bass_hard
      sleep 1 # now sleeps for 0.5 seconds
    end
  end

  sleep 5

  # bpm goes back to normal
  4.times do
    sample :drum_bass_hard
    sleep 1 # sleeps for 1 second
  end

Introduced in 2.0.0

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

Examples

  use_bpm 60   # Set the BPM to 60
  play 50
  sleep 1      # Sleeps for 1 second
  play 62
  sleep 2      # Sleeps for 2 seconds
  with_bpm_mul 0.5 do # BPM is now (60 * 0.5) == 30
    play 50
    sleep 1           # Sleeps for 2 seconds
    play 62
  end
  sleep 1            # BPM is now back to 60, therefore sleep is 1 second
  

Introduced in 2.3.0

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.

Examples

use_cent_tuning 1
play 50 # Plays note 50.01

with_cent_tuning 2 do
  play 50 # Plays note 50.02
end

# Original cent tuning value is restored
play 50 # Plays note 50.01

Introduced in 2.9.0

Block-level enable and disable cue logging

with_cue_logging true_or_false (boolean)

Similar to usecuelogging except only applies to code within supplied do/end block. Previous cue log value is restored after block.

Examples

  # Turn on debugging:
  use_cue_logging true

  cue :foo # cue message is printed to log

  with_cue_logging false do
    #Cue logging is now disabled
    cue :bar # cue *is* sent but not displayed in log
  end
  sleep 1
  # Debug is re-enabled
  cue :quux # cue is displayed in log
  

Introduced in 2.6.0

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.

Examples

# Turn on debugging:
use_debug true

play 80 # Debug message is sent

with_debug false do
  #Debug is now disabled
  play 50 # Debug message is not sent
  sleep 1
  play 72 # Debug message is not sent
end

# Debug is re-enabled
play 90 # Debug message is sent

Introduced in 2.0.0

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

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.
Options for with_fx
Examples

# Basic usage
with_fx :distortion do # Use the distortion effect with default parameters
  play 50 # => plays note 50 with distortion
  sleep 1
  sample :loop_amen # => plays the loop_amen sample with distortion too
end
# Specify effect parameters
with_fx :level, amp: 0.3 do # Use the level effect with the amp parameter set to 0.3
  play 50
  sleep 1
  sample :loop_amen
end

# Controlling the effect parameters within the block
with_fx :reverb, mix: 0.1 do |fx|
  # 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

  play 60 # plays note 60 with a little bit of reverb
  sleep 2

  control fx, mix: 0.5 # change the parameters of the effect to add more reverb
  play 60 # again note 60 but with more reverb
  sleep 2

  control fx, mix: 1 # change the parameters of the effect to add more reverb
  play 60 # plays note 60 with loads of reverb
  sleep 2
end

# Repeat the block 16 times internally
with_fx :reverb, reps: 16 do
  play (scale :e3, :minor_pentatonic), release: 0.1
  sleep 0.125
end

# The above is a shorthand for this:
with_fx :reverb do
  16.times do
    play (scale :e3, :minor_pentatonic), release: 0.1
    sleep 0.125
  end
end

Introduced in 2.0.0

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.

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).
Options for with_merged_midi_defaults
Examples

midi_note_on :e1 # Sends MIDI :e1 note_on with default opts

use_midi_defaults channel: 3, port: "foo"

midi_note_on :e3 # Sends MIDI :e3 note_on to channel 3 on port "foo"

with_merged_midi_defaults channel: 1 do

  midi_note_on :e2 # 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.
end

midi_note_on :e2 # 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.

Introduced in 3.0.0

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.

Options for with_merged_sample_defaults
Examples

sample :loop_amen # plays amen break with default arguments

use_merged_sample_defaults amp: 0.5, cutoff: 70

sample :loop_amen # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

with_merged_sample_defaults cutoff: 90 do
  sample :loop_amen  # plays amen break with a cutoff of 90 and amp of 0.5
end

sample :loop_amen  # plays amen break with a cutoff of 70 and amp is 0.5 again as the previous defaults are restored.

Introduced in 2.9.0

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.

Options for with_merged_synth_defaults
Examples

with_merged_synth_defaults amp: 0.5, pan: 1 do
  play 50 # => plays note 50 with amp 0.5 and pan 1
end
play 50 #=> plays note 50
with_merged_synth_defaults amp: 0.5 do
  play 50 #=> plays note 50 with amp 0.5

  with_merged_synth_defaults pan: -1 do
    with_merged_synth_defaults amp: 0.7 do
      play 50 #=> plays note 50 with amp 0.7 and pan -1
    end
  end
  play 50 #=> plays note 50 with amp 0.5
end

Introduced in 2.0.0

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.

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).
Options for with_midi_defaults
Examples

midi_note_on :e1 # Sends MIDI :e1 note on with default opts

with_midi_defaults channel: 3, port: "foo" do
  midi_note_on :e3 # Sends MIDI :e3 note on to channel 3 on port "foo"
end

use_midi_defaults channel: 1   # this will be overridden by the following

with_midi_defaults channel: 5 do
  midi_note_on :e2 # Sends MIDI :e2 note on to channel 5.
                   # Note that the port is back to the default
end

  midi_note_on :e4 # Sends MIDI :e4 note on to channel 1
                   # Note that the call to use_midi_defaults is now honoured.

Introduced in 3.0.0

Block-level enable and disable MIDI logging

with_midi_logging true_or_false (boolean)

Similar to usemidilogging except only applies to code within supplied do/end block. Previous MIDI log value is restored after block.

Examples

  # Turn on MIDI logging:
  use_midi_logging true

  midi :e1 #  message is printed to log

  with_midi_logging false do
    #MIDI logging is now disabled
    midi :f2 # MIDI message *is* sent but not displayed in log
  end
  sleep 1
  # Debug is re-enabled
  midi :G3 # message is displayed in log
  

Introduced in 3.0.0

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.

Examples

play 50 # Plays note 50
sleep 1
with_octave 1 do
 play 50 # Plays note 62
end
sleep 1
play 50 # Plays note 50

Introduced in 2.9.0

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.

Examples

use_osc "localhost", 7000  # Specify port 7000
osc "/foo/baz"             # Send an OSC message to port 7000

with_osc "localhost", 7010 do # set hostname and port for the duration
                                # of this do/end block
   osc "/foo/baz"             # Send an OSC message to port 7010
end

osc "/foo/baz"             # Send an OSC message to port 7000
                             # as old setting is restored outside
                             # do/end block

Introduced in 3.0.0

Block-level enable and disable OSC logging

with_osc_logging true_or_false (boolean)

Similar to useosclogging except only applies to code within supplied do/end block. Previous OSC log value is restored after block.

Examples

  # Turn on OSC logging:
  use_osc_logging true

  osc "/foo" #  message is printed to log

  with_osc_logging false do
    #OSC logging is now disabled
    osc "/foo" # OSC message *is* sent but not displayed in log
  end
  sleep 1
  # Debug is re-enabled
  osc "/foo" # message is displayed in log
  

Introduced in 3.0.0

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.

Examples

  use_random_seed 1 # reset random seed to 1
  puts rand # => 0.733917236328125
  puts rand  #=> 0.464202880859375
  use_random_seed 1 # reset it back to 1
  puts rand # => 0.733917236328125
  with_random_seed 1 do # reset seed back to 1 just for this block
    puts rand # => 0.733917236328125
    puts rand #=> 0.464202880859375
  end
  puts rand # => 0.464202880859375
            # notice how the original generator is restored

  ## Generating melodies
  notes = (scale :eb3, :minor_pentatonic, num_octaves: 2)  # Create a set of notes to choose from.
                                           # Scales work well for this

  with_fx :reverb do
    live_loop :repeating_melody do         # Create a live loop

      with_random_seed 300 do              # 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

        8.times do                         # Now iterate a number of times. The size of
                                           # the iteration will be the length of the
                                           # repeating melody.

          play notes.choose, release: 0.1  # '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...
          sleep 0.125
        end
      end

      play notes.choose, amp: 1.5, release: 0.5 # 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.
    end
  end
  

Introduced in 2.0.0

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.

Examples

  use_random_source :white # use white noise as the distribution (default)
  rand_reset # reset random seed
  puts rand # => 0.75006103515625
  puts rand # => 0.733917236328125
  puts rand # => 0.464202880859375
  rand_reset # reset it again
  use_random_source :pink # use pink noise as the distribution
  puts rand # => 0.47808837890625
  puts rand # => 0.56011962890625
  rand_reset # reset it
  use_random_source :perlin # use perlin noise as the distribution
  puts rand # => 0.546478271484375
  puts rand # => 0.573150634765625

  with_random_source :white do # use white noise just for this block
    puts rand # => 0.464202880859375
  end

  puts rand # => 0.597015380859375
            # notice how the last generator (perlin) is restored

Introduced in 3.3.0

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.

Examples

with_real_time do
  play 70  # Sound will happen without a scheduling delay.
end

play 70  # Sound will happen with the default latency (0.5s).

Introduced in 3.0.0

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.

num_beats The number of beats within the sample. By default this is 1.
Options for with_sample_bpm
Examples

live_loop :dnb do
  with_sample_bpm :loop_amen do #Set bpm based on :loop_amen duration
    sample :bass_dnb_f
    sample :loop_amen
    sleep 1                     #`sleep`ing for 1 sleeps for duration of :loop_amen
  end
end
live_loop :dnb do
  with_sample_bpm :loop_amen, num_beats: 4 do # Set bpm based on :loop_amen duration
                                              # but also specify that the sample duration
                                              # is actually 4 beats long.
    sample :bass_dnb_f
    sample :loop_amen
    sleep 4                     #`sleep`ing for 4 sleeps for duration of :loop_amen
                                # as we specified that the sample consisted of
                                # 4 beats
  end
end

Introduced in 2.1.0

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.

Options for with_sample_defaults
Examples

sample :loop_amen # plays amen break with default arguments

use_sample_defaults amp: 0.5, cutoff: 70

sample :loop_amen # plays amen break with an amp of 0.5, cutoff of 70 and defaults for rest of args

with_sample_defaults cutoff: 90 do
  sample :loop_amen  # plays amen break with a cutoff of 90 and defaults for rest of args - note that amp is no longer 0.5
end

sample :loop_amen  # plays amen break with a cutoff of 70 and amp is 0.5 again as the previous defaults are restored.

Introduced in 2.5.0

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.

Examples

with_sched_ahead_time 1 do
  play 70  # Sound will happen with a latency of 1
end

play 70  # Sound will happen with the default latency (0.5s)

Introduced in 3.0.0

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.

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)
Options for with_swing
Examples

live_loop :foo do
  with_swing 0.1 do
    sample :elec_beep      # plays the :elec_beep sample late except on the 1st beat of every 4
  end
  sleep 0.25
end

live_loop :foo do
  with_swing -0.1 do
    sample :elec_beep      # plays the :elec_beep sample slightly early
  end                      # on the 1st beat of every 4
  sleep 0.25
end

live_loop :foo do
  with_swing -0.1, pulse: 8 do
    sample :elec_beep      # plays the :elec_beep sample slightly early
  end                      #  on the 1st beat of every 8
  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.
live_loop :foo do
  with_swing 0.14, tick: :a do
    sample :elec_beep      # plays the :elec_beep sample slightly late
  end                      #  on the 1st beat of every 4

  with_swing -0.1, tick: :b do
    sample :elec_beep, rate: 2  # plays the :elec_beep sample at double rate
  end                           #  slightly early except  on the 1st beat of every 4
  sleep 0.25
end

live_loop :foo do
  with_swing 0.1 do
    cue :tick              # send out cue messages with swing timing
  end
  sleep 0.25
end

live_loop :bar do
  sync :tick
  sample :elec_beep       # 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)
end

live_loop :foo do
  with_swing 0.1, offset: 2 do
    sample :elec_beep      # plays the :elec_beep sample slightly late
  end                      # on the the 3rd beat of every 4
  sleep 0.25
end

live_loop :foo do
  with_swing 0.1, pulse: 2, offset: 1 do
    sample :elec_beep      # plays the :elec_beep sample slightly late
  end                      # on the 2nd beat of every 2
  sleep 0.25
end

Introduced in 3.0.0

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.

Examples

play 50 # Plays with default synth
sleep 2
use_synth :supersaw
play 50 # Plays with supersaw synth
sleep 2
with_synth :saw_beep do
  play 50 # Plays with saw_beep synth
end
sleep 2
# Previous synth is restored
play 50 # Plays with supersaw synth

Introduced in 2.0.0

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.

Options for with_synth_defaults
Examples

play 50 # plays note 50 with default arguments

use_synth_defaults amp: 0.5, pan: -1

play 50 # plays note 50 with an amp of 0.5, pan of -1 and defaults for rest of args

with_synth_defaults amp: 0.6, cutoff: 80 do
  play 50 # plays note 50 with an amp of 0.6, cutoff of 80 and defaults for rest of args (including pan)
end

play 60 # plays note 60 with an amp of 0.5, pan of -1 and defaults for rest of args

Introduced in 2.0.0

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.

Examples

with_timing_guarantees true do
  sample :loop_amen  #=> if time is behind by any margin, this will not trigger
end

with_timing_guarantees false do
  sample :loop_amen  #=> unless time is too far behind, this will trigger even when late.
end

Introduced in 2.10.0

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.

Examples

use_transpose 3
play 62 # Plays note 65

with_transpose 12 do
  play 50 # Plays note 62
  sleep 1
  play 72 # Plays note 84
end

# Original transpose value is restored
play 80 # Plays note 83

Introduced in 2.0.0

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.

Examples

use_tuning :equal, :c
play :e4 # Plays note 64
with_tuning :just, :c do
  play :e4 # Plays note 63.8631
  sleep 1
  play :c4 # Plays note 60
end
# Original tuning value is restored
play :e4 # Plays note 64

Introduced in 2.6.0