Randomness
Randomness is a first step to generating music. With it we can generate whole pieces of music, introduce variation and surprise. Knowing how to harness randomness is an interplay between us and the computer. If we think of all posibilities, randomness gives us a way to "sample" the possibility space / unseen.
Music that relies at least to some degree on randomness is said to be stochastic, or aleatoric.
This guide shows how to use randomness to introduce variation to our music, specifically through the idea of a random walk.
Notes:
- Pure randomness (seeds)
- Range
- Perlin, Gaussian
- Random number generation
- Apply to: pitch, velocity, timing
Random Walk
In 2D graphics, a random walk involves drawing a path by repeatedly choosing a random direction in which to move. On this 2D plane, each step can be one of four directions: up, down, left, or right (plus a fifth choice if you include not moving as an option). Given a certain set of rules, this might look as follows:
How might we apply this idea to music? As we've seen, a piano has 88 keys, giving it a range from A0 to C8, which map to the MIDI numbers 21–108. We can treat this as a 1D plane, and say that at each moment we have 4 choices: 1) play a higher note; 2) play a min note; 3) play the same note; 4) play nothing. The range 21-108 and the 4 choices define the "possibility space" for our random walk.
Random Notes
Let's start simple and just play random notes by repeatedly picking a random number between 21 and 108. This gives us a random distribution, where each of the 88 notes have an equal chance of being played.
Random Numbers
For this example, we'll need a way to generate a random number within a given range, which JS doesn't have out-of-the-box, so let's create one:
Random Stream
Before actually making any sounds, let's just create a regular stream of random numbers within our desired range. We just need to convert our random number function to an Observable:
Random Notes
Now, let's plug in the sampler()
function from Tuplet and hear some notes:
Let's refactor this using the program()
structure from Tuplet:
This probably sounds like the bleeps and bloops you imagine when you hear the phrase "computer generated music". At strict intervals and constant velocity the results sound rather mechanical.
More randomness
By also applying some randomness to the timing and velocity, we can add more nuance.
This makes things feel more natural, emulating the variations of timing and touch of a human player.
Whilst initially quite interesting though, pure randomness doesn't hold our attention for long, as, by definition, it lacks the patterns and structure that are a key aspect of our enjoyment of music.
Relative notes
If we think about taking a walk, even if we're just wandering, we're not taking random steps and leaps. Our movements have direction, each step is related to the previous ones to keep us moving along a certain path.
Rather than choosing randomly, we can pick our next note relative to the current one.
This gives us something that has more of a flow and sense of direction. We've constrained the options from all possible notes, to just those that are 5 notes (a 5th) either up or down from the current note. This gives us some control, but we're still very much at the whim of chaos to determine our path.