Arduino MIDI arpeggiator
I’ve been learning Arduino recently; my mate Jon and I have been discussing building some kind of synth modules based on the platform.
To help me get started, I built a very simple 4 input arpeggiator:
- Knob 1 - controls base note
- Knob 2 - controls arpeggio (“pattern”)
- Knob 3 - controls tempo
- Knob 4 - emphasis - various patterns of velocity
This is just for learning really; MIDI is easier to work with as it’s simple digital out.
Video of it in operation:
Here’s the source code. It’s really scrappy but it does work!
const int MIDI_CHANNEL_1 = 0x90;
const int ARP_VARIATIONS = 13;
const int ARP_LENGTH = 8;
const int VELOCITY_SILENT = 0x00;
const int arps[ARP_VARIATIONS][ARP_LENGTH] = {
// major asc
{ 0, 4, 7, 12, 0, 4, 7, 12 },
// major desc
{ 12, 7, 4, 0, 12, 7, 4, 0 },
// major up and down
{ 0, 4, 7, 12, 12, 7, 4, 0 },
// major asc 2 oct
{ 0, 4, 7, 12, 16, 21, 24, 24 },
// major 7
{ 0, 4, 7, 11, 12, 11, 7, 4 },
// dominant 7
{ 0, 4, 7, 10, 12, 10, 7, 4 },
// minor asc
{ 0, 3, 7, 12, 0, 3, 7, 12 },
// minor desc
{ 12, 7, 3, 0, 12, 7, 3, 0 },
// minor up and down
{ 0, 3, 7, 12, 12, 7, 3, 0 },
// minor with major 7
{ 0, 3, 7, 11, 12, 11, 7, 3 },
// minor with dominant 7
{ 0, 3, 7, 10, 12, 10, 7, 3 },
// chromatic asc
{ 0, 1, 2, 3, 4, 5, 6, 7 },
// chromatic desc
{ 7, 6, 5, 4, 3, 2, 1, 0 },
};
const int grooves[3][4] = {
// flag
{ 0x45, 0x45, 0x45, 0x45 },
// downbeat
{ 0x70, 0x45, 0x45, 0x45 },
{ 0x70, 0x45, 0x65, 0x45 }
// downbeat and upbeat
//{ 0x60, 0x45, 0x60, 0x45 }
};
const int NOTE_GAP_AFTER_MS = 1;
// global scope
int pattern = 0; // the arp we're running
int baseNote = 10; // note to start on
int groove = 0; // the velocity groove
void setup() {
// Set MIDI baud rate:
Serial.begin(31250);
}
void selectArp() {
float sensorValue = analogRead(A0);
pattern = (sensorValue / 1024) * 13;// TODO magic numbers
}
void selectBaseNote() {
float sensorValue = analogRead(A2);
float tmp = sensorValue / 1024;// TODO magic numbers
baseNote = (tmp * 90) + 10;
}
void selectGroove() {
float sensorValue = analogRead(A3);
float tmp = sensorValue / 1024; // TODO magic numbers
groove = (tmp * 3);
}
void loop() {
int i = 0;
int idxGroove = 0;
while (true) {
selectArp();
int noteLengthMs = analogRead(A1);
selectBaseNote();
selectGroove();
// play the note
int note = arps[pattern][i] + baseNote;
Serial.print(i, note);
// slightly stronger down beat
int velocity = grooves[groove][idxGroove];
noteOn(MIDI_CHANNEL_1, note, velocity);
delay(noteLengthMs);
noteOn(MIDI_CHANNEL_1, note, VELOCITY_SILENT);
delay(NOTE_GAP_AFTER_MS);
i++;
if (i >= ARP_LENGTH) {
i = 0;
}
// TODO jagged arrays
idxGroove++;
if (idxGroove >= 4) {
idxGroove = 0;
}
}
}
// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:
void noteOn(int cmd, int pitch, int velocity) {
Serial.write(cmd);
Serial.write(pitch);
Serial.write(velocity);
}
I have also co-written “Mitty the Kitty”, an Arduino based game with my kids and built an Arduino synth and drum machine