AAX - ProTools - really ProTools? Really?
-
Is there a way to get the state of the host transport in HISE? If so you could use that and turn all notes off whenever transport is stopped.
-
@d-healey well there is Engine.getPlayHead() - which returns a bunch of stuff including isPlaying (for the playhead), so you would think this would be the fix - but 10 or 15 seconds of thinking about this (I will admit on the back of 15 years of working with onListener call bacaks) will tell you that this isnt a solution:
So we need to find out if the playhead is running (transport = playing) and its state can be obtained from getPlayHead, and to read this state we will need a timer..suddenly - BIG problem.
Lets set up our timer at say 100ms:
we need to check if the current playHead state is different from the saved playHead state (from the last time we called the timer) - if so and we've gone from "playing" to "stopped" then we can issue an Engine.allNotesOff() and be done with it....
BUT, BUT BUT,BUT.....
when the user presses play, and some midi notes are triggered, and the user then very quickly presses stop - we are right back where we started; the notes are hanging - and our timer thinks there has been no state change (there has its gone stopped-start-stopped all between the timer calls)
There is a solution to this - and its one I feel HISE must implement at some point - we need an onTransport call back....so our plugins can manage transport start and stop and tempo changes in a realtime-like way - otherwise we are all writng our own timer callbacks and all of them will make approximation errors ...bad bad bad...
-
A better way for handling this edge case would be to check if the plugin is being used inside Protools and then do their job by automatically inserting a allNotesOff message when the transport changes inside HISE.
This shouldn't be the task of a script - especially if it happens only on one host - makes me wonder how FL Studio manages to send proper note offs :)
-
@Christoph-Hart yes I understand this is an edge case, so are you suggesting this should be implemented in HISE somehow? In the C++ code? But in any case the general principle isn't an edge case.
For every running sequencer that I build, that uses "Sync Tempo" I will need to check the current tempo of the DAW, and I can only currently do that (if at all) in a timer callback, and depending on when the tempo change occurred I will be some number of milliseconds "out of sync", however if there is an onTransport callback then I get to know immediately there is a tempo change and can act upon it.
Its been asked for before I know - and I think its a very very good idea.
-
Its been asked for before I know - and I think its a very very good idea.
+1
-
Yes but still using a callback like this to fix a certain host behaviour isnt the best solution so yes it should be done on C++ level - if the host fails you, then HISE should save you ;)
-
@Christoph-Hart I agree using a call back to fix a single hosts (poor) behaviour is a bad idea, but that doesn't invalidate the need for a call back for the more general situation I outline above.
So I am asking for the call back, and I'd really like it to occur (and provide detailed information in some sort of message) for the following situations:
transport start
transport stop
tempo changeWhat, for an incredible amount of user-friendly bonus points, would be great is the ability to register an interest in a callback for these events:
- bar start - so it would trigger the callback on every bar start
- all the tempo sync bar options(1/2D, 1/2,1/2D, 1/4D, 1/4 etc etc.)
If HISE provided these then writing sequencers would become a much much much more trivial task to undertake, and in fact I think would make HISE even more unique, attractive and powerful.
-
I could add a
TransportHandler
class that you could assign callbacks to - just like theExpansionHandler
class:const var th = Engine.createTransportHandler(); // first parameter is synchronous or not // if you want it to be executed synchronously (in the audio thread) // you must supply an inline function (because the normal function isn't // realtime safe) th.setOnTempoChange(true, inline function() { // the transport handler will contain // the AudioHead properties and can be // obtained with `this` Synth.startTimer(this.bpm); }); // if it's async, it can be a normal function th.setOnTransportChange(false, function() { MyPanel.setTimerCallback(function() { // something }); });
-
@Christoph-Hart yeah I think that would work...
so (for our edge case..)sort of:
const var th = Engine.createTransportHandler(); th.setOnTransportChange(false, function() { if (!this.playing) Engine.allNotesOff(); });
so cheeky request, can we also get:
th.setOnBarStart(false, function() //<--- oh look at that sorta onListener ish...
and maybe the bar subdivisions?
-
so (for our edge case..)sort of:
Almost... you want it to be synchronous because asynchronous calls might be skipped if no interface is present.
const var th = Engine.createTransportHandler(); th.setOnTransportChange(true, function() { if (!this.playing) Engine.allNotesOff(); });
-
@Christoph-Hart and those super useful other event types? (Crosses fingers here...)
-
If the basic system is there, adding those is trivial. I'll try to cover all information that is contained in the AudioPlayhead.
-
-
....
-
@Christoph-Hart Hey Christoph, would that solve the hanging notes issue for me too?
-
Actually I'm thinking about adding a allNotes off message automatically when the transport playback state changes from true to false so this might solve some hanging note issues indeed (the notes will still hang until you stop the playback) - it's a rather intrusive change for all projects, but I can't think of a scenario where this backfires.
You can check this functionality with this code:
const var th = Engine.createTransportHandler(); inline function onStop(isPlaying) { if(!isPlaying) Engine.allNotesOff(); }; th.setOnTransportChange(true, onStop);
If it works (and Lindon's initial problem with protools is fixed with this code), I'll add it to the default handling inside HISE...
-
it's a rather intrusive change for all projects, but I can't think of a scenario where this backfires
Might be a good idea to add a pre-processor definition to disable it in some weird edge case.
-
@Christoph-Hart said in AAX - ProTools - really ProTools? Really?:
If it works (and Lindon's initial problem with protools is fixed with this code), I'll add it to the default handling inside HISE...
OK so I built using the latest HISE - included the the code for handling All Notes Off on playhead stop, and the customer reports a big improvement in AAX/ProTools, its still not apparently perfect - moving from showing up around 50% of the time down to 5-10% of the time. Which I think is still a "ProTools behaving badly" problem..not sure how we can fix it any further....
-
@Christoph-Hart I just wanted to ask if this is now a part of the HISE build or if I still should call...?
const var th = Engine.createTransportHandler(); inline function onStop(isPlaying) { if(!isPlaying) Engine.allNotesOff(); }; th.setOnTransportChange(true, onStop);