W3C home > Mailing lists > Public > public-audio@w3.org > July to September 2012

Re: MIDI Tracks and Sequences

From: James Ingram <j.ingram@netcologne.de>
Date: Sat, 15 Sep 2012 14:12:47 +0200
Message-ID: <505470BF.7080006@netcologne.de>
To: Chris Wilson <cwilso@google.com>
CC: public-audio@w3.org, Jussi Kalliokoski <jussi.kalliokoski@gmail.com>, Joseph Berkovitz <joe@noteflight.com>
Hi Chris, Joe, all,

Am 14.09.2012 18:22, schrieb Chris Wilson:
> On Fri, Sep 14, 2012 at 2:07 AM, James Ingram <j.ingram@netcologne.de 
> <mailto:j.ingram@netcologne.de>> wrote:
>
>     The problem is that the sendMIDISequence() function is recursive.
>     And it has to be that way because of the way setInterval() works. 
>
> It really, really doesn't need to be recursive.
I don't think you can remove the recursion, and stay accurate at the 
same time. See below.

> That's what's giving you scope trouble, I believe.  This is also 
> causing you to have to pervert how you use setInterval - if you're 
> going to have to cancel the interval every tick, you should just use 
> setTimeout.
You are right, of course, using setInterval was an artefact. I thought 
it might help keep the stack size down if I could explicitly clear 
something, but using setTimeout actually makes no difference (I just 
tried it).

> Additionally, you are only sending one message per tick; that's not 
> really the point.  You should be sending any messages that are between 
> this interval call and the next, to get them queued up;
> ... more like this: https://gist.github.com/3722988.

That's more or less what Joe suggested too.
But if you send all messages within the INTERVAL as fast as possible (in 
the while{} loop) then you lose accuracy. As far as I can see, the delay 
between messages inside the INTERVAL is being ignored, and everything 
gets scheduled on a grid of INTERVAL milliseconds (plus or minus a few 
nano-seconds). In your code that's every 200ms. That's also what I hear 
in test 6 [1], where I have simply replaced my sendMIDISequence() 
function by your code  (remember, my recursive function was working with 
an accuracy of 1 millisecond). [Actually, that's not quite true: I have 
seen rare glitches in test 5 (maybe once in 3 minutes) in which 2-3 
notes deviate by more than 1 millisecond. Obviously, setInterval 
sometimes takes a rest...]

Interestingly, the scheduling in test 6 (your code) also decays over 
time, and the individual note-clusters spread out a bit. Looking at the 
log, there's also some drift in where setInterval is starting each 
INTERVAL. That's obviously what you meant by
> and really, you need some lookahead past that, in case the timers are 
> skewed a bit (aka the setInterval callback is late).
I'm not at all happy with an indeterminacy of around 200ms, and I know 
that passing small delays to setInterval  is something one shouldn't 
expect to work. So there's no way I can get to anything like 1 
millisecond accuracy by using setInterval or setTimeout non-recursively.

Hope that makes sense. If not, I'm all ears.

This being the case, I think it would be worth taking a closer look at 
including Tracks and Sequences in the API. I've done that in a separate 
posting. this one is long enough already.

all the very best,
James

[1] http://james-ingram.de/tests/JazzMIDIBridge/ji-known-sequence6.html
Received on Saturday, 15 September 2012 12:13:28 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Saturday, 15 September 2012 12:13:32 GMT