The idea with the drum synth is to get a wide range of sounds out of the smallest, simplest possible circuit. There are 4 drum modes, bass, snare, hat and something more glitchy. I’m using an AtTiny45 as it’s got analogue inputs, fast PWM for output and enough memory for a few lookup tables of data. Here’s the test circuit:
The AtTiny chip is computing each sample at roughly 31kHz so I need to avoid any CPU-hungry operations like multiplication (8Mhz clock/31.25kHz = 256 instructions max). The bass drum gets around this by using two 8 bit lookup tables, each 256 bytes in size. The first is an ‘impact’ table which is a sort of exponential drop off curve and the second is a sine wave scaled to a 0-255 range. Source code is here (Compiled in g++, fuses L = 0xE2, H = 0xDF, E = 0xFF) and here’s the bit that does the important work:
impactPos += speed; sinePos += pgm_read_byte(&impact_tbl[(impactPos >> 8) & 0xff]); sample = pgm_read_byte(&sine_tbl[(sinePos >> 4) & 0xff]);
The sine table is being modulated by the ever-decreasing impact table so the frequency drops over time. The speed of the playback determines the pitch of the drum and the initial impactPos determines the type of sound. For a cheesy 70’s disco tom you set it to zero to go from a really high tone down to a low one. For a tech bass you start further down the curve to get a more muted and constrained sound.
This is a lazy approach as there is no decay on the volume – instead it depends on the drum playing out until the frequency of the sine wave is too low to hear. This avoids any multiplications but has some 8 bit artefacts as a consequence (I kind of like them). Here’s some example output: