• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: CoreMIDI question
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CoreMIDI question


  • Subject: Re: CoreMIDI question
  • From: Kurt Revis <email@hidden>
  • Date: Sun, 28 Apr 2002 05:17:28 -0700

On Sunday, April 28, 2002, at 12:05 AM, robert <robert@apple-
audio.allyourbass.org> wrote:

However, the docs on MIDIPacketListAdd() tell me that this function can be
given a timestamp at (as far as I can understand) which an every (sending a
MIDI message) has to occur. The docs are not very clear about this, though.

I'm afraid I can't quite parse that sentence, but here's an overview anyway.

Each MIDIPacket structure contains some MIDI data, as well as a timestamp. When you receive MIDI data, the data you get has a timestamp indicating when the device received it. When you send MIDI data, you supply the timestamp. If the timestamp is 0, or in the past, the data will be delivered immediately. If it is in the future, CoreMIDI will queue up the data and attempt to get it sent out the device as close to the timestamp as it can. (Obviously the drivers have to cooperate in doing this.)

Incidentally, this only works for data sent through MIDISend(). If you are using MIDIReceived() to indicate that data is coming from a virtual MIDI source, then CoreMIDI will not do any scheduling for you -- the timestamps are passed through to destination programs unchanged. This is kind of unfortunate, especially in your case:

I'm toying with the idea of a small application consisting of a BPM counter
which drives a virtual MIDI source sending MIDI Clock messages (the 0xF8
message in the MIDI protocol).

If I were you, I would change your program around so that it uses MIDISend() to send to endpoints, instead of being a virtual source. This may require a rethink on your part, since it means that your users will have to use your app to choose where to send the MIDI clock, instead of letting them select it as a source in other applications. It will be quite a bit easier to get working this way, though, since you can let CoreMIDI worry about the hardest part of the scheduling. You just need to give it events some reasonable amount of time in advance of when they should be sent.

(This will also let you send MIDI clock to external MIDI devices, which you couldn't do directly with a virtual source.)

If you really really want to use a virtual source, I imagine it can be done. But getting the easier case working will teach you most of what you need to know, so you might as well tackle that first.

Here's what to do, roughly: Your app should have a thread which wakes up periodically, figures out what time it is, creates some MIDI clock messages, and sends them. Each message should be timestamped with some time in the future. It's up to you to decide how far into the future you want to go, and how many clocks you want to generate at a time (maybe just one). (If you can batch up the clock ticks, your thread will need to wake up less frequently, which is easier to accomplish reliably... but response will be worse when the clock starts or stops or the tempo changes.)

Now you just need your thread to wake up with a somewhat consistent period (it does not need to be perfect). There are an absurd number of ways to do this. You suggested select() and setitimer(), both of which are a bit too high level to be convenient. pthread_cond_timedwait() is in the same category. There is also CFRunLoopTimer, and in Cocoa you have NSTimer and -[NSThread sleepUntilDate:]. I don't recall the exact results, but I don't remember the latter two methods being very accurate.

Instead, I suggest one of the following:

* usleep(). Ignore the warnings about setitimer() in the man page, since they are completely wrong--Darwin doesn't actually use that method.

* nanosleep(). This is in the current Mac OS X, but there is no man page or function declaration. However, you can declare it yourself, and your program will link fine. Supposedly this will be fixed in the future.

* mach_wait_until(). Again, no man page, but at least it's declared. This lets your thread sleep until a given time (it takes a Mach timestamp which is exactly the same as a CoreAudio host time timestamp).

To get more details for all of these, I recommend Google, searching the mailing list archives (this list, Darwin-development, and Mac-Games-Dev), reading any comments in the headers, and looking at the Darwin source code (check out Libc and xnu). I also just posted the URL to some of my own code which uses usleep() or nanosleep() to wake up periodically.

Note that you will pretty much never wake up exactly when you want--the Mac OS X scheduler is just not that exact (it's not a real-time OS). So you need to be prepared for a fair amount of variance. For ordinary threads, the variance can in fact be quite high, especially if the system is busy with other, more high-priority threads. (The worst thing seems to be when the user is dragging a window around.) If you want less variance, you should look into making your thread use the time-constraint scheduling policy, using thread_policy_set(). Again, this has been discussed a fair amount on the lists, and I expect more info about it to be communicated by Apple as time goes on.

There's my brain dump--I hope it helps and was not overwhelming. As always, any corrections from everyone else are welcome.

--
Kurt Revis
email@hidden
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: CoreMIDI question
      • From: Doug Wyatt <email@hidden>
    • Re: [coreaudio] Re: CoreMIDI question
      • From: robert <email@hidden>
References: 
 >CoreMIDI question (From: robert <email@hidden>)

  • Prev by Date: CoreMIDI question
  • Next by Date: Midi timing issues
  • Previous by thread: CoreMIDI question
  • Next by thread: Re: [coreaudio] Re: CoreMIDI question
  • Index(es):
    • Date
    • Thread