rings - guyjbrown/bleepmanual GitHub Wiki

A ring is a circular array. To understand what that means, try this example:

use_bpm(80)
notes = ring({C4,D4,E4})
for i=1,8 do
    play(notes[i],{level=0.8})
    sleep(0.25)
end

You'll hear 8 notes being played which are C4, D4, E4, C4, D4, E4, C4, D4. So a ring is like an array with indexes that wrap around in a circle. If we step forwards through the array and run off the end, we start again at the beginning. Also, if we step backwards through the array and run off the beginning, we start again at the end! This is a pretty wacky, so maybe a diagram will help:

graph LR;
id1((C4))-->id2((D4));
id2((D4))-->id3((E4));
id3((E4))-->id1((C4));
Loading

Scales are rings

The scale function in Bleep always returns a ring. Try this:

use_bpm(80)
notes = scale("minor_pentatonic",C4,1)
for i=1,24 do
    play(notes[i],{level=0.8})
    sleep(0.25)
end

Ring functions

Rings are powerful features of Bleep because we provide lots of functions that you can use to chop them up, squish them, mix them together, sort them and do all sorts of other amazing stuff. These functions provide some great ways to experiment with melodies and rhythms. The following sections give examples of some commonly used ones:

pick

pick(n) randomly selects n values from the current ring and returns a new ring containing them. This is great for making sequences of notes that conform to a scale:

use_bpm(80)
the_scale = scale("harmonic_minor",D3,2)
play_pattern(the_scale:pick(4),{
    duration=0.25,
    level=0.8})

clone

clone(n) returns a new ring that contains n copies of the current ring. This is very handy for making bass lines and other melodies that consist of a repeating sequence of notes.

use_bpm(80)
use_synth("rolandtb")
three_notes = ring({D2,Fs3,G3})
play_pattern(three_notes:clone(4),{
    duration=0.25, 
    gate=0.8, 
    env_mod=0.7})

shuffle

shuffle() return a new ring that contains a random permutation of the current ring; in other words the values get shuffled like a pack of cards. So maybe you want to play all of the notes in a scale but in a random order:

use_bpm(80)
use_synth("elpiano")
the_scale = scale("major_pentatonic",E4,1)
play_pattern(the_scale:shuffle(),{
    duration=0.25})

reverse

reverse() returns a new ring that is a time-reversed version of the current ring. Let's play a scale backwards over two octaves, from the highest note to the lowest one:

use_bpm(80)
use_synth("elpiano")
the_scale = scale("major_pentatonic",E4,2)
play_pattern(the_scale:reverse(),{
    duration=0.25})

stretch

stretch(n) returns a new ring in which each value in the current one is repeated n times. We can use this to make a fast repeating bass line, for example:

use_bpm(80)
notes = scale("harmonic_minor", D2, 1):pick(3)
play_pattern(notes:stretch(8), {
    duration=0.125, 
    level=0.8,
    gate=0.5})

Notice that we introduced a new trick there. Since scale returns a ring, we don't need to store it in an intermediate variable; we can just apply a ring function such as pick directly. We'll look at this in more detail below.

Full list of ring functions

function what it returns
pick(n) A ring containing n randomly selected values from the ring
shuffle() A copy of the ring in which the values are randomly shuffled
clone(n) A ring consisting of n adjacent copies of the ring
reverse() A time-reverse copy of the ring
stretch(n) A new ring in which each value is repeated n times
length() The length of the ring (an integer value)
head(n) The first n elements of the ring
tail(n) The last n elements of the ring
slice(a,b) The elements of the ring with indexes between a and b inclusive. Note that the first index of a ring is 1 (not 0 as in many other programming languages)
concat(r) Concatenates (joins) the current ring with the ring r
multiply(s) Multiplies each value of the ring by a scalar value s
add(s) Adds the scalar value s to each value in the ring
mirror() Return a time-reversed (mirrored) copy of the current ring
reflect() Similar to mirror, but removes the duplicate middle element
sort() Return a copy of the ring in which its values are in numerically increasing sorted order
alternate(c) Make alternating intervals by duplicating each value of the ring and adding a constant c
merge(r) Merge (intercalate) the current ring with another ring r
quantize(n) Quantise values in the ring to the nearest n
const_ring(n,v) Make a Ring of size n with constant value v
rand_ring(n,min,max) Make a Ring of n random values between min and max
range_ring(n,min,max) Make a range of n values ranging between min and max

Next: Playing note patterns

⚠️ **GitHub.com Fallback** ⚠️