The Doof Machine - Arduino Drum Sequencer - Simple & Customizable

by PTV in Circuits > Arduino

530 Views, 4 Favorites, 0 Comments

The Doof Machine - Arduino Drum Sequencer - Simple & Customizable

PTV04 The Doof Machine - Instructables Edition - Opening
coverpic1.png
IMG_0034.JPG
PTV04 The Doof Machine Uno.png

Hey there!

Welcome to PTV04 "The Doof Machine". Please come in! Sit down and make yourself comfortable. Can I get you a drink or something?

Basically, I wanted something that would be pretty easy to make, yet be fun/useful enough to make it worth doing; and allow for some customization too.

Inspired by Gavin Davies' work https://gavd.co.uk/2022/03/arduino-based-drum-machine/

The Doof Machine is a 16 step drum sequencer that plays 1, 2 or a blend of 2 samples at any one time. 2 dials for each sample (one controls how many steps in each loop/sequence [up to 16], and the other controls how many of those steps will be playing a sample [up to 16 depending on what you've set your "number of steps" dial to]) and 1 dial for tempo control. You can have 4 samples loaded into each sample bank (8 samples in total) and that seems to allow for a pretty decent amount of variation in sounds and beats without making to project too complex. Check out the video! See what you think.

I will go through in detail how to make your own samples and adjust the code.

The Doof Machine is meant to be an entry level safe project and I will do my best to present it in a way that makes it accessible for someone that has very little or no prior knowledge. An interest in computers, electronics and music is highly recommended though!

It's pretty easy to put together and doesn't require too many parts but I think it's a satisfying enough project to make it worth having a go at. Hope you enjoy!

Supplies

IMG_0229.JPG
IMG_0223.JPG
IMG_0222.JPG
IMG_0218.JPG
IMG_0232.JPG
IMG_0220.JPG
IMG_0224.JPG
IMG_0226.JPG

Here's a list of components and tools you'll need to bring your own Doof Machine to life!:


Materials:

  1. An Arduino board! You'll need an Arduino board as the brain of your Doof Machine. An Arduino Uno or Arduino Nano (or equivalent aftermarket version) is recommended for this project. I have used an aftermarket Arduino Nano in this Instructable but an Uno will also work fine without having to edit any code.
  2. A USB cable that matches your Arduino board!
  3. A PC to run your Arduino IDE and upload the code!
  4. A full size breadboard! 5.5 cm x 17 cm (2.2" x 7"), the row numbers should go up to about 65.
  5. 5 linear dial potentiometers! Pretty much any rating should be fine, but make sure that they are linear B type potentiometers. Otherwise you may get some unbalanced results. In this Instructable I used 5 B50K pots that I upcycled from an old mixing desk. However I'm currently making a circuit board version with some newly purchased B10Ks. Higher ratings should work fine too.
  6. 8 push buttons! Basic single pole, single throw (SPST) buttons.
  7. 6.3mm (1/4") female mono audio output jack! For connecting The Doof Machine to a guitar amp or some other audio output.
  8. A bunch of wires! About 15 long ones and about 24 shorter ones.
  9. A guitar amp and lead! or something similar to connect your new instrument into.
  10. A soldering iron and 60/40 rosin core solder! (optional) To solder the pins onto the Arduino Nano and connect wires to the output jack (if necessary).
  11. A sincere urge to succeed and flood the world with fantastic electronic noise!

Install Arduino IDE, Check Your Arduino, Install Mozzi & Grab Samples!

In this step, you'll set up your development environment by installing the Arduino Integrated Development Environment (IDE) . It's also a good time to make sure that your Arduino's working too!





  • Once you've installed the Mozzi library, it couldn't hurt to close down and reopen the Arduino just to make sure the changes have taken effect.
  • Once that's done and good to go, you'll need to jump into your file explorer window (or finder or equivalent) and get into the Mozzi directory within libraries in the Arduino IDE (which is usually in Documents). **For Example** C:\Users\Peter\Documents\Arduino\libraries\Mozzi
  • Once in, we'll need to make a new folder called "sfx" (C:\Users\Peter\Documents\Arduino\libraries\Mozzi\sfx) This "sfx" folder is where we'll keep all of our samples for The Doof Machine. I suppose they could have gone into the already existing "samples" folder, but I thought that this way would keep everything nice and neat.
  • Please note that the code assumes that you have an "sfx" folder in your Mozzi library!
  • Then it's just a matter of downloading the below samples into the "sfx" folder and getting ourselves ready to start putting the board together!

Wiring the Circuit!

PTV04 The Doof Machine Nano.png
PTV04 The Doof Machine Nano - Marked.png
PTV04 The Doof Machine Uno.png
PTV04 The Doof Machine Uno - marked.png

Okay, got all your bits and pieces? Let's do this!



Please refer to the below table for ease of connections with your project. There are copies of the above diagrams for your reference that include the used notations.

B=Buttons!

D=Digital Arduino Pins!

P=Potentiometers!

A=Analogue Arduino Pins!

B1 >to> D3

B2 >to> D4

B3 >to> D5

B4 >to> D6

B5 >to> D7

B6 >to> D8

B7 >to> D10

B8 >to> D11

P1 >to> A3

P2 >to> A4

P3 >to> A1

P4 >to> A5

P5 >to> A2

+ Wire on 1/4" Audio Socket >to> D9 (PWM)

Upload the Code and Try It Out!


Okay, without any more messing around. Here's the code!

(There is also a .ino file available).

So what are you waiting for!? Jump into your Arduino IDE, upload the code and get things running!


/*
PTV04 The Doof Machine - Instructables Edition
Peter Polmeartagami - PTV ArtSpace 2023
Create more music machines! Create more music!


Inspired by Gavin Davies' work https://gavd.co.uk/2022/03/arduino-based-drum-machine/
*/


#include <MozziGuts.h>
#include <Sample.h>
#include "sfx/doof01.h"
#include "sfx/doof02.h"
#include "sfx/doof03.h"
#include "sfx/tsh04.h"
#include "sfx/tsh01.h"
#include "sfx/tsh02.h"
#include "sfx/tsh03.h"
#include "sfx/doof04.h"


#include <EventDelay.h>
#include <mozzi_rand.h>


#define CONTROL_RATE 128
#define CELLS_PER_SAMPLE 2048


Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aDoof01(DOOF01_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aDoof02(DOOF02_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aDoof03(DOOF03_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aTsh04(TSH04_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aTsh01(TSH01_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aTsh02(TSH02_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aTsh03(TSH03_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aDoof04(DOOF04_DATA);


Sample<CELLS_PER_SAMPLE, AUDIO_RATE>* sample1 = &aDoof01;
Sample<CELLS_PER_SAMPLE, AUDIO_RATE>* sample2 = &aTsh01;


EventDelay kTriggerDelay;
const byte MAX_STEP_COUNT = 16;
byte cursor1 = 0;
byte cursor2 = 0;


void setup() {
  pinMode(2, INPUT_PULLUP); // ON/OFF switch if you want to add one.
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  startMozzi();


  aDoof01.setFreq((float)DOOF01_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aDoof02.setFreq((float)DOOF02_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aDoof03.setFreq((float)DOOF03_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aTsh04.setFreq((float)TSH04_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aTsh01.setFreq((float)TSH01_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aTsh02.setFreq((float)TSH02_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aTsh03.setFreq((float)TSH03_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aDoof04.setFreq((float)DOOF04_SAMPLERATE / (float)CELLS_PER_SAMPLE);
 


  kTriggerDelay.set(10);
}


bool shouldPlay(byte steps, byte beats, byte i) {
  float divisor = ((float)beats / (float)steps);
  bool shouldPlay;
  if (i == 0) {
    shouldPlay = (beats != 0);
  } else {
    byte score = i * divisor;
    byte prevScore = (i - 1) * divisor;
    shouldPlay = (score > prevScore);
  }
  return shouldPlay;
}


void updateControl() {  // ON/OFF switch if you want to add one.
  if (digitalRead(2) == LOW) {
    return;
  }


  if (digitalRead(3) == LOW) {
    sample1 = &aDoof01;
  } else if (digitalRead(4) == LOW) {
    sample1 = &aDoof02;
  } else if (digitalRead(5) == LOW) {
    sample1 = &aDoof03;
  } else if (digitalRead(6) == LOW) {
    sample1 = &aTsh04;
  } else {
    // You can assign different samples or set sample1 to nullptr if you want no sound.
  }


  if (digitalRead(7) == LOW) {
    sample2 = &aTsh01;
  } else if (digitalRead(8) == LOW) {
    sample2 = &aTsh02;
  } else if (digitalRead(10) == LOW) {
    sample2 = &aTsh03;
  } else if (digitalRead(11) == LOW) {
    sample2 = &aDoof04;
  } else {
    // You can assign different samples or set sample2 to nullptr if you want no sound.
  }


  byte steps1 = (byte)map(mozziAnalogRead(4), 0, 1023, 1, MAX_STEP_COUNT);
  byte beats1 = (byte)map(mozziAnalogRead(1), 0, 1023, 0, steps1);
  byte steps2 = (byte)map(mozziAnalogRead(5), 0, 1023, 1, MAX_STEP_COUNT);
  byte beats2 = (byte)map(mozziAnalogRead(2), 0, 1023, 0, steps2);


  if (kTriggerDelay.ready()) {
    if (cursor1 >= steps1) {
      cursor1 = 0;
    }
    if (cursor2 >= steps2) {
      cursor2 = 0;
    }


    if (shouldPlay(steps1, beats1, cursor1)) {
      (*sample1).start();
    }
    if (shouldPlay(steps2, beats2, cursor2)) {
      (*sample2).start();
    }


    cursor1++;
    cursor2++;


    kTriggerDelay.start(map(mozziAnalogRead(3), 0, 1023, 300, 50));
  }
}


int updateAudio() {
  int asig = (int)(((long)(*sample1).next() + (*sample2).next()) * 127);
  if (asig > 127) {
    asig = 127;
  } else if (asig < -128) {
    asig = -128;
  }
  return asig;
}


void loop() {
  audioHook();
}


Okay! You can call that complete now if you want to! Well done!

However.... If you would like to dig deeper and learn how to customise your own sounds relatively easily,

please continue!

Creating and Uploading Your Own Samples!

Okay, so you wanna customise this little puppy, aye? Well let's do it then!

THIS SECTION ASSUMES A SOMEWHAT INTERMEDIATE LEVEL OF PC SAVVY! (I'm sure you'll be fine)

Before anything else, I highly recommend printing out a copy of The Doof Machine's code in it's entirety. It'll make any check work much quicker and easier on the eyes/brain.

Although not the only way to do it, this is the way that I have done it. And I have done it this way because it was (after a lot of scratching my head) the easiest and most cost effective way I've been able to find so far given my current skill level.

I hope it helps you in some way!

Software Used


Make Your Samples!

What we want from this exercise is 8 new (short length!) samples in a .wav format.


Apologies if this and the next video seem a little long-winded. Feel free to skip through once you understand the process!

Prepare Your Samples!

What we want from this exercise is 8 samples in a (headerless) .RAW format, trimmed to a length of 2048 samples (for the code) at a 16,384 Hz sample rate (for Mozzi) in a signed 8-bit PCM format.


Convert Your Samples!

Using the below Google Colab Notebook, we can quickly convert all 8 of our (or any number of) samples all at once into Mozzi and Arduino friendly .h files complete with all required effects. This notebook should be useful for many other Mozzi sample applications. It can handle samples of any length.

Please feel free to make use of and distribute this code in any way you see fit. Make more music machines!

RAW2HQuick


Updating The Code To Run Your New Samples!

Chat GPT can make this chore much easier! Although sometimes it plays nicer than other times. This step is why a printout of the original code is useful!


Recommended Chat GPT Prompt:

Can you please rewrite the above code with

xxx.h replacing doof01.h,

xxx.h replacing doof02.h,

xxx.h replacing doof03.h,

xxx.h replacing doof04.h,

xxx.h replacing tsh01.h,

xxx.h replacing tsh02.h,

xxx.h replacing tsh03.h,

xxx.h replacing tsh04.h?


/* 
PTV04 The Doof Machine - Instructables Edition
Peter Polmeartagami - PTV ArtSpace 2023
Create more music machines! Create more music!

Inspired by Gavin Davies' work https://gavd.co.uk/2022/03/arduino-based-drum-machine/
*/

#include <MozziGuts.h>
#include <Sample.h>
#include "sfx/bom01.h"
#include "sfx/bom02.h"
#include "sfx/bom03.h"
#include "sfx/chi04.h"
#include "sfx/chi01.h"
#include "sfx/chi02.h"
#include "sfx/chi03.h"
#include "sfx/bom04.h"

#include <EventDelay.h>
#include <mozzi_rand.h>

#define CONTROL_RATE 128
#define CELLS_PER_SAMPLE 2048

Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aBom01(BOM01_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aBom02(BOM02_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aBom03(BOM03_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aChi04(CHI04_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aChi01(CHI01_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aChi02(CHI02_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aChi03(CHI03_DATA);
Sample<CELLS_PER_SAMPLE, AUDIO_RATE> aBom04(BOM04_DATA);

Sample<CELLS_PER_SAMPLE, AUDIO_RATE>* sample1 = &aBom01;
Sample<CELLS_PER_SAMPLE, AUDIO_RATE>* sample2 = &aChi01;

EventDelay kTriggerDelay;
const byte MAX_STEP_COUNT = 16;
byte cursor1 = 0;
byte cursor2 = 0;

void setup() {
  pinMode(2, INPUT_PULLUP); // ON/OFF switch if you want to add one.
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  startMozzi();

  aBom01.setFreq((float)BOM01_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aBom02.setFreq((float)BOM02_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aBom03.setFreq((float)BOM03_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aChi04.setFreq((float)CHI04_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aChi01.setFreq((float)CHI01_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aChi02.setFreq((float)CHI02_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aChi03.setFreq((float)CHI03_SAMPLERATE / (float)CELLS_PER_SAMPLE);
  aBom04.setFreq((float)BOM04_SAMPLERATE / (float)CELLS_PER_SAMPLE);
 
  kTriggerDelay.set(10);
}

bool shouldPlay(byte steps, byte beats, byte i) {
  float divisor = ((float)beats / (float)steps);
  bool shouldPlay;
  if (i == 0) {
    shouldPlay = (beats != 0);
  } else {
    byte score = i * divisor;
    byte prevScore = (i - 1) * divisor;
    shouldPlay = (score > prevScore);
  }
  return shouldPlay;
}

void updateControl() {  // ON/OFF switch if you want to add one.
  if (digitalRead(2) == LOW) {
    return;
  }

  if (digitalRead(3) == LOW) {
    sample1 = &aBom01;
  } else if (digitalRead(4) == LOW) {
    sample1 = &aBom02;
  } else if (digitalRead(5) == LOW) {
    sample1 = &aBom03;
  } else if (digitalRead(6) == LOW) {
    sample1 = &aChi04;
  } else {
    // You can assign different samples or set sample1 to nullptr if you want no sound.
  }

  if (digitalRead(7) == LOW) {
    sample2 = &aChi01;
  } else if (digitalRead(8) == LOW) {
    sample2 = &aChi02;
  } else if (digitalRead(10) == LOW) {
    sample2 = &aChi03;
  } else if (digitalRead(11) == LOW) {
    sample2 = &aBom04;
  } else {
    // You can assign different samples or set sample2 to nullptr if you want no sound.
  }

  byte steps1 = (byte)map(mozziAnalogRead(4), 0, 1023, 1, MAX_STEP_COUNT);
  byte beats1 = (byte)map(mozziAnalogRead(1), 0, 1023, 0, steps1);
  byte steps2 = (byte)map(mozziAnalogRead(5), 0, 1023, 1, MAX_STEP_COUNT);
  byte beats2 = (byte)map(mozziAnalogRead(2), 0, 1023, 0, steps2);

  if (kTriggerDelay.ready()) {
    if (cursor1 >= steps1) {
      cursor1 = 0;
    }
    if (cursor2 >= steps2) {
      cursor2 = 0;
    }

    if (shouldPlay(steps1, beats1, cursor1)) {
      (*sample1).start();
    }
    if (shouldPlay(steps2, beats2, cursor2)) {
      (*sample2).start();
    }

    cursor1++;
    cursor2++;

    kTriggerDelay.start(map(mozziAnalogRead(3), 0, 1023, 300, 50));
  }
}

int updateAudio() {
  int asig = (int)(((long)(*sample1).next() + (*sample2).next()) * 127);
  if (asig > 127) {
    asig = 127;
  } else if (asig < -128) {
    asig = -128;
  }
  return asig;
}

void loop() {
  audioHook();
}


Thank you so much! I hope you enjoyed!


Peter Polmeartagami

PTV (Polmeartagami Ventures)