On a harpsichord, pressing the key triggers a hammer to strike a string. It doesn’t matter how hard you play the key, or how long you hold the note down, you will always get the same hammer strike from it. So all that matters, in terms of musical events, is which key you pushed down. In the MIDI standard this is a “Note On” message.
On an organ, pressing a key opens a valve, releasing a key closes it. Playing the key harder or softer doesn’t do anything. In the MIDI standard, it needs Note On and Note Off messages.
On a piano, the velocity at which you press the key determines how fast the hammer swings, and therefore how loud the note is. Also releasing the key will dampen the note, though it won’t ring out forever. So you’ve got Note On messages with velocity, and Note Off.
On a synth, you might also have pressure as well as velocity — while holding a note down, pressing harder might increase the volume or brightness. This comes in two formats:
- Channel pressure: the overall pressure across the keyboard, regardless of which notes are played. This was somewhat common on mid-range controllers, being relatively cheap to implement.
- Polyphonic aftertouch: the pressure of each individual key on the keyboard. So if you hold down C2 with a lot of pressure but lightly press E3, they two notes will have different pressure values. This used to be a high-end feature since it required many more sensors, but with modern tech you’ll find it on much cheaper controllers now, like the Launchpad X and Microfreak that I have.
Going newer and more expensive with specialized controllers, there’s also MPE (Midi Polyphonic Expression) — which can send not just pressure but position, tilt, or other messages per note. Each of these is sent on a separate channel. For instance, you can bend notes or have individual vibrato per note like on guitar strings.
Some people demand MPE support on newer software synths. But a lot of them either don’t directly support pressure, or only channel pressure. Bitwig can assign channel pressure to a parameter of any synth even if it doesn’t directly support it (and its own native synths can support polyAT).
When you have a controller that sends polyAT and you want to use it as channel pressure, the correct thing to do is use the maximum pressure of all the keys. That is what the Microfreak does internally, if you assign pressure to the filter for example. There are many keys but only one filter, so it uses the strongest pressure to control that.
But in Bitwig, it converts polyAT to channel pressure by more nefarious means. If you’re holding down C2 with strong pressure and you lightly play E3, the “channel” pressure will suddenly drop very low. Worse, it may get stuck after you release E3. Or it may wobble back and forth rapidly between the different pressure values on the two keys. It’s also likely to get stuck on some non-zero value if you release a key — because polyAT messages are no longer sent at that point, although channel aftertouch = 0 would have been — which is a problem if you want to directly control note volume with pressure.
Enter this stupid workaround in VCV Rack:
- Polyphonic aftertouch and gate data is separated into its individual notes.
- The aftertouch and gate values are run through a VCA, so that when the gate is released, the pressure gets cut off.
- The separate notes are merged back into a polyphonic data stream (it’s a shame poly cables, which are not a real thing in Eurorack, don’t look different in VCV Rack).
- The Poly Min/Max module finds the highest of these resulting levels and outputs that as a monophonic value.
- It’s slewed a bit to smooth out sudden jumps in pressure.
- It’s reassigned to MIDI Mod Wheel messages, because while the VCV plugin can add messages to the MIDI data stream it can’t filter out the existing polyAT messages.
- The actual synth I want to play is assigned next in the Bitwig channel, and it uses the mod wheel as if it were pressure. This hack is acceptable-ish because neither the Microfreak nor Launchpad X has a mod wheel.
This shouldn’t be necessary — Bitwig should be smart enough to do this on its own. But here we are.