I’ve been thinking recently about different control enhancements that might be possible to improve modules.
One idea I am trying to come up with a solution for, is knob (or sliders and other controls) detents.
If you don’t know what this is, it is difficult to describe but IRL some physical knobs have a certain spot (or multiple spots) where the knob sort of soft-clicks or latches into place. Note, this is not the same as snap because the values either side are still selectable, its just requires more precision to get to them.
The pitch knobs of the 4ms Stereo Triggered Sampler have a detent at 12 o’clock for example, this makes it very easy to reset the samples pitch.
Obviously in VCV you can right click a control and enter the exact value you want, but a functional detent would make setting certain values much faster, especially during a performance. (For example, an attenuvertor that has detents at -0.5, 0 and 0.5 would be nice I think)
I haven’t attempted to code this yet, just contemplating it.
I was thinking something along the lines of overriding the onDragMove of Knob and using some kind of dynamic scale for the mouse movement, or possibly since Knob already has members for speed and forceLinear perhaps this wouldn’t be too hard to implement just modifying those values.
Yes that is definitely a good suggestion, although it doesn’t feel as satisfying to me, and is possibly not quite as useful in a performance situation, since you would still need the keyboard…
But for sure its on the todo list as a backup if I can’t get it to work another way.
Although, this has now got me thinking, maybe a knob system where the user can create their own custom snap points would be good, or possibly it could even be a module that allows you to apply custom snap points to any control on any other module… this needs some deeper thought
I’ve been planting to implement this in the Morph knob on my Algomorph modules, because I think that snapping to the nearest algorithm makes sense at the knob level there, and so I was looking at this code recently:
In Mutable Instruments hardware, knob detentes are coded at the software level. For example, this bit is for the Deja Vu knob on the Marbles module. The knob has a detente around 12 o’clock. This detente invokes a lock that has some hysteresis, so the “detente exits” are further from center than the “dentente entrances”.
I’m not sure if it makes more sense in VCV to code this above the parameter at the UI layer like you suggest, or to do it “in DSP” as the Audible Instruments plugin is currently doing. I think it’s an interesting question and I’m curious what others think.
Note: 1.06382978723 = 0.5 / 0.47 so the formula here is “if the knob is outside of the detente (exits), rescale the knob’s value such that the dead zone does not exist.”
I guess because MI is used as an external lib, doing the detents is only possible in DSP? And does that mean that the detents are not represented in the actual position of the knob, only the value?
Seems plausible to use this type of code but on the UI side (there doesn’t seem to be any reason why it needs to be on the DSP side, so it probably shouldn’t be) of a module to get a detent that is represented by the knob position as well. I’ll give it a try next time I am fussing with my plugins…
It works this way in the original hardware too, so it’s not a quirk of the Audible Instruments port if that’s what you mean. I imagine the primary benefit is cost savings in hardware production, but also it does give you flexibility in creating knob behavior “however you like” as well as changing behavior via software updates.
One consideration that comes to mind for me is VCV’s parameter mapping. I like the thought that someone MIDI-mapping a knob on one of my modules will have the detente behavior preserved in their MIDI controller.
Rather doing it in process() or at the widget/mouse level, I’m thinking it might be ideal for something like the above Mutable code to wind up in a custom subclass of ParamQuantity. But I don’t yet know enough about the parameter mapping code to understand how to be sure that mapped parameters won’t bypass the detente. Maybe this is a good feature request for the Rack API?
Your detents could be considered a form of quantization. In a physical knob, you need greater physical force to move out of the detent. The UI equivalent would be some nonlinear change in mouse position, instead of the normal uniform linear relationship between change in mouse position and change in parameter. (ignoring for the moment that some HID devices now support pressure, which would be another way of simulating detents)
An alternative UI could be simply that you quantize the value to increments when a modifier key is held (or the reverse). This would probably be much easier to learn and use (at the expense of some unquantifiable “feel”
I would try a custom knob that has an intermittent value that works like normal knobs then make a function that maps the detents from that to the parameter value. So basically when the knob hits the detent it holds that value while dragging until you’ve dragged far enough. The think that is missing will be the feedback. Maybe you can play a small click sound or shake it pulse the knob visually. I think getting an analog for that feedback is critical.