[sdiy] MIDI velocity
rsdio at audiobanshee.com
rsdio at audiobanshee.com
Wed Apr 6 20:30:15 CEST 2016
It's difficult to add anything to this thread. I believe that every question has been answered. I have a few comments to add below, still.
On Apr 5, 2016, at 4:43 AM, Richie Burnett <rburnett at richieburnett.co.uk> wrote:
> 1. Is it reasonable to expect that I could use a low-end micro (e.g. PIC) to
> scan a 61-key Fatar velocity sensitive keyboard with sufficient velocity
> resolution to work well? ... For instance the old E510 is quoted as having
> 128us resolution, and it sounds challenging to write a program to poll all
> 61 keys nearly 8000 times a second? ... I couldn't find any
> online examples of PIC based DIY velocity sensitive keyboards, and most
> commercial keyboards seem to have an ASIC taking care of timing the switch
> closures and reporting results to a general purpose micro to form the MIDI packets.
What are some examples of commercial keyboards with ASIC solutions? I recall that the ancient keyboards had dedicated chips, but my impression was that these keyboards actually pre-dated the availability of general purpose processors that became more common later. The middle period of synths seem to all use generic 8-bit processors to directly scan the keyboard. Of course, by the time the DX-7 came out, it was common to make custom chips for any product expected to sell in the millions, most likely to prevent competitors from easily buying off-the-shelf parts and duplicating the firmware. In other words, I don't think that the problem itself requires an ASIC, but I'd be interested to see examples of newish keyboards (80's or later) that actually use them.
All of my (our?) favorite vintage synthesizers were designed with 8-bit processors like the 6800, Z-80, or 8049/8051 running at about 1 MIPS. They usually had a few 8-bit ports and all use a switch matrix for the keyboard. Some of the Technical Service Manuals actually mention the exact scan rate, and it's usually on the order of 1 millisecond. That's for non-velocity-sensitive keyboards, so perhaps the scan rate is higher for velocity. It would be interesting to find a Service Manual for a velocity-sensitive keyboard that actually describes the scan rate. My experience is with really old keyboards, so if anyone has pointers to this information on velocity synths, I'd appreciate it!
If you write your PIC timer interrupts in assembly, you should have no problem trying higher scan rates.
I would recommend using a matrix where the two switches for any given key are on the same column. This will allow the firmware to read both switches simultaneously, and will probably improve the timing accuracy since transitions will be 100% definitive. Of course, you're stuck with the matrix wiring of the key bed that you buy, so unless that is a standard wiring, you're not going to be able to do it this way.
As for the idea of hooking each key to its own GPIO, that approach is counter-productive if you think about the actual firmware. Even with a 32-bit processor, the largest GPIO port that you can read would only be able to deal with 16 keys (velocity needs two switches). Then the firmware would loop through each port and would still need 4 iterations to handle all keys. How is that any different from having 4 columns in a keyboard matrix? Then, if you consider an 8-bit processor instead of a 32-bit ARM, your GPIO ports get smaller and the loop iterations increase to 16. Basically, from a firmware point of view, it's no more efficient to loop through separate GPIO ports than it is to write the column bits and read the same GPIO port on each iteration. I realize that someone already pointed out that standard key beds are already wired for matrix access, but I wanted to illustrate how both approaches require a loop that processes only a subset of keys at a time.
There's also the consideration of wiring between PCBs. Discrete GPIO would require 122 dedicated wires for a 61 keys with velocity, whereas the matrix can be done with 24 wires (16x8) or even 23 (12x11). DIY may not matter, but commercial designs probably want a 24-pin ribbon between boards rather than a 122-pin ribbon!
Another consideration is that even though humans might perceive a chord as if all notes were hit simultaneously, the computer is scanning so fast that it can actually detect each individual key and send out the MIDI message before the next key switch hits. If anyone has timing measurements for chord stabs, that would be very interesting.
> 2. What does the MIDI velocity byte actually represent!? ... I would have thought that there
> should be a reciprocal calculation done somewhere to convert from time to
> velocity. Is this method the commonly accepted way to implement velocity
> sensitivity, or just a compromise because the reciprocal was too difficult
> to do back then? I couldn't find anything in the original MIDI
> specification that describes what the velocity byte should actually
> represent. If it does actually represent time, then that's easier, but it
> sounds wrong.
Velocity is distance over time.
The original MIDI specification says "Interpretation of the Velocity byte is left up to the receiving instrument." If the receiving end is free to interpret the value any way it wants, then there doesn't seem to be much point in having a standard on the sending end.
Reciprocal calculations involve division, which is expensive in terms of instruction time, even with some modern processors (like DSP). Although it's true that many processors have a single-cycle divide instruction, that's not generally true, and certainly wasn't available in the early days.
Since the two switches are at a fixed distance, you can consider the distance to be "1." So, you're correct that it would be a simple reciprocal. I think what you have here is a happy coincidence that affords easy optimization. The desire to have multiple curves pretty much requires a lookup table, at least on simple 8-bit processors. Since you're going to have lookup tables anyway, you might as well incorporate the reciprocal calculation in the lookup, and thereby avoid a multi-cycle division. Otherwise, you'd calculate the reciprocal and then do a lookup anyway. Might as well build in the calculation that's expensive.
> 3. How should a receiving synth set it's voice's volume depending on
> the velocity byte received?
The original MIDI specification says "A value of 64 (0x40) would correspond to a mezzo-forte note and should also be used by device [sic] without velocity sensitivity. Preferably, application of velocity to volume should be an exponential function. This is the suggested default action; note that an instrument may have multiple tables for mapping MIDI velocity to internal velocity response."
Since our perception of sound intensity is relative, and dB is a logarithmic function, I'm pretty sure that their exponential function is intended to map a sensible linear velocity value to a logarithmic sound intensity so that we perceive a direct correlation.
> To add to my confusion one chip that I looked at from Dream semiconductor mentioned a "logarithmic" timing method for measuring note on and note off velocity. Help!!! Is it really just a case of everybody does it differently, and just go with what sounds good, or is there a definitive standard somewhere for how MIDI velocity *should* be implemented?
If you graph 1/x, x^2, x^N, log(x) and ln(x) on the same graph (Apple's Grapher.app makes this quick and easy), you'll note that a lot of the curves have sections that look very similar. If you flip or invert one or the other, you can get pretty much the same curve. Given the 7-bit resolution of velocity and the fact that users may want a few variations, then I don't think it's terribly important what the exact math is for generating the curve. For vintage processors, it would all be tables in memory, rather than actual functions, and those tables might even be hand-calculated or tweaked.
More information about the Synth-diy