Figuring out the Woovebox MIDI protocol for Woovebox Connect

So, I had this idea for a piece of software that would listen to the MIDI output of the Woovebox and instead of just displaying the surface of the Woovebox verbatim as Woovebox Connect does, it would display additional help information for the screen and parameter you're on. The Woovebox display doesn't always do the best job to show where you're at.

The Woovebox micro music workstation sitting on a nondescript table

For this I wanted to see what kind of information the Woovebox actually sends.

To figure this out, I could do two things: I could try to look at the source code (Woovebox Connect is a web application, after all) or I could just try to analyse the MIDI messages. Unfortunately, the code is (probably) written in a language other than JavaScript for the most part and then compiled to JavaScript and a Webassembly module using Emscripten. This could be disassembled but I would rather not try that as the first approach.

Instead, I connected the Woovebox via my CMI Bluetooth MIDI interface interface to my computer and started a MIDI monitor and watched what was coming in.

First things first: When the device is at idle (Say in the Song mode, not playing), the device sends three message every few seconds

(I'll show the received bytes in hex here once and then a more descriptive form I will use exclusively after this)

0xB0 0x09 0x03 (CC:9 on Ch1, Value 3)
0xB0 0x09 0x04 (CC:9 on Ch1, Value 4)
0xB1 0x09 0x23 (CC:9 on Ch2, Value 35)

The 3 and 4 seem to be part of an actual heartbeat scheme for Woovebox connect, as the device sends the 3 regularly even if not connected to Woovebox Connect. If connected, Woovebox Connect seems to answer with a 4, which then the Woovebox answers with both the 4 and the CC:9 on Channel 2.

The third message (CC:9 on Ch 2) changes in value and looking at the Woovebox Connect screen, it is reasonable to assume that this is the battery percentage.

Unsurprisingly, more interesting things happen when you interact with the device. I was hoping for some usable information on where in the page/menu structure the device is currently in, but the implementation seems to be very focused on getting the Woovebox Connect mirroring working (Fair enough!).

Let's start with the input. Every time you interact with either the encoder or any of the fake or real buttons, some control changes are sent.

For buttons (and this includes pressing the encoder in), there's always a CC:3 on Channel 1 for button down and a CC:3 on Channel 2 for button up. The value encodes the actual button pressed:

The encoder sends either 1 or 2 on CC:3 on Channel 2 for a left or a right turn (One for each step of the encoder)

That's the input covered. The state of the display of the Woovebox is, when ever needed, dumped as a bunch of CCs as well, but this took me a while to figure out. The easier one to explain is how the device sends the status of the button LEDs. There are two messages, CC:14/15 (I'll explain THAT in a sec) on Channel 9 and 10, sending the state of the upper and lower 8 LEDs as a bitfield, the lowest bit addressing the last bit in the 8 LED block. Now, MIDI aficionados will have spotted a problem: Addressing 8 bits with a CC value is a bit of an issue, because MIDI value bytes are 7 bit only. Here's where the two different CC's come into play: CC14 will clear the 8th bit, CC15 will set it. So to switch all LEDs on, you would send: CC:15 on Channel 9 as 127 and CC:15 on Channel 10 as 127.

Now for the fun part: The state of the 7-segment display is dumped in a series of messages in similar fashion: CC:14/15 for Channels 1-8 (For the 8 digits). But what are the values? I first thought of maybe ASCII or something similar, but playing around with the values the Woovebox sent, this didn't make any sense. Then I realised that a 7-segment display (at least one that has dots next to the digit) is an 8-bit value as well. Looking up how the seven segments are usually addressed and staring at binary numbers for a while confirmed that this was indeed what I was looking for.

-a-
f b
-g-
e c
-d-

One interesting thing is that the Woovebox even sends every frame of the (slightly obnoxious) scrolling when paging.

Unfortunately, this seems to be all there is to it. I don't think I have seen messages that aren't covered by the above.

Just as a note, as someone who had to work with, or implement MIDI addressing schemes a couple of times, the whole thing feels a bit wild. There's not a lot of room to send other messages and it's not

So, how hard would it be to build that thing I want to build? Well, for one, harder than I thought, but I think there's a chance. Here's what I'm thinking:

  1. Have a representation of the display in memory and update it according to the MIDI messages that come in
  2. Match the display contents to a list of known content variations that we know represent the pages. This could be either done by matching arrays or, more efficiently, turn the 8 bytes into one big number.
  3. Show the help for that page

There are issues with this approach. For example, holding a parameter button for a longer period of time (because you want to read the help) will first switch to the long parameter name (We could also match) but then switches back to the page header and only if you modify the value, it will switch back to the parameter screen.

This can probably be overcome by some clever selection on what screens contents to act on and which ones to ignore (and probably also listen to the button up so as to when to actually switch back to the overview help.

I will see if I can find some time soon to hack together a prototype.