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