Page 1 of 1

Adroit Custom - more details

Posted: Mon May 29, 2023 3:00 pm
by ColinP
====
Edited to add: For anyone stumbling across this out of the blue it follows on from a previous thread called What if? that explains the context.

viewtopic.php?t=2882

This thread has become a sort of thinking out loud blog on the development of Adroit Custom so might not be of interest to many people especially given some of the minute technical detail.
====


Reflection.png
Reflection.png (352.35 KiB) Viewed 8332 times

This shows a ittle test patch with Adroit Custom doing some reflection.

The focus here is the single Custom Panel module labelled TEST. In a practical application the other modules would be off-screen and not visible.

It took ten mouse clicks to add the two knobs, two scopes and the LED.

A few seconds later the top knob was labelled KNOB 1 and had a CV mapping to output 1 of the Custom IO module. Similarly for the knob below. The two scopes took a few more clicks to configure. Finally another two clicks were required to make the LED monitor Input A3.

The controls on the Custom Panel (in this case just the two knobs) have up to four simultaneously available mappings that can perform remote control on other module's controls, send CV to a Custom IO's CV outputs or send MIDI messages such as CC to a Custom IO module. Here they are just outputting CVs for test purposes.

The Custom IO module defaults to Bank A but one could add three more modules and switch them to Banks B, C and D so in total Custom Panels can access 32 CV or audio inputs, 32 CV outputs and four MIDI outputs.

Each MIDI output supports 16 channels and 128 different CC's as you'd expect so that's 64 channels of MIDI and 8,192 CC destinations for anyone who has a warehouse full of outboard. In a more practical realm it means you can simplify MIDI configuratiion - say always sending MIDI CCs on channel 1 while still controlling four different hardware or VST synths. Or it may be that you don't need MIDI at all.

In this patch Output A1 is connected to Input A1, Output A2 is wired to Input A2 and Input A3 receives the triangular output from the second Mini LFO. So we can see the CV mapped outputs from KNOB 1 and KNOB 2 on the scopes while the LED at the bottom of the TEST module throbs away in time with the LFO.

The Custom Control module looks after control automation. The keypad with 16 buttons enables you to switch between 16 different scenes. Each control on every Custom Panel has 16 memories of its settings so a single button press on the keypad can change every single control in a large interface if required. A mini Scene Selection keypad is also one of the items that you can add to a Custom Panel.

The MORPH SPEED control enables you to set how quickly the scenes change (anything from 0 to 25 seconds). So when selecting a new scene the knobs and sliders can move smoothly from one setting to another.

As mentioned the two scopes show the mapped CV outputs from KNOB 1 and KNOB 2 varying over time. If MORPH SPEED was set full CCW then these graphs would be stepped.

Here scenes are being changed by the upper Mini LFO sending a regular pulse to the NEXT input of the Custom Control module.

The GATE OUTPUTS beneath the keypad reflect which of the 16 scenes is currently selected. In this instance the 9th output is wired to the RESET input so that the sequencing automatically resets on completion of the 8th scene but you can use these gate outputs to control things like switch modules so that each scene can have different inter-module wiring.

In the screen grab we are transitioning from Scene 2 to Scene 3 . The Custom Panel knobs show their Scene 3 settings and the yellow arcs show the difference at this point in time between these settings and the morphing settings. As the transition progresses these arcs shrink and eventually disappear when the morphing catches up to the knob settings. However you can still adjust the knob settings mid transition and the interpolation is recalculated. This is particularly useful when the morphing is slow.

Finally we have the Custom Look module. This configures the visual appearance of itself and the other Custom modules but its main purpose is to allow you to skin the Custom Panel modules so that they look unique. Here no background image is loaded so the Custom Panel module uses the same three-color gradient fill as the other modules.

This was supposed to be a brief post! Still it will fold into the documentation. Hopefully my ramblings have been of interest to some of you.

Things may change quite a bit from what's shown here and the ETA is difficult to judge as there are several other aspects of Custom that I've not revealed yet and they need considerable work. But I'm hoping to launch before the end of June.

Re: Adroit Custom - more details

Posted: Mon May 29, 2023 4:53 pm
by Steve W
Ingenious. Glad to see you are having success with these tests. Thanks for sharing!

Re: Adroit Custom - more details

Posted: Tue May 30, 2023 12:06 pm
by ColinP
I could just tidy things up a little and release the modules as they stand but I've realised there is much more potential to explore.

Doing tests has been important for various reasons. One was that I really wanted to master scene modulation. Achieving this with CPU efficiency and without user confusion was a challenge.

Morphing between scenes can be done at high speed. So for instance you could send an envelope signal with a very fast attack and a slow decay into the CV IN of Custom Control, set the @0V control to scene 4 and the @5V control to scene 1 and then each note played uses scene 1 for the attack then smoothly morphs through scene 2 and 3 ending on scene 4. The same envelope CV can control the morphing speed (with its attenuvertor set so that higher voltages result in faster morphing) so that the attack transition to scene 1 happens instantly while the morphing between the other scenes takes progressively longer as the note dies away.

At the moment the morphing between scenes is always linear - the slopes on the scopes in the example above are all straight lines. This means that when morphing from one scene to another the knobs and sliders instantly accelerate, travel at a constant speed then instantly decelerate. This gives things a slightly robotic feel so I'm now working on improving the interpolation so that the motion can accelerate and decelerate in the same way a human being would do it (albeit one with dozens of hands). So in the example above the traces on the scopes would be gentle curves rather than straight lines.

I'm also lookng at resonant morphing as an option so that controls overshoot then settle down with variable damping. The goal being a knob on the Custom Control module probably called MORPHING LAW that gives robotic linear interpolation when fully CCW, smooth sigmoid interpolation at 12 o'clock and "tipsy" behaviour when fully CW.

You can also use slow speed scene modulation to achieve control automation by cycling through the 16 scenes in a sequence that lasts say 4 bars (giving us one beat resolution in 4/4) When you turn a knob or move a slider its setting for the currently selected scene/beat is overridden and the new setting is played back during subsequent cycles. So you can bit by bit adjust knobs/sliders over time to end up with complex but repeatable automation.

Re: Adroit Custom - more details

Posted: Wed May 31, 2023 6:25 am
by seal58
Hello Colin,

Respect! That's a very creative project.

Indeed accelerated and decelerated morphing will be a better solution than only linear morphing, because contour at start and end points of one morphing process will be more smoothly.

I wish you an accessful work on this project.

Roland

Re: Adroit Custom - more details

Posted: Wed May 31, 2023 9:56 am
by ColinP
seal58 wrote: Wed May 31, 2023 6:25 am Indeed accelerated and decelerated morphing will be a better solution than only linear morphing, because contour at start and end points of one morphing process will be more smoothly.
Thanks for the kind words Roland.

I've been thinking more about the morphing law and (putting fancy resonance to one side for the moment) have realised that the provision of linear and smoothed interpolation options isn't really sufficient.

Smoothed interpolation (using my old friemd -2x^3 + 3x^2) works great for point to point morphing. So if we morph from one scene to another the knobs and sliders accelerate from their old positions up to top speed then smoothly decelerate as they approach their destination settings but this doesn't produce smooth curves when doing sequenced morphing (1 to 2 to 3 etc). Instead it produces a sothened staircase - as between each scene the knobs/sliders speed up mid-way but slow down to zero as they pass through the sample points. So it's actually worse than linear interpolation as the speed cycles up and down giving an undesirable throbbing effect. Something you may well have been hinting at in your comment.

So when doing sequenced / through value rather than point to pont morphing we ideally want some kind of polynomial interpolation. But the code can't see into the future. The next morph could be to any scene and happen at any time depending on the CV input or what button the user presses. So linear interpolation is the only reliable method.

However in many circumstances the scene morphing will progress in a predictable fashion - say if we cycle through scenes at a steady four scenes per bar as per my previous automation example. In this instance the code might indeed be able to predict the future as each knob/slider has its next 15 values already in its memory. In effect ever knob and slider has it's own channel in a giant 16 step sequencer and the code can look ahead and see these "future" values.

The user can of course vary the values on the fly but there's nothing we can do about that. The other problem is that the cycle might not use all 16 scenes - the sequence could reset after eight for instance in which case the next scene after 8 would be 1 rather than 9. But the code could remember when the end of cycle occured last time and predict that scene 8 would most likely be followed by 1.

So I'm now thinking of offering the following options 1) linear as a reliable general-purpose fallback, 2) sigmoid for point to point morphing and 3) quadratic with EOC memory for sequenced morphing.

I'll probably drop resonant morphing, continuous variability between laws and per control choice and just have a simple three way switch on Custom Control as otherwise it might all get a bit too complicated.

Re: Adroit Custom - more details

Posted: Wed May 31, 2023 5:50 pm
by ColinP
Yeah, I really like the ergonomics of a simple three position switch with straighforward practical labels...

CC22.png
CC22.png (137.73 KiB) Viewed 8274 times

Re: Adroit Custom - more details

Posted: Thu Jun 01, 2023 5:35 am
by UrbanCyborg
For through-morphing you could use a cubic, say, like a Bézier curve; that would give you total control over how you approach and quit a point, as well as continuity of derivatives. Another plus would be that you could extend it to higher dimensions, as in Bézier patches. Of course, there's a bit of computational complexity, but I believe there are ways of approximating Béziers. Been a long time since I studied that stuff.

Reid

Re: Adroit Custom - more details

Posted: Thu Jun 01, 2023 11:36 am
by ColinP
You are probably right Reid, that cubic may be the way to go rather than quadratic. Everything is still linear at the moment but I'll be doing the upgrade over the next day or so. The interpolation is already modular so it'll be easy to plug in whatever algorithm seems most appropriate.

It's actually difficult to judge how high a degree of interpolation might be warranted as so much depends on what the morphing is modulating. There are also multiple sample rates involved as there are three pathways - remote control based on SetValue() events , MIDI CC messages and finally CV at 48k.

Most client modules being driven by Custom Panel modules remotely controlling their knobs/sliders will be written on the expectation that the SetValue() events they receive are being generated by mouse motion and they will be slew limiting the modulation using the stock SmoothValue mechanism so the end result isn't going to be high fidelty tracking or capable of audio rate response. VM's event handling struggles with high throughput anyway so I'm varying the event rate on a control by control basis, only sending an update when a 0.5% threshold is crossed. So a rare case morrph of a knob over its entire range in one second will generate 200 SetValue() events rather than 48,000. I'll tweak this during beta as it may be that I can shave more off.

MIDI CC is only 7 bit and who knows what rate as it depends on whether it's sent internally for instance to a MIDI aware VM module or a VST via a Plugin Host or down a physical low-baud wire in the hardware domain.

These limitations are why 32 direct CV outputs are available as these can run at 64 bits and 48k to bypass the restrictions where necessary.

Interpolation efficiency is something to look as I'm doing raw interpolation at 48k to simplify the issues implied above and I'm working on the basis that there will be a ceiling of about 50 mappings in play so that's nearly two and a half million interpolations per second when running flat out. But the Granular Synth's engine runs about 10 times faster than that so I'm not too concerned.

The main problem I'm having is repainting the interface during mporphing. The notion is that client knobs/sliders will be offscreen so the cost is in the repainting of Custom Panel ones.

When not morphing everything is event driven and CPU loads are in the 1% to 2% region but when using 10 Custom Panels each with 5 knobs morphing continuously, load goes up to about 8% on my laptop which is much higher than I would like. Redrawing 50 knobs at 20 FPS isn't taxing the GPU much but the handshaking involved for the CPU is severe. VM's just not designed to cope with that kind of thing. I'd like to bypass things but there are critical hooks missing. Chiefly the DAW automation is opaque and I'm pretty sure a lot of people expect to be able to automate knobs from their DAW.

The only fix I have at the moment is adding a Custom Look option to disable visual feedback of morphing. This could be remotely controlled from a Custom Panel button so users of low-end machines could engage an "ECO" button on a Custom interface to drastically improve efficiency.

===

Hmmm. I just went back to look at some of the stress testing I did on N-Step and the knob repainting overhead I'm getting now is much worse than I'd expect. So the way I'm drawing the morphing arcs (shown in yellow in the acreen shot at the top) is probably the real problem. Maybe the canvas invalidtion is messing up and making the knobs repaint twice or something daft? I'll postpone the interpolation upgrade until I've investigated further...

Yup a quick test revealled that the CPU jumps up by about 500% when drawing the arcs so something is going seriously wrong there! :oops:

Re: Adroit Custom - more details

Posted: Fri Jun 02, 2023 11:49 am
by ColinP
An update for anyone who hasn't lost the will to live after reading this far...

The problem wasn't the actual drawing of the arcs because I could bypass that code and it didn't make any real difference. Rather it was the invaildation of the canvases that contain the arcs. These are behind the knobs in the z-order so invalidating them also invalidated the canvases that the knobs are drawn on. Blindling obvious really but I somehow managed to think this wouldn't happen. I can be really stupid sometimes. So I was thinking that the knobs were only being redrawn when the scene change occurred (or a knob was changed by the user) but in fact they were being repainted every time the arcs where updated.

This has made me rethink how to do this as there's no longer any real advantage in drawing the arcs. I might as well animate the knobs instead. I initially thought this a bad idea as users altering the knob mid-morph (if the knobs were showing the interpolated rather than target setting) seemed wrong but I now see that the user action can simply update the "real" target value to match the interpolated value. Although the real value would jump it wouldn't appear to do so to the user, instead it would seem that by touching the motorized knob or slider they had put a brake on its motion. Which is completely intuitive.

By the way Reid I also spent a couple of hours refreshing my understanding of curves and I think cubic Hermite spline interpolation is the way to go for morphing repeating sequences.

Re: Adroit Custom - more details

Posted: Sun Jun 04, 2023 9:41 pm
by ColinP
Here's what the cubic spline interpolation looks like...


cubic.png
cubic.png (8.22 KiB) Viewed 8179 times

The result is a lot smoother than linear and ihe CPU hit doesn't look too bad.