Hi Billy,
The notes trigger situation may be a matter of taking control of the trigger flow - this works a little differently in Ruby compared to what we're used to, but is actually very flexible once you get used to it.
Let me know if this is correct...
I am guessing that you have an incoming note value coming from part of your schematic - but you don't want the note to actually play until it receives a trigger from some other part of the schematic that handles the timing?
With the Ruby in your post, what is happening is that the note gets sent when the @note value changes, which fires the MIDI at the wrong time, and possibly with the wrong value - but if you block the trigger, it won't get sent at all!!
By adding a little code to the "event" section, it is possible to separate "update note value" and "send the note" into two completely separate events.
Here's a little example of how you would do that - hopefully the comments in the code will make it clear what is happening....
PPQYes, I think you're on the right track. A frame is a collection of samples that is exactly one ASIO buffer in size, and totally in sync with the VST host. It's weird at first because we are so used to the SM "one sample at a time" way of doing things - but in reality, the host always sends data in buffer-size "chunks". SM has been hiding this from us for a long time!
Now, finding the beat starts should be quite simple - grab a 'frame' of the PPQ signal, and scan the data until you find that point where the ramp resets. ASIO buffers are so small, I think we can safely assume that there would never be more than one per frame!!
You could possibly also look for crossing other values in the ramp (e.g. 0.5 = half beat) for smaller timing divisions.
If the frame arrives at time "t", you should be able to say that the MIDI event needs sending at some time "t + offset", where offset represents how far into the buffer the crossing happened.
But hang on, time "t + offset" is some time in the future - surely it will then get sent too late?
This is the bit I've been experimenting with, and I think I need to go back to the drawing board because it may be simpler than I first thought. The host knows what the ASIO buffer size is, so my guess is that it would use 'latency compensation' to send the PPQ one frame in advance.
But that's only a guess, and my experiments ground to a halt when I got distracted by other things!!
The other slight trouble is that running a Ruby routine for every single incoming frame will use quite a bit of CPU power, because Ruby is nothing like as efficient as DSP code or assembly - so there are a few other little problems to solve...
1) Making the Ruby code totally, utterly as optimised as possible. For example, if the first and last PPQ values of the frame were, say, 0.69 and 0.71, there's no point scanning the whole frame because we're nowhere near the crossing point. (unless you're weird like me and want to test for quintuplet beats!).
2) There needs to be a 'Master Clock' so we only need one of those greedy Ruby timing routines!
3) Some way to distribute the clock around the schematic that doesn't need any "green" at all, so that we don't mess up our lovely new accurate timing. And for us folks with lots of old SM schematics, that means LOTS of modules to re-write!!
(NB - MIDI events are now integrated with Ruby, so the timing of MIDI links should be OK)
And thanks for bringing this stuff back to my attention.
Just writing out this description has really helped me to straighten out in my head exactly what we're trying to achieve, and break it down into little chunks that we can tackle one step at a time.
Off to a very noisy gig shortly, but if I'm not too hung-over tomorrow, I'll dig out my old experiments and see what improvements I can make.