nOb controller apparently available this instant (this is not a drill)

Seems like to “close the loop” someone should submit a standard for VCV to along with the other ones? Admittedly this will only be faced by devs who process MIDI… but maybe there will be more ways to do this in the future.

My guess is that it’ll serve as a reference implementation of the relevant part of MPE+ (a little confusing that it lives there, since MPE and 14-bit control are orthogonal)…

Unless dissuaded, I intend to do my long-ago-proposed whistle-stop tour of the VCV codebase once V2 is out, and I’ll definitely write up how the 14-bit implementation works which, if not a standard, would at least serve as a prose citation rather than a code excerpt…

2 Likes

My implementation does need both messages before proceeding, no matter which order they arrive. This might not work in every case, but well, we’ll see what happens when released to the VCV Library.

1 Like

I’m going to guess that what will happen is that @gc3 will try to make it glitch, and let you know the results. :wink:

First chance I get :slight_smile:

go get it out of git and try it now!!!

1 Like

Parachuting back in for a moment to say that I finally had a chance to test it and v1-dev of @stoermelder MIDI-CAT works like a treat with 14-bit mode on my Faderfox UC4.

To make this concrete using real-world knobs and scaling, plus factory settings:

With MIDI-CAT mapping the FREQ knob of Rack VCO-2, I can tune to 440.04Hz and can get an 0.17Hz change up or down (i.e. to 440.21 or 439.87). In 7-bit mode the closest I can get to A4 is 438.2Hz and the next values up and down are 460.27 (+22.07) and (417.2) (-22), which I’d describe as a flat A# and a sharp Ab, and obviously a big audible jump. To be clear, this is the interaction of VCO-2’s knob scaling and MIDI-CAT’s mapping, not anything specific to the hardware or the 14-bit protocol, but I think it’s not a bad starting benchmark.

Some quick points:

  1. The UC4 has endless encoders, so it should be possible to do about as well with, say, MIDI-STEP, PILE and some fancy slew and scaling to handle knob acceleration; I’ll test this. (Basically, some version of MIDI-STEP and PILE is what’s running on the UC4 firmware anyway, and the question is whether it’s polling at an increased rate and, if so, whether that makes a practical difference);
  2. Slew limiting is still important to avoid audible glissandi (that is, to make glissandi into portamenti) because it’s not as though the HW is outputting anything close to the 14-bit physically traversed values in between the start and end knob positions. In practice, small slew values make changes feel highly responsive and smooth to my ear.
  3. Because (per @stoermelder’s comment above) MIDI-CAT needs a new MSB and LSB message before updating, switching the HW to 7-bit mode without informing MIDI-CAT will, as expected, stop all updates for that CC. The workarounds above might allow auto-switching back to 7-bit using either the timeout or the eat-one method, but there’s a certain amount of “Doctor, it hurts when I do this”; “Then don’t do that!” here.
  4. There are a few quality of life thoughts I might have about mapping and mode changes, but I’ll move those into a separate thread once I’ve experimented a bit more.

The upshot is that high-quality 14-bit MIDI control is available in Rack V1 thanks to @stoermelder and if you’re MIDI-mapping pitch-related knobs (in particular) with MIDI-CAT and aren’t quantizing anyway you should definitely try to use 14-bit hardware unless you like randomly sharp flats and randomly flat sharps.

I will, of course, compare this to the nOb as soon as it arrives!

3 Likes

My cheat for this sort of thing was far more evil. I created a thread from Rack that can mash floats fed via a FIFO into an array that’s globally visible, and I made a simple plug that looks at eight consecutive values and clamps normal floats (-12V, 12V), sends denormals to 0V, and everything else (infs and nans) generates a trigger. The message is a frame char, eight bytes of base64, and a newline. The data decodes to an index uint16_t and a float value. So for the cost of some kludgery, I have comms a lot lighter weight than OSC. I have similar hacks for fsthost (WINE vst2 support), jalv (lv2 standalone), and zynaddsubfx. All I need to drive this is something that reads hardware input, and maps to a float value appropriately.

Neat! Interested to see where you go with this. I haven’t done much with OSC, but am curious to know what problem the additional overhead was creating (or was expected to create). Are you planning HW that has a lot of controllers updating simultaneously at very high speed, and/or are you operating in a restricted environment?

Having spent some time reading about the pitfalls of the MIDI 1.0 standard when using 14 bit CC’s, I decided to implement 3 methods to see what the differences are, and how they translate in use. I have also looked the the Core module, MIDI-CC, where smoothing filters are used. I have used the same filter but added a slider to the context menu to adjust the response, where the original module uses tau = 1/30 = 0.03333333 seconds.

The methods used are: a. MIDI 1.0, when MSB is set LSB = 0. b. When MSB or LSB is recieved, the output is updated, with no zeroing or waiting c. When MSB is updated, LSB is waited upon before updaing all 14bit, LSB are updated with no waiting.

With the smoothing filter set at 0.033333, to match MIDI-CC the scope is showing no noticable glitches, however this changes when the response time of the filter is reduced to the minimum the diffence in the three methods becomes apparent.

a. downward glitches become apparent

b. upward glitches

c. I am yet to see a glitch.

Here is a video showing the differences. My tests have all been using done on a homemade controller consisting of a pi pico, a couple of multiplexers, and some trimmers. It would be very helpful if others could test also to confim the results, but I have been very impressed with the improvements. I have been able to dial in CV values with an accuracy of 0.002V, and tune VCO’s better than I can tune a guitar with a clip-on tuner.

In the video, I have two feeds to the scope, both from the same controller, 7 bit and 14 bit, even though the hardware is at best 12 bit, but more like 9 bit with filtering. The scope is set to 0.25V/div so only covers the range 0 - 1v to be able to clearly see the difference.

The code can be found at https://github.com/StudioSixPlusOne/rack-modules/blob/Midi-cc-14/src/modules/Zilah.cpp

Windows and Linux build can be found: Release Zilah, · StudioSixPlusOne/rack-modules · GitHub

1 Like

No. More that I’m pretty agressive about conserving resources. It’s sort of a hang over from my PDP-11 / RT-11 and Z80 / CP/M days.

1 Like

ah, an example of Knuth’s law in action?

1 Like

Z80, thats where I started in the 80’s, I had a choice, Amstrad Basic, or Assembly, Now you can get a microcontroller that is more powerful for the price of a coffee.

1 Like

I was there, too. 6502-b. A lot of stuff mattered then.

3 Likes

Nice, @Curlymorphic! I’ll give this a try with the Faderfox as well. Because that uses endless encoders and tracks acceleration (or the lack thereof) it can increment by a single bit in the LSB (confirmed via reading the CC messages), so I’m expecting 0.00061V precision over 0V to +10V.

Now we’ve got a 14-bit knob driver and a CV option! 14-bit makes such a huge difference for sensitive params. This is great.

BTW, it strikes me that the (minor) gotcha for your option C (versus the @stoermelder MIDI-CAT wait-for-both method) is that if the user starts sending the +32 CC by accident (say, from another hardware element or a merged controller) it’ll wiggle the 14-bit output. But this is clear user error and arguably not something you’d need to account for. It also wouldn’t work with a hypothetical LSB-then-MSB (≈ little-endian) 14-bit controller, but I don’t know if any of those exist (and, of course, it would work with a hypothetical efficiency-minded controller that only sends the LSB if the MSB doesn’t change, although I sincerely hope that none of those exist–yikes!)

1 Like

No. It’s more a matter that if I don’t spend it in one place, it can get spent in other ways.

Better to have and not need than the converse.

In the case of OSC, there are dictionary lookups for a parameter path per change. I’d rather use an index. I’d rather use the CPU for signal processing than fluffery. Protocols with repeated name lookups give me the irrits.