This is almost for sure a question for @martin or maybe @moss and no one else, but I’d be happy to know if anyone else has any experience with this as well…
I tend to use a lot of automated parameters, so I’m constantly sending updates to MOST of the controls that the Electra exposes. In addition, I’m using custom formatters on almost all controls, because most parameters I’m controlling don’t easily match the numerical range possibilities of the Electra (think: parameters with non-linear ranges, like frequency controls that are exponential).
I’ve been wondering whether it’s better for me to switch directly to the “Override text value” sysex command instead of custom formatters, so I can eliminate both the complexity and cost of the formatters. But a reasonable-worst-case scenario for this would still be sending ~36 parameters value and string updates at 20-30 updates per second. I guess my assumption here would be: the sysex message just copies a string into memory, whereas formatters have to do an entire Lua invocation, which is almost surely more expensive?
Before I go too far down the rabbithole of refactoring this - does this sound like a plausible performance improvement? Are there other obvious things to improve performance of the Electra in mega-update scenarios like this?
I only use sysex updates but only for values that need to be updated. Sending updates for all visible parameters all the time, could be an issue on the MkI.
Lua is not that expensive. The interpreter and the context are initalized when the preset is loaded. When formatter is called, the overhead is only about binding parameters and executing the particular call. Of course the complexity of the formatter plays role. Sysex update is what you said, it just overwrites the string buffer. So definitely less expensive.
In some circumstances a high number of individual control repaints can slow things down. To prevent that one can call
window.stop(), do all the work, and then call
window.resume(). This will result in single page repaint. It is worth using if multiple actions (visibility, colour, position, text) changes are done to each control. If you just call formatter, it should be fine - a formatter call will cause single repaint of the control.
I’ve tended to use code in format routines for things like panning (typically -50L … 0 … +50R) where the parameter range is 0-100. For things like levels, I might see the gear needing -85 dB to 0 and sometimes full and off enter the picture.
For those things, I tend to use static arrays and map the values (0-80) into the array with the formatting routine handling the text changes for off/full.
The more things I can keep static, the better I can manage overall performance/memory usage.
That being said, I’ve blown past the mk I limits in a couple presets already just because I wanted to display/use param values that would be familiar to a user of the hardware. I don’t generally use the mapping lists just because.
I’m old and I code like someone that learned assembly and C. lol
Even on the mkII, I haven’t been able to send parameter value updates (no text, just 14 bit values) to 32 controls at a rate of 30 updates per second without causing a slowdowns in the range of several seconds on the device.
Another thing to note regarding window.stop() and window.resume(): while it makes visual updates on the E1 appear smoother, you’ll get more uneven frame times in bidirectional scenarios (e.g. E1 sending updates to a client like a DAW and receiving response messages updating parameter texts on the E1). So twisting a knob will feel more stuttery. I improved this by applying window.stop() and window.resume() only on certain kind of actions like updating a parameter name. This way, normal parameter value updates would be painted instantly. I haven’t tested this with lots of parameters being automated, so more tweaks might be necessary.
I’ve been using the stop()/resume() in a more controlled manner, but I have seen some of the things you mentioned.
For me, I use it when I’m restructuring various controls for an effects editor. Depending on what algorithm is being used in the unit I need to change which controls are shown/hidden, adjust some ranges and names and stuff like that.
So what happens is when the sysex dump is being pulled back and parsed, I adjust all my controls at that time.
Then, when the user is actually using/editing things I very tightly bound the few areas I need to to minimize the stutter.
That’s what I settled with, too! I directly apply changes on parameter adjust messages and on value text messages and use the stop/resume mechanic when receiving a parameter name change, a control visibility change or a parameter range change.
On the topic of sending parameter value updates for multiple controls at 30Hz, is there room for improvement on the E1 or is this part already optimized as much as possible?
One thing I found early on (depending on how complex your preset is) is that it was faster to use multiple pages and switch between them versus trying to update lots of controls on a single page.
AFAIK, the MIDI bandwidth is what it is. Obviously try to optimize the messages and such, but there is a limit.
Also, I try to separate performance controls/pages from editing pages to minimize unnecessary traffic.
One of the reasons why the upcoming release is taking longer is exactly this. There is room for improvement indeed. I am trying to optimize performance for this use case. The E1 firmware was originally designed to communicate with hardware synthesizers and therefore the focus was on processing large sysex messages and things like that. With the DAW integrations, you need complete opposite - large amounts of CCs and Lua calls.
The upcoming release will be quite big in this regard, mostly addresing feature requests expressed here. setSlot() supporting moving things between pages, programmatic changes of Message, performance improvements for dynamic changes, and I would like to include a programatic access to Overlay lists.