Holiday Project: Working with MIDI clock over BLE and ESP32

I built a MIDI sequencer over Bluetooth low energy (BLE) using Arduino-like ESP32 microcontrollers. Here are my findings.

.

It’s been a long vacation. The Jewish holiday season was nice to us this year and spanned across two weeks of continuous vacation. So I had some time to do something with all of the utilities I bought off AliExpress.

When I was young, my dream was for my high school band to become extremely successful and to be able to do music for a living. I really love expressing myself through art and have always thought I have good things to share with the rest of the world. Coding is one example of art, but guitar playing is, too.

I have lots of guitar gear lying around and I had the idea of trying to build simple tools using Arduino. I know how to code—how hard can it be?

It seems that most things are very simple and most of it was just "connecting the dots".

So in a day, I built a simple MIDI sequencer that is generating MIDI Control Change commands over Bluetooth Low Energy (BLE). I built it using ESP32 DOIT DevKit, which has Bluetooth and WiFi integrated, while still being fairly cheap and small.

What is MIDI?

MIDI, Musical Instruments Digital Interface, is a standard digital protocol for musical instruments to communicate with each other. Most Keyboards (electric piano-like) have "MIDI out" ports to allow them to be connected to a MIDI host, a device that receives MIDI signals, and to send notes for the host to play.

That's not all. Some guitar effect pedals and units have MIDI in and/or MIDI out, to allow controlling them, or to allow them to control other pedals.

How does it know what to do? MIDI has several types of messages Just to list a few:

  • "note on" and "note off" do exactly what you probably think. It's exactly like pressing on a key in the keyboard: it has a channel (MIDI channel, or device, to apply the note), the note itself, and a velocity. This is very helpful if you want to build a synth and want to use an external physical keyboard 😉
  • "midi clock" is an event for tempo synchronization. We will discuss it in a few paragraphs.
  • "program change" (or PC) is a request to change into a preset or a... predefined program. It also expects a MIDI channel to send data to.
  • "control change" (or CC) is a request to change something. the "something" we want to change is assigned to a number, an ID of some sort. Some devices have pre-defined CC numbers configured for some actions, and some allow you to set custom numbers for different abilities. It can request to change the volume of the synth, using a fader on the external keyboard, or engage a specific effect or change values in effects, in many guitar pedals. The HXFX has both pre-defined CC numbers and has the ability to extend the pre-defined ones with custom CC numbers to control other settings.

This enables experienced guitar players to have advanced scenarios in their signal chain: press one button to engage all the effects and presets needed for a certain song or part, and avoid "tap dancing"—the funny dance you see when guitar players try to change multiple effects in a minimal time. Automation! for guitar players! it is like programming for my guitar playing! This is obviously my jam.

I personally have multiple guitar effects that support MIDI, but I am focusing on Line 6 HX Effects (I will refer it to HXFX from now), which is an awesome multi-effect processor. I am a fan of Line 6 products since I was in middle-school and I find myself falling back to their products every now and then (I have a couple of them in my guitar gear cabinet).

The Effect I'm Looking For

The HXFX has a bunch of pitch modules. The last couple of versions really upgraded their sound, but still did not give the effect I was looking for. The effect I'm trying to get is similar to the notable intro of Muse's song "Map of the Problematique", but that hook repeats on the chorus too. If you aren't familiar with it, here's the (amazing!) song:

A mesmerizing harmonizing guitar intro!

The effect is an harmonizing arpeggiator, that, after playing one legato (or continuous) note and then, it will manipulate the pitch based on a rhythm of my choice. "dumdum-duhduh-dum-duh-dumdum-duhduh"!

This is called a sequencer. We have a grid with specific divisions (1/4ths, 1/8ths, 1/16ths) and we can send MIDI messages based on the current tempo and the given time.

Communication between HXFX and ESP32

There are libraries for both MIDI and MIDI over BLE. These two libraries work very well together, although I had a little glitch. More on this later.

I decided to use MIDI over BLE because I still haven't got my resistor pack from eBay, so I can't create a wired MIDI circuit <_<, so I used BLE as a transport mechanism in the meantime. This can be nice, though! I might build a MIDI controller in the future, and I will integrate MIDI over BLE for wireless communication in it 😇

MIDI gives the ability to communicate both (input and output):

  • The output will be Control Change messages, which will tell HXFX to change the harmonizing MIX (or any other parameter) in various timings.
  • The input will be used to get MIDI clock, so we will know when to send the MIDI messages (based on the current tempo, declared in HXFX!)

Pairing the HXFX to BLE was fairly simple, as I used WIDI Master, which I own for years and never used it, ever since it was on Kickstarter or something similar.

Control Change

Sending a "Control Change" message is fairly easy with the Arduino MIDI library:

MIDI.sendControlChange(cc_number, cc_value, channel);

where:

  • cc_number is the Control Change number (as we mentioned earlier in the MIDI message types) we will assign in HX FX (for controlling the "mix" or any other parameter). I used 5
  • cc_value is the value we want to set with this control change. The range is between 0 and 127. When aiming for "Map of the Problematique" sound, I had an array of zeroes and 127s, so it was either 0% mix or 100% mix for the effect.
  • channel is a the channel HXFX is listening on. I used 1.

MIDI Clock

A unit like HXFX can contain multiple effects that are time-driven, like delays or modulation, and most of the time you want them to be in a specific tempo (measured in BPM, number of beats per minute). Each song has its own tempo, and sometimes different parts have different tempos An example of such song is "Prayer of the Refugee" by Rise Against.

I want HXFX to be "the brain" of my time-based effects, so I want it to calculate the tempo. It is very convenient because HXFX has a dedicated "tap tempo" button which allow to tap it in a specific rhythm and it calculates the BPM based on the taps.

HXFX can be set to send "MIDI clock" messages to inform us when to send a given MIDI message!

So what is MIDI clock?

MIDI clock is a MIDI message that happens 24 times on every beat, given the current tempo. So, in a tempo of 120BPM, that generates 2 beats per second, we will have 48 MIDI clock messages every second (24 * 120 / 60 = 48)

How is it useful? For the effect in use, I want to use 1/16th. That means I want to send a control change every 6th MIDI clock message: if there are 24 messages in a quarter, and we want sixteenth, it means 24 / 4 = 6 messages. It means our "iteration" can look something like so:

int ticks = 0;
byte controlChanges[] = { /* 16 control changes */ };

void loop() {
  if (!isConnectedToBLE()) {
    return;
  }

  while (MIDI.read()) {
    if (MIDI.getType() == midi::Clock) {
      ticks = (ticks + 1) % (24 * 16);
      if (ticks % 6 == 0) {
        sendControlChangeForSixteenth(ticks / 6);
      }
    }
  }
}

And now all we have left is to implement sendControlChangeForSixteenth:

int ccNumber = 5;
int channel = 1;

void sendControlChangeForSixteenth(int sixteenth) {
  MIDI.sendControlChange(ccNumber, controlChanges[sixteenth % 16], channel);
}

Finishing Up

The device is working properly! and now all left for me to do is to wait for my AliExpress shipment of a resistor kit, so I can use MIDI cables instead of wireless Bluetooth. This will allow me to stick it underneath my pedalboard and have a nice extension for my Line 6 HX Effects!


That's it. It was a fairly simple project, but it was very very fun to do—gives me the confidence that I might be able to build more complex tools, maybe a clone of Morningstar FX's MC-6 which I also own (or go for the MC-8 on my clone!).