Cabbage Logo
Back to Cabbage Site

MIDI controllable custom presets + csound to DAW feedback

Dear csound/cabbage gurus/Rory,

I’m cycling back on an old question/frustration.

I created my preset system allowing me to save and load presets with buttons, which can be MIDI mapped in a DAW (see snapshot). The idea is to on the fly save/load presets in different slots and the entire bank of presets can then be saved/loaded to/from a single file.
image

I’m using arrays for this and it works fine, but the problem is that when presets change the host DAW doesn’t get informed and doesn’t send MIDI feedback to a mapped MIDI controller. This is related to my previous questions (Plugin feedback DAW automation, MIDI feedback from plugin to MIDI controller - Can plugin inform a mapped MIDI controller about the state of variables when they change internally without using a mouse? ).

Looking at other posts, e.g. Solution for user-made presets?, Combobox snaps selection from csound, ToneZ - Free EDM synthesizer, Easier way to share presets, I think my preset system uses a similar basic principle as in the ToneZ’s synth or in presetmanager2_midi.zip from Combobox snaps selection from csound, i.e. custom triggering and changing parameters from the preset info. I see that those solutions suffer from the same issue as my solution. They don’t inform the host about the parameter changes upon preset changes, which can be triggered either via a MIDI mapped button or via MIDI program change messages.

To resolve this, you (Rory) “modified things so that changes made to a channel within Csound (using chnset) are broadcast to the host”. Unfortunately, this interrupts automation. Trying to resolve this, “the last attempt used an AUTOMATION channel to disable/enable the plugin from broadcasting changes to the host”. This was not a stable solution, so I believe you reverted back to not using the AUTOMATION channel, right? In version 2.5.16 it doesn’t seem to function anymore.

I’ve seen plugin examples (not open source though) which can change presets with MIDI program change messages, send parameter change feedback to DAW and not interrupt automation. I still hope this (or something similar) is possible in csound/cabbage? But if not due to some reason, I’d like to know, just so I can plan my plugin designs around it.

The preset system in Examples/Miscellaneous/PresetsNamed.csd seems great and it does send feedback to DAW. So there must be some fundamental difference in how it sets the parameters, not using chnset? Could this system be reworked to allow custom triggers invoked by e.g. MIDI program change messages or buttons change?

Best,
Samo

Hi Samo. Good to hear from you again. Yes, I had to revert the changes made because they were causing weird behaviour with the hosts. I will need to investigate this again. Updating parameters using presets is more or less the same as parameters updated using chnset.

I think we may have to go back to the start on this one. Can you post a simple .csd that shows once again what the problem is? Sorry to ask but it would be most helpful :wink:

Hi Rory,

I think the automation got interrupted (for me in Ableton) because of a feedback loop (see discussion in Plugin feedback DAW automation).

I think the problem is well illustrated by comparing the ToneZ’s synth or the presetmanager2_midi.zip to Examples/Miscellaneous/PresetsNamed.csd. Check how they respectively don’t and do broadcast changes to a DAW, e.g. Ableton.

The first two examples have the same issue as we discussed here: MIDI feedback from plugin to MIDI controller - Can plugin inform a mapped MIDI controller about the state of variables when they change internally without using a mouse?

I’m copying your post as an illustration what to look for (after you made the change which is now reverted):

Note that the PresetsNamed.csd does broadcast to the host while the other examples here don’t. It seems we have the same issue of not broadcasting any explicit chnset instructions. See also my code example in MIDI feedback from plugin to MIDI controller - Can plugin inform a mapped MIDI controller about the state of variables when they change internally without using a mouse?
The key bits are:

rslider bounds(2, 22, 120, 120) range(0.5, 10000, 220, 0.25, 0.001) channel("OscFrq") 
button bounds(126, 20, 65, 65) latched(0) channel("OscFrqMultiplier2")  text("","") value(0)  
button bounds(126, 88, 65, 65) latched(0) channel("OscFrqMultiplier05") text("","")  value(0)  

and

if (trigger(chnget:k("OscFrqMultiplier2"), .5, 0) == 1) then;
    kOscFrq *= 2
    chnset  kOscFrq, "OscFrq" 
endif
    
if (trigger(chnget:k("OscFrqMultiplier05"), .5, 0) == 1) then;
   kOscFrq *= 0.5
   chnset  kOscFrq, "OscFrq" 
endif  

This makes me believe that your “snaps” systems is doing something different under the hood than the other examples using chnset.

Best,
Samo

Leave it with me. I’ll take a look. I’m pretty busy till Wednesday, but I’ll get back to you as soon as I make any headway. Btw, does the standard Presets.csd also work fine? Because PresetsNamed.csd and that call the exact same code in the plugin interface…

Ok, I have something for you, but it will take some testing. The biggest issue I see with the current situation is trying to mix the presets, which call higher level plugin parameter methods, with manual calls to chnset. The problem is that hosts will intermittently save plugin states, and when they do it will cause the plugin’s presets to be called, which will then trigger chnset’s, which causes a whole chain of events that seem to make Live go a little crazy.

The solution to this is two-fold. First thing to do is to set CHNSET_GESTURES to 1:

chnset 1, "CHNSET_GESTURES"

The other thing you need to do is to give up on using the preset system to save user presets. Instead roll your own that use chnset. It just so happens that I’ve added two new opcodes that might help here. channelStateSave and channelStateRecall. These will provide a means of saving and recalling presets using only Csound channels.

You can grab the latest build from here. I’ve also included an example called PresetsChannels for you to try out. It’s in the Misc examples menu/folder.

Let me know how it goes. In my tests I can record parameter changes made with chnset without any problems. Note I only tested with Live and Reaper. I haven’t ventured as far as AUs…

Btw, here is a simple example that doesn’t use the channelState opcodes. But it can’t recall presets either…

<Cabbage>
form caption("Test") size(370, 280), colour(58, 110, 182), pluginid("ysdt")
rslider bounds(12, 8, 85, 79), channel("att"), range(0, 1, 0.01), text("Att.")
checkbox bounds(252, 188, 100, 30) channel("checkchan9") text("Test Check")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 
</CsOptions>
<CsInstruments>
; Initialize the global variables.
;sr is set by the host
ksmps = 32
nchnls = 2
0dbfs = 1

chnset 1, "CHNSET_GESTURES"

instr 1
   kCheck chnget "checkchan9"
   if changed(kCheck) == 1 then
      chnset random:k(0, 1), "att"
   endif
endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
i1 0 z
</CsScore>
</CsoundSynthesizer>

Hi Rory,

Thanks so much! Also for you good description of the problem.

I tested in Ableton. It seems to work fine for all the channels except the checkbox. I can record automation fine, but the one on the checkbox gets interrupted.

When I get some time, I’ll test your channel state opcodes - they seem very handy!

I just tested your example with CHNSET_GESTURES and it is interrupting automation - old story.
What exactly is the CHNSET_GESTURES supposed to do?

Did you test the example I posted above or the channels one? Try the code I posed above, it works fine for me. I have ye to full test the channel opcodes version. But we could be back to a misunderstanding of what you want. Check the video here.

I tested the example above and I am getting the same as in your video.
But try playing back the recoded automation. It gets interrupted, right?

Yes I see this now. It makes sense of course because we also recorded the checkbox automation. You can set the combobox to be non-automatable using automatabile(0) but somehow the slider on its own will disarm automation. So when we play the automated track, it moves the slider, which is turn sends a parameter change message to the host, which causes Live to disarm automation because according to Live “this button is only active is you manually adjusted a parameter that is automated” I’ll take another look and see if I can find a fix.

I made some changes to that instrument so that we can switch CHNSET_GESTURES1 on and off. With CHNSET_GESTURES set to off I can record automation in the default way, i.e, calls to chnset within Csound don’t register as automation changes, but moving a control with the mouse will register automation changes. With CHNSET_GESTURES enabled, I can call chnset, which will in turn update the host automation, I can also move sliders and have this recorded. But we must disable CHNSET_GESTURES before playback of the recorded automation. Otherwise it goes into some kind of recursive loop.

Also note that I have disable automation for the two checkboxes. I don’t think it’s a good idea to automate the CHNSET_GESTURES channels, and didn’t see any point in it for the random chnset either. Here’s the file.

AutoTest.csd (889 Bytes)

1 I’m not sure CHNSET_GESTURES if the best channel name. I called it that because it enables a gestureChange call in the plugin API. But I’m open to suggestions.

Hi Rory,

isn’t this similar to the approach with the AUTOMATION channel, perhaps the implementation is different?

The effect is unfortunately similar as in the attempts with the AUTOMATION channel. Initially it works fine but it stops working after a while. It might have to do with the speed of action? In the attached video I am using a MIDI controller for the slider. I haven’t modified your csd file.

The thing with enabling automation on a button is that while I don’t need to record automation, I could potentially use it to change presets via MIDI mapping and if it is not automatable it is also not MIDI mappable it seems. May I dare enabling automation for the checkbox? :grimacing:

So you are moving the MIDI slider, and also triggering the ‘modify slider parameter’ at the same time?

I don’t have a MIDI controller to test this out with at the moment. Is there any way I can recreate the issue without one?

I suspected from the previous experience that the functionality may eventually break, so I wanted to get to that point fast - thus pushing and twisting vigorously.

I think you need to test with a mapped controller. Maybe you could try generating MIDI CC (for example with PD) and send it over to Ableton via a virtual bus, but I am afraid it has to do with mapping.

So I set up a MIDI send from Pd and started output a MIDI event every 10 ms for 10 seconds. At the same time I was pressing the update parameter button as fast as I could. It all worked fine for me here. Check out the video.

Am I missing some extra step you do?

It seems we found a common ground. You’re not missing any extra steps. But my computer or csound might be doing something that I am not aware, because I tried it now with Pd and I get the same issue as with MIDI controllers. I tried sending MIDI every 0.5 s.

Since the slider keeps moving while Pd is sending MIDI, I guess it is not due to Ableton? What do you think? Could it be something with my csound installation or do cabbage installers take care of it? At the moment I can’t easily test this on a different computer… Let me know if you have any ideas what could I try or check. Thanks so much again for your patience and persistence!

Ok, that’s weird. I’m using Csound 6.15, if you type csound into the terminal it will print the version. I’m also using Live 10. What are you using? My Mac OS is 10.13.6

I’m a bit outdated with Live 9 and Mac OS 10.12.6, but Csound version is as yours 6.15.
I might need an update soon :worried:

I just wanted to add that I realized now that I have the same problem with other non Cabbage plugins (broadcasting to the host interrupts after a while). So I really need to do some updating and sorting my system :fearful:.

I thing you provided a feasible handle to address my wish to record automation after a preset change and send feedback to MIDI controllers. Thanks so much for your fantastic work!

btw. the new more efficient mechanism for updating the widgets with cabbageSet you described here: Bye-bye `identchannel()` Maybe? PLEASE READ!
seems very exciting!

I’m sorry to hear that the problem is present with other plugins, but also kind of relieved it’s not specific to Cabbage!

Thanks. Feel free to throw out any suggestions if you have them!