Re: Can MIDIPackets be modified after they are sent?
Re: Can MIDIPackets be modified after they are sent?
- Subject: Re: Can MIDIPackets be modified after they are sent?
- From: Tom Jeffries <email@hidden>
- Date: Mon, 06 Jun 2011 15:06:48 -0700
Brian,
10 ms latency is not a problem, but jitter certainly is. The docs for timers seem to imply that the actual message to the function that plays the note may be delayed by 50 ms or more (the online docs are down or I'd include a quote). Obviously that won't work.
I tried using the CoreAudio Clock, but have not been able to find a way that I can set a regular callback with it. That's why I set things up using a series of MIDIPackets for the predetermined notes with notes being generated in real time added in a separate set of MIDIPackets to be played as quickly as possible.
Maybe I'm missing something obvious? Is there an accurate millisecond clock? Did I miss something with CoreAudio Clock?
Thanks, Tom Jeffries
On Sat, Jun 4, 2011 at 12:07 PM, Brian Willoughby
<email@hidden> wrote:
Your assumption is false. You can build sequences in real time, and the only caveat is that there is a slight latency, just as there is with real-time audio.
As Andre suggests, run your sequence on a millisecond clock, and then provide the events a few milliseconds before they are supposed to play. Considering that a 10 ms latency should not cause problems with music, the above should be plenty accurate. The only modification I would make to Andre's suggestion is that you do not necessarily need to keep the entire sequence of events in a buffer, but it certainly does help to think of the system in those terms - separating the source of events from their delivery to CoreMIDI is the key.
The catch is that you cannot alter events after you submit them to CoreMIDI. But, if you're generating totally new events just a few milliseconds before they should be heard, then you can have a sequence built in real time. The key is to keep a constant latency rather than random. You could even program your sequence builder such that it thinks it's working with instant output, but then your CoreMIDI code would simply add a 10 millisecond latency to the time stamp and then immediately submit that altered event to for playback.
If you are modifying live MIDI input, then you'll most certainly need to add the constant latency value to the time stamp of the incoming data. In other words, you can't reliably play MIDI events in the "past" - which is what would happen if you reuse the time stamp of incoming data, and then submit the potentially-altered event for output.
I'm not sure exactly what the latency should be, but I'm sure you can experiment to find the best value. Something between 1 or 2 milliseconds and 10 milliseconds should work fine. You can even set the latency much higher - and there are interesting psychoacoustic reasons for doing it that way - but I have a feeling that you'll want to go for as short a latency as will work reliably with your code. Just keep in mind that the latency cannot be 0 milliseconds.
By the way, if you're dealing with audio in the same code, then you might just want to query CoreAudio for the audio latency (input and/or output, as appropriate) and then match your internal latency for CoreMIDI to that. Some MIDI interfaces will have their own latency. USB-MIDI, particularly, will have a random latency of around 1 or 2 milliseconds. But the rare few interfaces like MOTU's MTS will have no latency at all, and so your programmed latency will be exact.
Brian Willoughby
Sound Consulting
On Jun 4, 2011, at 09:24, Tom Jeffries wrote:
So in other words, neither MIDIPackets nor the built-in sequencer can be used for sequences being built in real-time? That's how I'm proceeding, I just want to verify.
On Sat, Jun 4, 2011 at 8:42 AM, andre <email@hidden> wrote:
On 07.05.2011, at 17:36, Tom Jeffries wrote:
Is there a way to change the event data after playback has started, or am I back to trying to make this work with a clock?
The solution is to keep your events around in a sequence or buffer, modify them there, and send them out only a few milliseconds before they are due.
You need a "player" thread that runs in sync with the system clock, i.e. waits for a particular millisecond clock value and then reads the next events from the sequence to send them out.
It is a bad idea to schedule events very early ahead of time, except for very, very simple purposes.
HTH
Andre
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden