Proper MIDI automation of controls across multiple MIDI channels?
-
If the MIDI automation system gives you everything except for using the MIDI channel as filter then I‘d recommend to keep on nagging me to add this - it should be a pretty easy addition with another simple check.
-
@Christoph-Hart But I'm nagging you on 2 fronts already (ScriptNode stuff and Faust channels), and was about to open up another thread...
Alright, can you add this please? I think it's an advanced enough thing where you don't have to modify the built in right-click MIDI learn system, so any implementation of this would have to be custom anyway. Therefore the automation object should just check for the MIDI channel on incoming controller messages.
This also plays in with exclusivity - setExclusiveMode should then be set to off for this to work, no? Also, will the message be consumed by controller number or as an object, i.e. will setConsumeAutomatedControllers also have to be set?
-
Yes so basically you would need another call
MidiAutomationHandler.setUseMidiChannels()
and then it will also take into account the channel of the incoming MIDI message when learning is active (or if you pass in a custom JSON object you can just supply the channel you want). -
@Christoph-Hart that sounds great.Thanks a lot.
Do you think there's a performance difference doing it this way and having a branch in on controller?
-
Do you think there's a performance difference doing it this way and having a branch in on controller?
Not relying on the script and doing stuff in C++ is always faster.
-
@Christoph-Hart Nag nag
If C++ is always faster, then it would be paramount to avoid a large branching function in on_controller when multiple MIDI channels are in play, as that by itself means there's a lot of controller data being sent into the plugin, no?
Can you please add the proposed MIDI channel property to the automation object?
-
@aaronventure I would like to see this added to the MIDI learn function. As it is I can't use the built-in MIDI learn because it will respond to all MIDI channels of the learned CC, and with a multi-timbral setup (such as an orchestral template in a DAW) this is a no-no.
-
@VirtualVirgin Does this happen also if you filter the MIDI channel using the settings floating tile?
-
@d-healey said in Proper MIDI automation of controls across multiple MIDI channels?:
@VirtualVirgin Does this happen also if you filter the MIDI channel using the settings floating tile?
So I think this is what you are asking about.
The know here has been MIDI learned using CC#1 on Channel 1, and I am moving a knob on my MIDI controller sending CC#1 on Channel 2.The Channel Filter has no effect here on the MIDI learn input.
Even if it did, it wouldn't be very useful as you would still want other channels to pass though to get to their desired destination,
To work properly, the MIDI learn itself needs channel detection and a "Channel" column needs to be added to the floating tile so the user can change it if need be. -
@VirtualVirgin said in Proper MIDI automation of controls across multiple MIDI channels?:
To work properly, the MIDI learn itself needs channel detection and a "Channel" column needs to be added to the floating tile so the user can change it if need be.
Ah ok, yeah that seems like a better solution. Is there a situation where you would want multiple channels to control the learned control?
-
@d-healey said in Proper MIDI automation of controls across multiple MIDI channels?:
@VirtualVirgin said in Proper MIDI automation of controls across multiple MIDI channels?:
To work properly, the MIDI learn itself needs channel detection and a "Channel" column needs to be added to the floating tile so the user can change it if need be.
Ah ok, yeah that seems like a better solution. Is there a situation where you would want multiple channels to control the learned control?
Not off the top of my head. I'm assuming that if the user wants to control the same set of controls from more than one device, then they will map those knobs/sliders to the same MIDI channel on the different devices. That remapping is not possible on every device however, so it all depends on how many options to add for what may be minimal use cases.
-
@d-healey having a multi instrument or multi layer setup offering a midi channel selection for each, as well as being able to set it to "omni" like in Kontakt where it then responds to all channels
So when passing a midi channel in the object, I guess an implementation would be where we can pass either a channel integer, an away of integers or a string saying "all", or -1 or whatever react to all, the way it is now (in case the implementation requires it to have a defined midiChannel property).
-
@aaronventure Alright, I've pushed the channel filter feature. You have to add
HISE_USE_MIDI_CHANNELS_FOR_AUTOMATION=1
to your extra definitions to enable this, otherwise it will retain the old functionality.I've also updated the docs for the MidiAutomationHandler object so it's not fishing in the dark anymore.
-
@Christoph-Hart Awesome, thanks! Great job on the docs, too. I was already writing a post asking a bunch of questions about doing MIDI with the custom automation stuff. Two things I wanna ask here:
-
What is the converter property?
-
Can you elaborate on the preprocessors a little bit more? The docs say something that left me wondering whether I understood how they're implemented in HISE properly.
If you don't see the Channel property in the JSON object, you have to enable the support for different MIDI channels by adding HISE_USE_MIDI_CHANNELS_FOR_AUTOMATION=1 to your Extra Definitions field (you don't have to recompile HISE for it to be applied though).
So if I add this preproc to my project's Extra Definitions for the current system, it will start showing up in the JSON object?
I don't have to build HISE with this preproc?
Usually it's the other way around for stuff like HISE_USE_SVF_FOR_CURVE_EQ.
Why is there no global Extra Definitions field that will apply to all systems?
Why a preprocessor instead of a method call like you described in the post from 4 months ago? Won't this complicate hopping between projects that use it and the ones that don't?
-
-
What is the converter property?
it contains an encoded function for how to turn the value into a string. That might include range, suffixes, or even options (when using comboboxes). I unified this system a few months back so that plugin parameters and MIDI controllers should show the properly formatted text from the values (I think in this case it will affect the range slider display). Ideally you don't need to think about this at all, as it will be handled by HISE automatically).
So if I add this preproc to my project's Extra Definitions for the current system, it will start showing up in the JSON object?
I don't have to build HISE with this preproc?
Yes exactly, I've recently added a function that dynamically pulls some preprocessor values in HISE and uses the static compile time preprocessor in the compiled plugin. This obviously only works with things that do not affect compile-time code, and I have to explicitely implement it for every preprocessor.
I'm open to a suggestion of preprocessors that you might benefit from this - as I said, with some it won't work (eg. HISE_NUM_CHANNELS is being used as a static array size for all multichannel data objects which would slow down the performance within HISE considerably), but
HISE_USE_SVF_FOR_CURVE_EQ
might be a candidate for this improvement, as it just pulls the value when creating the filter objects.Why is there no global Extra Definitions field that will apply to all systems?
No idea, but I just paste the stuff I need in all the platforms I want to support and I suggest you do the same :)
Why a preprocessor instead of a method call like you described in the post from 4 months ago? Won't this complicate hopping between projects that use it and the ones that don't?
As I described above, a preprocessor is resolved into a static compile time value, so the compiler might perform optimizations. We can leave that on the table inside HISE for certain things, but moving eg. the number of macros into a function would be a performance regression in the compiled plugin.
These settings will be refreshed when you switch projects and change the field in the settings so it should be about as comfortable as calling a method.
-
@Christoph-Hart said in Proper MIDI automation of controls across multiple MIDI channels?:
Yes exactly, I've recently added a function that dynamically pulls some preprocessor values in HISE and uses the static compile time preprocessor in the compiled plugin. This obviously only works with things that do not affect compile-time code, and I have to explicitely implement it for every preprocessor.
I'm open to a suggestion of preprocessors that you might benefit from this - as I said, with some it won't work (eg. HISE_NUM_CHANNELS is being used as a static array size for all multichannel data objects which would slow down the performance within HISE considerably), but HISE_USE_SVF_FOR_CURVE_EQ might be a candidate for this improvement, as it just pulls the value when creating the filter objects.
That's pretty cool. There's a big list somewhere but here are some that I use which look like they could be a candidate based on your prerequisites:
- HISE_SUSPENSION_TAIL_MS : this is an interesting one because if you use a peak node's buffer for displaying on the interface via the tile component, it will freeze when the network gets suspended
- HISE_USE_SVF_FOR_CURVE_EQ obviously, almost zero downsides, it also enables LP/HP Q parameter. The CPU usage of filters increases by around 20%, but it's very low to begin with so it's not really a thing unless you're using 50 filters per instance with 10-20-30 instances in a session
- HISE_BACKEND_AS_FX this may or may not be possible, I have no idea how it's routed in the back, I use this to compile the plugin version of HISE so I can run it in Plugin Doctor and thoroughly analyse the DSP results.
- JUCE_USE_BETTER_MACHINE_IDS
- HISE_INCLUDE_PROFILING_TOOLKIT but maybe it's not worth it if Perfetto's on its way out anyway.
@Christoph-Hart said in Proper MIDI automation of controls across multiple MIDI channels?:
As I described above, a preprocessor is resolved into a static compile time value, so the compiler might perform optimizations. We can leave that on the table inside HISE for certain things, but moving eg. the number of macros into a function would be a performance regression in the compiled plugin.
These settings will be refreshed when you switch projects and change the field in the settings so it should be about as comfortable as calling a method.
Yeah preproc working dynamically for the IDE explains this.