1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
4 Randomisation
# Randomisation
A great way to add some interest into your music is using some random
numbers. Sonic Pi has some great functionality for adding randomness to
your music, but before we start we need to learn a shocking truth: in
Sonic Pi *random is not truly random*. What on earth does this mean?
Well, let's see.
## Repeatability
A really useful random function is `rrand` which will give you a random
value between two numbers - a *min* and a *max*. (`rrand` is short for
ranged random). Let's try playing a random note:
```
play rrand(50, 95)
```
Ooh, it played a random note. It played note `83.7527`. A nice random
note between 50 and 95. Woah, wait, did I just predict the exact random
note you got too? Something fishy is going on here. Try running the code
again. What? It chose `83.7527` again? That can't be random!
The answer is that it is not truly random, it's pseudo-random. Sonic Pi
will give you random-like numbers in a repeatable manner. This is very
useful for ensuring that the music you create on your machine sounds
identical on everybody else's machine - even if you use some randomness
in your composition.
Of course, in a given piece of music, if it 'randomly' chose `83.7527`
every time, then it wouldn't be very interesting. However, it
doesn't. Try the following:
```
loop do
play rrand(50, 95)
sleep 0.5
end
```
Yes! It finally sounds random. Within a given *run* subsequent calls
to random functions will return random values. However, the next run
will produce exactly the same sequence of random values and sound
exactly the same. It's as if all Sonic Pi code went back in time to
exactly the same point every time the Run button was pressed. It's the
Groundhog Day of music synthesis!
## Haunted Bells
A lovely illustration of randomisation in action is the haunted bells
example which loops the `:perc_bell` sample with a random rate and sleep
time between bell sounds:
```
loop do
sample :perc_bell, rate: (rrand 0.125, 1.5)
sleep rrand(0.2, 2)
end
```
## Random cutoff
Another fun example of randomisation is to modify the cutoff of a
synth randomly. A great synth to try this out on is the `:tb303`
emulator:
```
use_synth :tb303
loop do
play 50, release: 0.1, cutoff: rrand(60, 120)
sleep 0.125
end
```
## Random seeds
So, what if you don't like this particular sequence of random numbers
Sonic Pi provides? Well it's totally possible to choose a different
starting point via `use_random_seed`. The default seed happens to be
0, so choose a different seed for a different random experience!
Consider the following:
```
5.times do
play rrand(50, 100)
sleep 0.5
end
```
Every time you run this code, you'll hear the same sequence of 5
notes. To get a different sequence simply change the seed:
```
use_random_seed 40
5.times do
play rrand(50, 100)
sleep 0.5
end
```
This will produce a different sequence of 5 notes. By changing the seed
and listening to the results you can find something that you like - and
when you share it with others, they will hear exactly what you heard
too.
Let's have a look at some other useful random functions.
## choose
A very common thing to do is to choose an item randomly from a list of
known items. For example, I may want to play one note from the
following: 60, 65 or 72. I can achieve this with `choose` which lets
me choose an item from a list. First, I need to put my numbers in a list
which is done by wrapping them in square brackets and separating them
with commas: `[60, 65, 72]`. Next I just need to pass them to `choose`:
```
choose([60, 65, 72])
```
Let's hear what that sounds like:
```
loop do
play choose([60, 65, 72])
sleep 1
end
```
## rrand
We've already seen `rrand`, but let's run over it again. It returns a
random number between two values exclusively. That means it will never
return either the top or bottom number - always something in between the
two. The number will always be a float - meaning it's not a whole number
but a fraction of a number. Examples of floats returned by
`rrand(20, 110)`:
* 87.5054931640625
* 86.05255126953125
* 61.77825927734375
## rrand_i
Occasionally you'll want a whole random number, not a float. This is
where `rrand_i` comes to the rescue. It works similarly to `rrand`
except it may return the min and max values as potential random values
(which means it's inclusive rather than exclusive of the
range). Examples of numbers returned by `rrand_i(20, 110)` are:
* 88
* 86
* 62
## rand
This will return a random float between 0 (inclusive) and the max
value you specify (exclusive). By default it will return a value
between 0 and one. It's therefore useful for choosing random `amp:`
values:
```
loop do
play 60, amp: rand
sleep 0.25
end
```
## rand_i
Similar to the relationship between `rrand_i` and `rrand`, `rand_i` will
return a random whole number between 0 and the max value you specify.
## dice
Sometimes you want to emulate a dice throw - this is a special case of
`rrand_i` where the lower value is always 1. A call to `dice` requires
you to specify the number of sides on the dice. A standard dice has 6
sides, so `dice(6)` will act very similarly - returning values of either
1, 2, 3, 4, 5, or 6. However, just like fantasy role-play games, you
might find value in a 4 sided dice, or a 12 sided dice, or a 20 sided
dice - perhaps even a 120 sided dice!
## one_in
Finally you may wish to emulate throwing the top score of a dice such
as a 6 in a standard dice. `one_in` therefore returns true with a
probability of one in the number of sides on the dice. Therefore
`one_in(6)` will return true with a probability of 1 in 6 or false
otherwise. True and false values are very useful for `if` statements
which we will cover in a subsequent section of this tutorial.
Now, go and jumble up your code with some randomness!
|