Ideas for a Realtime Application

Hi everyone

I am looking at how to implement a sequencer, which will trigger various events based upon time. Firstly sending MIDI events using the MBS plugin, but perhaps sending messages out to USB and serial devices, some onscreen activity, etc etc. Perhaps syncing it all to MIDI timecode.

The time accuracy would ideally be to the millisecond.

I imagine I could use a Timer and set the tick to a millisecond, and that might do that job.

I’m just wondering, before I start the trial and error process, if anyone can lend some advice based upon experience. What are the pitfalls? What to do, what not to do. And so on.

I’m targeting OS X.

TIA
Tom

I guess you own all MBS classes and you are using a Console App. I think I read something in like your question and comes to my mind TimerMBS for accurate timing. @Christian Schmitz this one is for you … :wink:

I’ve just installed MBS and have the MIDI message transmission working (built upon the example app).
I’ll buy whatever MBS parts I end up using.
I haven’t yet worked out whether MBS MIDI will deal with timecode. OS X has a MIDI bus, so apps can talk to each other via that facility. Again, don’t know if MBS supports that, I’ve only just started with it.

I’m very curious about how to determine whether or not the events are firing at the right times. I suppose that could be determined with external hardware receiving MIDI messages (running a counter and logging the times), or perhaps a scope on the MIDI output. Another idea is to use the system time with the microseconds function, and check that within the Timer event, to see how much jitter there is.

Also need to know how much load can be put on the system i.e. how much code can run within that timer event. Is there a Unix profiling tool that would tell what percent of the system throughput is being used by a process? I’m sure that answer is easy to find.

Something I’ve just noticed…under some conditions, the Timer events stop. Like, the application loses focus, computer goes to sleep…or something. I don’t know yet, I’ve just seen that.

You might consider using Grand Central Dispatch’s dispatch_after to load up the events at the precise time they need to fire. I think MBS has something for that, but I can’t be sure. I think that’s probably the most accurate timing you’ll be able to get…

Timers aren’t entirely accurate - they’re close enough for most purposes but if you have to be accurate you’ll need to do something else

Apples OS tools (activity monitor & such) are useful

[quote=193370:@Norman Palardy]Timers aren’t entirely accurate - they’re close enough for most purposes but if you have to be accurate you’ll need to do something else

Apples OS tools (activity monitor & such) are useful[/quote]

From what I understand TimerMBS is much better. That is what Armando suggested. It may be able to go down to 1 ms.

On Windows as internally we’re not using MS high resolution timers

The MBS page says
Function: The class for a timer.
Notes:
This timer can work with smaller periods than the normal Xojo timers on Windows.
Works on Mac OS X and Linux, too.

Dunno how he’s implemented it

From another thread last week, posted by Christian himself :

[quote]Christian Schmitz Jun 3 Alpha Testers, Beta Testers, Xojo Pro, XDC 2015 Europe (Germany)
is this on Mac or Windows?

TimerMBS has a higher resolution on Windows as low as 1 ms while normal Xojo timer comes to about 60ms.[/quote]

I tend to believe him when he says 1 ms.

Thanks for all this input. It looks like there is still some reverse engineering to do.

I think that Grand Central Dispatch may be deeper than I want to go.

From an MBS press release:

“Our new TimerMBS class provides a high resolution cross platform timer.
While Xojo’s built in timer only fires 60 times per second on Windows, our
timer can run a quick as 1000 times per second.”

60 times per second is about 16 ms. But they say the MBS gadget will do 1 ms, so that is great. Though I don’t know if this is referring to Windows, or OSX too.

[quote=193720:@Tom Dowad]Thanks for all this input. It looks like there is still some reverse engineering to do.

I think that Grand Central Dispatch may be deeper than I want to go.

From an MBS press release:

“Our new TimerMBS class provides a high resolution cross platform timer.
While Xojo’s built in timer only fires 60 times per second on Windows, our
timer can run a quick as 1000 times per second.”

60 times per second is about 16 ms. But they say the MBS gadget will do 1 ms, so that is great. Though I don’t know if this is referring to Windows, or OSX too.[/quote]

Christian Schmitz said it for Windows in the post just above yours. The best you can do is to download the plugin from his site and experiment. It just displays a message in builds if not registered, but it works just the same.

As I can never resist digging in to the “too deep”, I came up with a simple function to schedule a callback via GCD…

[code]Sub setDispatch(nanosecondsFromNow as uint64,context as ptr, callback as ptr)
declare Function dispatch_time lib “/usr/lib/libSystem.B.dylib” (when as uint64,delta as uint64) as uint64
declare Function dispatch_get_global_queue lib “/usr/lib/libSystem.B.dylib” (ID as int32,flags as integer) as ptr
declare sub dispatch_after_f lib “/usr/lib/libSystem.B.dylib” (when as uint64,queue as ptr,context as ptr,work as ptr)

dim dispatch as ptr=dispatch_get_global_queue(2,0)

dim when as uint64=dispatch_time(0,nanosecondsFromNow)

dispatch_after_f(when,dispatch,context,callback)

End Sub
[/code]

The callback is a shared or global that has one parameter, context as ptr. You can pass a memoryblock, just be sure the memoryblock doesn’t go out of scope before the callback fires or you’ll get garbage.
Also be sure to add #Pragma StackOverflowChecking false to the callback or it will crash (not the case using the main queue).
Call it like:

setDispatch(1000000,context,AddressOf doDispatch)

Using a global queue with highest priority gets accuracy of less than a millisecond here vs 2-3 with the main queue.

In your usage I would store a base time value and add the offsets to schedule the callbacks. The memoryblocks would contain the midi data that needs to be sent at that point in time. This way you can queue up the data and not need to do any calculations in the sending code, just send whats in the context memoryblock and maybe set display values to be used by an update timer.

Amazing to find this thread where you discuss my work :slight_smile:

And MBS Plugin uses a lot of grand central dispatch. But be aware that you can’t run any Xojo code in the dispatched function/block unless you make sure it’s running on main thread.

So Jim I would recommend you not try too much here. Xojo is not re-entrant and StackOverflowChecking=false will not help!