Hi Nic, I've been trying some advanced MidiBridge "programming" with momentary scene changes. Just wondering if delayed (+D) messages make it through a scene change. Also, is it possible to delay (+D) a scene change?
The objective of all this is that I'm trying to set up a "preset" system for live performance. I want LoopyHD to be set at a particular bpm at the beginning of a song, but LoopyHD's implementation of bpm setting via CC's is not very good (you can only use 128 values to set all tempos between 30 and 300 or something like that, so you can't get at all of them), so I'm forced to do a workaround here.
The solution I came up with is: - if Scene1 in MidiBridge receives a certain "preset" Program Change message, MidiBridge first sends CCs to set the appropriate tempo in MidiBus, then MidiBridge switches into Scene2 - in Scene2, MidiBus starts playing, consequently sending MIDI Clock (including the right tempo info) to LoopyHD, then it shuts off
I'm using scene changes because I only want LoopyHD to slave to MidiBus during this "preset" setting phase, otherwise I want to control its transport freely, for compositional reasons. So I was hoping to, on selecting Scene2, push a single program change, which would start MidiBus playing for a little bit, stop it after a little bit, then switch back to Scene1, but I've run into complications with the +D across scenes.
Yes, a +D message will remain 'in the queue' after the scene in which it was delayed (and optionally cloned) has been switched away from.
It sounds like what you want is: whenever scene A is enabled, it should auto-switch to scene B after nnn ms? Here is how I think you can do it:
1. Assuming the Scene Channel is set to 1 (Prefs/Options) for scene changes and that scene A is scene 000 and scene B is scene 001 in MidiBridge
2. Create your scene 000 with the following enabled on any *input* port (on left) (suggest MidiBridge's own virtual port?):
- Program Changer, enabled, with it issuing program change 001 on channel 16 - Stream Byter, enabled, with these 2 rules:
CF = C0 +C +D2000 CF = XX +B
Now, when you switch to scene 000 via app UI or MIDI program change 0, it sends in a program change on MIDI channel 16 *as if it had been received on that port* which then gets passed into the Stream Byter which then clones it to the correct scene channel with a 2 second delay which results in scene 001 being auto-switched after that time.
In trying this out... I think I have it partially working, but what I came across is that the scene changes immediately... kind of gets stuck in a loop where I can no longer edit the "temporary" scene because it switches too fast
Yeah, you're right. When the delayed program change is injected it isn't delayed since the delay happens after the event is sent and not when cloned.
I know I did this before for someone!
First, we need to temporarily stop the loop issue by setting Scene Channel to OFF so you can load scene 000 without it switching.
We then need to setup network loopback - this assumes that you are not connecting to anything via wifi MIDI:
- Go to Prefs/CoreMIDI Net and enter the word 'localhost' in the top text field and press 'Connect'. If connected you should get a dialog and also the number '2' as a badge on the Interfaces tab button.
- Load Scene 000
- Now make a connection from MidiBridge in to CoreMIDI Net out
- Enable Program Changer sending PC 1 on channel 16 on MidiBridge in (left) (should already be done)
- Modify Stream Byter with just this single rule on MidiBridge in (left)
Ah, spoke too soon! I've found some strange behaviours trying to get this new setup working.
So first I tried loading other Program Changes on Channels other than 16 on various input ports in order to get a "pushed" event (which I could then use to turn MidiBus transport on and off), but these seemed to interfere with the delayed scene switch.
So then I tried using Stream Byter on the MidiBridge input module (the same module containing the code for the delayed scene switch), and entering it before the code:
CF = FA +C +D2000 CF = FC +C +D3000 CF = X0 +D4000
The strange behaviour is: this works if "listening" with a MIDI utility... but if i connect the MidiBridge input port to the MidiBus output port, the transport functions work, but the delayed scene switch does not.
The obvious thing to check is that in your scene 000 (transient one) that the MidiBridge in port (left) is connected to *both* the MidiBus out and CoreMIDI Net out simultaneously. Also check that the localhost connection is still 'up' (verify that the '2' still on badge).
Also, to make things cleaner, I would add an Event Filter to CoreMIDI Net out (on right) and setup to allow only program changes on channel 1. This will stop anything else from being looped back into CoreMIDI Net (just in case)
Why it works with a Midi Monitor could be that the monitor app is passing the events it receives back out of itself (MIDI thru) and back into MidiBridge somehow.
If the above isn't the problem, let me know and I'll try and reproduce.
I am able to reproduce and thought I had found cause and workaround. However when I went to document everything it didn't work again. I've messed around with too much stuff and need to start afresh with a clean slate (and brain). I may have a chance at this over the weekend, otherwise early next week.
Hi Nic, thanks for looking into this. I've found a workaround for my system for the time being, it's not as convenient or automatic a solution as the one I hope to eventually implement with the semi-automatic scene changing, but definitely no time pressures from this end. I'm just grateful you're interested in trying to find a solution. In my experience, it's super rare to have a developer step up to the plate like this, so thanks again.
OK, I managed to make this work. I still am completely stymied why starting MidiBus 'eats up' the delayed program change, but it does - even if MidiBus has no destinations enabled.
Here is how I have things set up:
- select only 'MidiBus' as destination on Transport pane - select only 'Network' as source on Monitor pane
- set Scene Channel to off (Prefs) while we are working to prevent unexpected scene shifts - Configure the localhost CoreMIDI Net connection on Prefs - Load Scene 000 - Remove *all* routings and all Stream Byter and Program Changer configurations from before (I'd even be tempted to delete and re-install MidiBridge to start from clean slate) - Connect CoreMIDI Net in to CoreMIDI Net out - Touch the 'beaker' on CoreMIDI Net out (on right!) - Enable Program Changer and set value '0' for channel 16 (as we did before) - Enable Stream Byter and paste in these rules
CF = FA +C FA = FC +C +D2000 FC = C0 01 +C +D2000 XX = XX +B
- Install rules and save to Scene 000 - Switch Scene Channel in Prefs back to 1
Now load up a different scene and then load Scene 000. You should see a flash on the CoreMIDI Net ports and the MidiBus port should flash with a sysex message. 2 seconds later, the MidiBus port should stop flashing and another 2 seconds later it should shift to Scene 001. These rules 'cascade' the events rather then scheduling them simultaneously.
You can adjust the delay times of the stop and shift events if you prefer other times between start/stop and stop/shift.
Wow, thanks for this Nic, I can confirm that it works on my setup as well. The only time it did not work 100% was when using the "Visual Events" option in Preferences, maybe because of some memory allocation issue?
I'll still have to make sure all my other rules and connections will work simultaneously with this, which might take a while to setup and potentially revise, but thanks again!
Just so I understand it better, is the reason we can ignore the rule "You can only generate a scene change from a ruleset if the rules are on an input (left) port in MidiBridge" because it is from the Network Out which is being fed back into the input stage?