gavd.co.uk

Frail and faltering follower of Jesus

Page image

Arduino MIDI arpeggiator

By Gavin Davies

Simple MIDI arpeggiator prototype based on Arduino

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:

  1. Knob 1 - controls base note
  2. Knob 2 - controls arpeggio (“pattern”)
  3. Knob 3 - controls tempo
  4. 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);
}

/articles/arduino-midi-arpeggiator/arduinoarps.jpg