Author Topic: How to optimize my preset to reduce CPU usage  (Read 3071 times)

Offline lm3783

  • Newbie
  • *
  • Posts: 5
How to optimize my preset to reduce CPU usage
« on: January 18, 2021, 05:18:42 PM »
Hello,

I'm working on a preset for Novation ReMOTE SL series controller. The major challenge is to display text on the controller screen. I've figured it out and uploaded my half-working preset as attachment. The procedure works as follows.
  • A MIDI CC event starts the whole process (Logical control B1), which is triggered by a Timer feedback.
  • Logical control _collect_act is called to update the left side of the screen, showing the ACT controlled 8 parameters and values. And _collect_volume is used to update the right side of the screen, showing the current 8 track names and volumes.
  • In _collect_act, it calls _collect_each_act 8 times to read 8 parameters. _collect_each_act is used to store the parameter name and value to text buffers.
  • After preparing the text buffers, _display_act is called to send the text to the controller.
  • _collect_volume works in a similar way.

It worked, but Cakewalk became struggling. The CPU usage was 100% on one core.
I have tried the following things to troubleshooting.
  • Setting the timer speed to Slow gives some improvement. Cakewalk now makes short freeze at every second.
  • Disabling the actual screen update (remove _display_act) has no positive effect.
  • Showing only 1 parameter instead of 8 works well, but with more than 2 parameters the lag is sensible.

My guessing is some operations are not supposed to be used too frequently. Has anyone encountered similar problem? I would like to know how to optimize it.

Thanks

Offline azslow3

  • Administrator
  • Hero Member
  • *****
  • Posts: 1679
Re: How to optimize my preset to reduce CPU usage
« Reply #1 on: January 19, 2021, 10:03:15 AM »
Hello,

You are using "advanced" technic with functions, state shifts, etc. right from the beginning. WOW.
To proceed effectively, you just need to apply monitoring concept correctly: http://www.azslow.com/index.php/topic,336.0.html
That is a bit lengthy explanation of that concept, and it may be not good written. Unfortunately there is no other way and once
you understand it, it is not difficult to use.

In short, instead of updating by timer you should update when something is changed, asking AZ Controller to do the check (that
is optimized and proved to work with 1000+ parameter with max rate, without significant CPU load). So E1-E8 should have Value Monitors
(right after "ACT" selection, but can be at the end). And in each monitor you display Value and Name (to not update Name till required,
use Function "Mon. par. not changed").

To make everything "perfect", you will need carefully set all monitors priority (f.e. Initialization is 0, Mode changes 1, Value changes 2).
And getting parameter name/value for not currently existing parameter fails, "Last Action: Fail" condition can be used to set corresponding text to ""/"---"
is such case.

X-Touch Mini preset is using all that technic intensively. But I can write an example in your preset.



Offline lm3783

  • Newbie
  • *
  • Posts: 5
Re: How to optimize my preset to reduce CPU usage
« Reply #2 on: January 19, 2021, 01:18:04 PM »
Thank you for the quick reply!

The bundled Mackie plugin is also laggy with this controller in HUI mode, while AZController's HUI preset works fine. Maybe it's also due to different implementations. I'll try your suggested way and see what happens.

btw, AZController is AWESOME. Never thought this could be achieved without some sort of script language.

Offline azslow3

  • Administrator
  • Hero Member
  • *****
  • Posts: 1679
Re: How to optimize my preset to reduce CPU usage
« Reply #3 on: January 19, 2021, 05:05:18 PM »
Mackie plug-in works with way more parameters then HUIv2 preset and it some operations are not optimized as in AZ Controller. But it is reasonably written, I am surprised you get lag from it.

AZ Controller engine is an interpreter. So it is based on script language. GUI is "compiling"/"de-compiling" special byte code on the fly, so there is no text representation which computer can parse (only one for humans, in the "Options/Export" Tab). Technically byte code/interpretation has roots in FORTH, but a possibility of complicated preset implemented using ridiculously tiny set of logical operations comes directly from computing theories of XX century  ;)   

Offline lm3783

  • Newbie
  • *
  • Posts: 5
Re: How to optimize my preset to reduce CPU usage
« Reply #4 on: January 21, 2021, 05:18:31 PM »
The result seems good. I add individual Value Monitor to each control and use feedback to update the display. No significant CPU load is observed.
The attachment is a quick preview that has some basic controls implemented. After more polishing I'll post the final preset and the readme file.

One last question: I need to send some deinitialization commands to the controller when Cakewalk is closing. Which monitor should I use?

Offline azslow3

  • Administrator
  • Hero Member
  • *****
  • Posts: 1679
Re: How to optimize my preset to reduce CPU usage
« Reply #5 on: January 22, 2021, 11:01:40 AM »
Monitoring is correct now. Just small simplification tip for value monitors:
you can move update value to the top and then use "Mon. par. not changed" with "Final" flag. After then update the name. This way you don't need set state and use condition.

I see you have "Priority 0" for Value Monitors. That can produce inperfections in case of value depends on other monitors (f.e. you want to auto switch to buses or on context) , better set it to 2 or 3. Also put "Device: Online" condition for displaying monitors, so they don't update device before you initialize it and after you cleared it.

Initialization and De-initialization can be done in State Monitor "Context" (priority 0, so before value monitors). "NoProject" is triggered on Cakewalk exist (plug-in unload). It is also called when you close project without closing Cakewalk, but probably de-initialization is fine in that case to (and re-initialization once another project is opened). Note that this monitor will be triggered also on in-project context changes, you will need to use a combination of Context and (your own) Device sets for decision.
One approach, explicitly put "do nothing" conditions on the beginning, so:
Context:NoProject Device:Offline - Undefined *
Context:Plugin Device:Online - Undefined *
Context:Track Device:Online - Undefined*
Context:Console Device:Online -Undefined *

Then you know Device state should change, so:
Set State Device <next> <loop>

Followed by conditional (de-)initialization:
Device: Online <send initialization>
Device: Offline <send de-initialization>
 
With such sequence, you can f.e. add auto-mode switch later (f.e. Context:Plugin Set State Mode ACT *, Context:Track Set State Mode Mix *, etc.).

NOTE: state monitors are triggered during startup and on global Monitor Reset.

Offline azslow3

  • Administrator
  • Hero Member
  • *****
  • Posts: 1679
Re: How to optimize my preset to reduce CPU usage
« Reply #6 on: January 22, 2021, 11:07:15 AM »
I forgot one more note...
Last selected parameter is remembered (selected in MIDI input mode, monitors are not changing it). So if you have Value action but conditions prevent parameter selection (f.e. as for all but the first fader in all but one fader mode in your current preset), last controlled parameter will be changed. That can be confusing. 

Offline lm3783

  • Newbie
  • *
  • Posts: 5
Re: How to optimize my preset to reduce CPU usage
« Reply #7 on: January 24, 2021, 07:38:27 AM »
Quote
you can move update value to the top and then use "Mon. par. not changed" with "Final" flag. After then update the name. This way you don't need set state and use condition.
For some unknown reason, if I want to send an empty string to the controller to clear the display, it must be firstly sent to the upper line (which shows the name) then to the lower line (which shows the value). To maintain the order I had to stick to the current way.

Quote
Initialization and De-initialization can be done in State Monitor "Context" (priority 0, so before value monitors). "NoProject" is triggered on Cakewalk exist (plug-in unload). It is also called when you close project without closing Cakewalk, but probably de-initialization is fine in that case to (and re-initialization once another project is opened). Note that this monitor will be triggered also on in-project context changes, you will need to use a combination of Context and (your own) Device sets for decision.
If I use "initial" flag to send initialization commands as in current preset, when a project is opened in Cakewalk, all the value monitors will be triggered and the display will be updated. However if I put them in Context monitor feedback, the display will be updated prior to the initialization (although I've added the device online condition and set priorities) and will be cleared.

To make things simple, now initialization is still done by "initial" flag, and Context monitor is used to do time insensitive things.

The preset is almost done. I'll put it in the following post.

Offline lm3783

  • Newbie
  • *
  • Posts: 5
Novation ReMOTE SL Preset
« Reply #8 on: January 24, 2021, 08:42:57 AM »
Supported controller
  • Controllers that should work: ReMOTE 25/49/61/ZeRO SL
  • Controllers that might work but not tested: ReMOTE 25/49/61/ZeRO SL MKII (*)
  • Controllers that will not work: ReMOTE (origin series), ReMOTE SL Compact
(*) LED indicators and touch sensing not impmented.

Installation
  • Check if the controller has the latest firmware (V4.2.02). If not, download and install firmware from Novation website.
  • Check if the controller has the Ableton Live Automap template. If not, download and install factory templates from Novation website.
  • Download and install AZ Controller.
  • Connect and turn on the controller.
  • Open Cakewalk. In Preferences--MIDI--Devices, select "2-ReMOTE SL" and "MIDIIN(OUT)2(2-ReMOTE SL)" as both input and output. Apply the change.
  • In Preferences--MIDI--Control Surfaces, add an "AZ Controller" with input port set to "MIDIIN2(2-ReMOTE SL)" and output port set to "MIDIOUT2(2-ReMOTE SL)". Close the dialog.
  • In Utilities--Cakewalk Plugin Manager, import the attached preset file to Control Surfaces--AZ Controller.
  • In Utilities--AZ Controller, select ReMOTE_SL preset.
  • The controller will automatically switch to the Ableton Live Automap template and become functional.

Usage
See the attached pdf for a brief description.

How this was made
Spoiler for Hiden:
Ableton has made support to a number of controllers. The controller interface was implemented in Python and the code could be studied (https://structure-void.com/ableton-live-midi-remote-scripts/). With such knowledge the proprietary communication protocols of various controllers could be revealed. Hopefully more controllers could be adapted for Cakewalk by this means.
« Last Edit: January 24, 2021, 09:06:30 AM by lm3783 »

Offline azslow3

  • Administrator
  • Hero Member
  • *****
  • Posts: 1679
Re: How to optimize my preset to reduce CPU usage
« Reply #9 on: January 24, 2021, 09:10:32 PM »
Thanks for sharing! Please don't be surprise the preset post will "disappear", I will move it to "Presets" board later.

I have understood with upper/lower rows, make sense and your solution is good for such case.

With initialization, it can be that controller needs some time after initialization. So "initial" is good approach in case it works stable (there is sufficient time between initial and updates once project is loaded). Alternatively, "Online" should be set with delay after initialization SysEx is set (f.e. in separate Timer <Once>, triggered from context with predictable delay set).