Drumique Analog Drum Machine


Drumique uses fully analog circuitry to generate it's four sounds: kick, snare, high hat and claps.

These analog circuits receive their triggers from an Arduino, which acts as the brains of the unit. It features a 16-step sequencer and each step for each sound can be set through the front-panel switches.

A video is currently in the making! Coming soon!

Please note that this page is a work-in-progress, as I have a lot of ground to cover on this one. Be patient please :)







The Brains


The thing that is at the center of it all: the Arduino. It reads out the front panel controls, receives MIDI data and converts it all to 4 triggers which are send to the 4 analog circuits to generate dem tasty beats!

At first I wanted to use an interrupt for the timing, but decided that this was overkill really and just stuck with using Micros() to time stuff. This is more than precise enough and well... can always easily change it, that's the advantage of the Arduino :)

Here's two great macros I made for the SQK-1 project to use instead of the DigitalRead and DigitalWrite functions. These will give you up to 40 times more speed!

//DigitalWrite does a lot of error checking (pin correctly set etc) which this obviously doesn't, so make sure your code is correct!
//'x' is the port (for example: PORTB)!
//'y' is the port number, not the pin number!
#define CLR(x,y)(x&=(~(1<<y))) //equalivent to: DigitalWrite(pin, LOW);
#define SET(x,y)(x|=(1<<y))    //equalivent to: DigitalWrite(pin, HIGH);
		

Notes:
I'm planning to replace all the slow Arduino library functions with faster stuff, such as direct (bitwise) port manipulation, but for clarity's sake I've kept the Arduino library functions in the code below. This code hasn't had any optimizations either, again because of clarity.
Don't worry though, it will run just fine (this exact code was running on Drumique in the demo video).

I'm using two CD4022 decade counters to scan the front panel controls. The Arduino generates clock and reset signals to make the CD4022's iterate through all the buttons through diodes (to prevent crosstalk and false signals). In turn all the buttons are connected to two connections which go back to the Arduino.
If a button is pressed this connection will be pulled high when the CD4022 switches on the output it has that button connected to and thus the Arduino knows that that button is pressed. This system reduces the amount of connections from 20 to a mere 6 :)

unsigned long beat_timer = 0;
unsigned long last_time = 0;

int curr_step = 0;
bool kick_steps[16] = {false};
bool snare_steps[16] = {false};
bool hh_steps[16] = {false};
bool tom_steps[16] = {false};

int mode = 0;
int mode_butt_prev = LOW;
bool runnin = false;
bool start_butt_prev = false;
int tempo_prev = 0;

int buttons_timer = 0;

void setup()
{
	//triggers
	pinMode(2, OUTPUT);
	pinMode(3, OUTPUT);
	pinMode(4, OUTPUT);
	pinMode(5, OUTPUT);

	//lights
	pinMode(7, OUTPUT);
	pinMode(6, OUTPUT);
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, LOW);

	//scanners
	pinMode(8, OUTPUT);
	pinMode(9, OUTPUT);
	pinMode(10, OUTPUT);
	pinMode(11, OUTPUT);

	//buttons
	pinMode(12, INPUT_PULLUP);
	pinMode(A0, INPUT_PULLUP);
	pinMode(A1, INPUT_PULLUP);
	pinMode(A5, INPUT_PULLUP);

	//60,000 / BPM = MS per 4th note
	//our sequencer always counts in 16th notes
	//so our final MS is: 4thMS/4
	//So for 120 BPM this would be: 125 ms = 125000 us
	beat_timer = 125000;
	last_time = micros();

	//kick_steps[0] = true;
	//ick_steps[5] = true;

	//set scanners and defaults
	digitalWrite(8, LOW);
	digitalWrite(9, HIGH); //reset
	delay(1);
	digitalWrite(9, LOW);
	digitalWrite(10, LOW);
	digitalWrite(11, HIGH); //reset
	delay(1);
	digitalWrite(11, LOW);

	//lights default
	digitalWrite(7, LOW);
	digitalWrite(6, HIGH);
}

void loop()
{
	if(runnin)
	{
		unsigned long curr_time = micros(); //need to take care of overflow after ~70 minutes
		if(curr_time - last_time > beat_timer)
		{
			last_time = curr_time;

			//set outputs
			digitalWrite(5, kick_steps[curr_step]);
			digitalWrite(2, snare_steps[curr_step]);
			digitalWrite(3, hh_steps[curr_step]);
			digitalWrite(4, tom_steps[curr_step]);

			//step
			curr_step++;
			if(curr_step > 15)
				curr_step = 0;
		}

		//set pins to LOW after 5ms/5000us, to ensure trigger pulse width, regardless of tempo
		curr_time = micros();
		if(curr_time - last_time > 5000)
		{
			digitalWrite(2, LOW);
			digitalWrite(3, LOW);
			digitalWrite(4, LOW);
			digitalWrite(5, LOW);
		}
	}

	//limit amount of scans as a hacky debounce and cpu load reduce
	buttons_timer++;
	if(buttons_timer > 4096)
	{
		//scan tempo 0-1023 mapped to 10-220 BPM, to millisecs, mapped to microsecs
		//((60,000 / BPM) / 4) * 1000
		int temp_tempo = 0;
		if((temp_tempo = analogRead(A4)) != tempo_prev) //quite expensive so lets only do it when changed
		{
			tempo_prev = temp_tempo;
			beat_timer = ((60000 / (long)map(temp_tempo, 0, 1023, 10, 220)) / 4) * 1000;
		}

		//scan START/STOP
		if(analogRead(A0) < 512 && !start_butt_prev)
		{
			runnin = !runnin;
			if(!runnin)
				curr_step = 0; //reset
			start_butt_prev = true;
		}
		else if(analogRead(A0) > 512)
		{
			start_butt_prev = false;
		}

		//scan MODE
		if((temp_tempo = digitalRead(12)) != mode_butt_prev)
		{
			mode++;
			if(mode > 3)
			 mode = 0;
			 
			mode_butt_prev = temp_tempo;
			
			if(mode == 0)
			{
				digitalWrite(7, LOW);
				digitalWrite(6, LOW);
			}
			else if(mode == 1)
			{
				digitalWrite(7, LOW);
				digitalWrite(6, HIGH);
			}
			else if(mode == 2)
			{
				digitalWrite(7, HIGH);
				digitalWrite(6, LOW);
			}
			else
			{
				digitalWrite(7, HIGH);
				digitalWrite(6, HIGH);
			}
		}

		//scan SOUND SEL
		/*if(analogRead(A5) < 512 && !sel_butt_prev)
		{
		}
		else if(analogRead(A5) > 512)
		{
		  
		}*/

		//now scan rhythm switches, when SET/RESET is pressed
		if(analogRead(A1) < 512)
		{
			//digitalWrite(LED_BUILTIN,HIGH);
			//reset both
			digitalWrite(9, HIGH);
			delayMicroseconds(5);
			digitalWrite(9, LOW);

			digitalWrite(11, HIGH);
			delayMicroseconds(5);
			digitalWrite(11, LOW);

			for(int i = 0; i < 8; i++)
			{
				//read out return signal
				if(analogRead(A2) > 64)
				{
					//1st row button's been set
					if(mode == 0)
						kick_steps[i] = true;
					else if(mode == 1)
						snare_steps[i] = true;
					else if(mode == 2)
						hh_steps[i] = true;
					else
						tom_steps[i] = true;
				}
				else
				{
					if(mode == 0)
						kick_steps[i] = false;
					else if(mode == 1)
						snare_steps[i] = false;
					else if(mode == 2)
						hh_steps[i] = false;
					else
						tom_steps[i] = false;
				}
				if(analogRead(A3) > 64)
				{
					//2nd row button's been set
					if(mode == 0)
						kick_steps[i + 8] = true;
					else if(mode == 1)
						snare_steps[i + 8] = true;
					else if(mode == 2)
						hh_steps[i + 8] = true;
					else
						tom_steps[i + 8] = true;
				}
				else
				{
					if(mode == 0)
						kick_steps[i + 8] = false;
					else if(mode == 1)
						snare_steps[i + 8] = false;
					else if(mode == 2)
						hh_steps[i + 8] = false;
					else
						tom_steps[i + 8] = false;
				}

				//step scanners
				digitalWrite(8, HIGH);
				delayMicroseconds(5);
				digitalWrite(8, LOW);

				digitalWrite(10, HIGH);
				delayMicroseconds(5);
				digitalWrite(10, LOW);
			}
			//digitalWrite(LED_BUILTIN,LOW);
		}
	}
}
		

So that's all the code and digital stuff. On to the analog goodness!



The Kick Drum




The kick is build around a bridged-T circuit, using a 4558 or 358 op-amp. Other similar op-amps will probably work too though you might get varying decay times and pitches.

The supply voltages are a bit odd because this circuit is most happy with a dual rail power supply. Since I only had a 12V single rail supply available I simply made a virtual ground using an op-amp as a buffer, V+ is +6V and V- is -6V in my schematic. Note that the trigger filter and bridged-T circuit both use the virtual ground.

Here's the virtual ground circuit I used:


The reason I used this circuit and not a simple resistor-divider is because using an op-amp you get way more stability even if the current draw is higher. A resistor-divider shifts in voltage as soon as you get a couple of mA of current draw and this would affect the sound.
I'm glad I ended up doing it this way because I ended up using that 6V/virtual ground quite a few times!




The Snare Drum




The snare combines a classic transistor noise circuit through a simple VCA and the bridged-T circuit. The idea is that the noise emulated the snare mat, whereas the bridged-T circuit emulates the drum sound itself. Note that the bridged-T uses the virtual ground discussed earlier (here at +6V relative to actual ground!).
In all honesty it sounds a bit more like a noisy tom, but since the Drumique already had the harch claps sound this turned out to be a perfect "snare" for this sound set. So I kept it the way it is.

Some analog drum machines run the noise through the bridged-T instead of having it separate, which sounds a bit harsher than what my circuit generates.
Experimentation is key so try both ways and see what you like! I also suggest using trimmers instead of the two output resistors to fine tune the mix between tone and noise.

The noise circuit I've used in all my noise circuits (snare, high hat and claps) is the following one by R. Andersen:


Please note that in my snare circuit the 4.7k resistor is replaced by the diode of the VCA and that I used different values for the resistor and capacitor.



The High Hat




The high hat is quite a complex circuit. Just like the snare drum it consists of two main sounds mixed together.
In this case it's three square wave oscillators that are tuned to frequencies quite close to eachother. This mimics the way a real cymbal resonates, generating loads of overtones and harmonics. Since square waves have a lot of harmonics they are a great solution to emulating a cymbal.

Again it's a good idea to use a trimmer for the noise mix (22k resistor) as certain settings generate various kind of tones and vibes, so its great to tune this sound to your liking.

The noise circuit used is the same one as the snare, but again with slightly different values.



The Claps




The claps are actually just really op-amp distorted noise, but despite its simplicity it sounds great. The decay setting matters a lot for the sound, can go from very snappy and short (almost snare) sounds to lengthy and gnarly. The capacitor in the op-amp circuit matters a lot for the sound so my advice is to play around with different ones on your breadboard.




Copyright 2018 Evil Turtle Productions. All Rights Reserved.