So far, almost all my build logs for this project have been about technical challenges, design choices, etc - there has been very little about the most interesting aspect of this drum machine: the way that randomness creates a beat. Now that I'm happy with the basic design and am well into the coding section of the project, this seems like a good time to explain the algorithm (if that's the right word?) behind DrumKid.
DrumKid starts off as a pretty regular drum machine. It begins with a basic 16-step drum pattern, e.g. "kick hat hat hat snare hat hat kick kick hat kick hat snare hat hat hat" (it can play multiple sounds at once, but that's much harder to write in a sentence!). This basic pattern is then modified using random numbers in the following way:
Imagine that for each type of drum (kick, snare, hat, etc), and for each step in the sequence, you roll a dice. If you roll a six, a drum hit is added to the sequence. So, as well as the original pattern, about a sixth of the steps (for each type of drum) that would have been empty now have drum hits. These dice rolls will be different every time, creating an unpredictable beat.
If we want the beat to be more unpredictable, we could lower the threshold of when we add an extra hit - say, when we roll a six or a five. This threshold effectively controls how much randomness we allow into the beat, and is controlled by a knob on the drum machine (obviously with a much bigger range than the one to six of a dice!). Turning the knob to zero will mean that only the original pattern is played, while turning it up to maximum will mean that every drum is triggered on every step. This parameter is called chance.
This is an interesting start, but it sounds much nicer when we also vary the volume/velocity of each drum hit. Let's imagine that every time the first dice has determined that there will be an extra hit, we will also roll a second dice to determine the velocity, with a roll of one creating a very quiet hit, and six creating a very loud hit. This will sound interesting, but a little bit wild - we want a way to tame this randomness.
We can define a minimum and maximum value for these random velocities, so that, for instance, all of the extra hits are between 30% and 50% volume. This allows the original pattern to remain discernible, while adding a sort of sub-groove to the beat. Alternatively, you could put the minimum at 10% and the maximum at 90%, creating a much busier feel. After a bit of experimenting, it turns out that the most intuitive, live-performance-friendly way to control these parameters is not with "min velocity" and "max velocity" knobs, but with one knob to determine the midpoint the random velocities, and one knob to control the range. This means you can create a drum fill simply by turning up the midpoint knob.
Manipulating these three knobs, chance, midpoint, and range, gives a lot of expressive control over a drumbeat, and these will be the main default controls on DrumKid. By pressing different buttons, it will be possible to switch the knobs to other functions, including audio effects like pitch shift, bit-crush, etc, and there may be other more obscure randomness-based parameters (perhaps an inverse of the process described here, which removes hits rather than adding them), but these three controls are the heart and soul of DrumKid, and provide its signature sound.
Coding is going well, so hopefully there will be an audio/video demo soon!