Re: [linux-audio-dev] MIDI sync issues; mmc, mtc, ...

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] MIDI sync issues; mmc, mtc, ...
From: Paul Barton-Davis (pbd_AT_Op.Net)
Date: Fri Dec 22 2000 - 18:00:48 EET


>>>MTC-bytes in the audio loop, MTC accuracy depends on the used buffersize
>>>(1024 samples frames at 44100kHz -> 23ms per iteration).
>> Ah, but MTC is based on SMPTE, with a maximum resolution of 1 SMPTE
>> frame. The wall-clock time of a SMPTE frame varies, but the minimum
>> value is 1/30 sec or 33msecs. So as long as the fragment size is
>> smaller than 33msecs, there's no problem whatsoever with the accuracy.
>
>Hmm, here's a quote from the MTC "spec" (not the printed one, I'm not
>sure just how official this is):
>
>--cut--
>[...]
> SMPTE time. It's analogous to the MIDI Clock message. The Quarter
> Frame messages are sent at a rate of 4 per each SMPTE Frame. In other
> words, by the time that a slave has received 4 Quarter Frame messages,
> a SMPTE Frame has passed. So, the Quarter Frame messages provide a
> "sub-frame" clock reference. (With 30 fps SMPTE, this "clock tick"
> happens every 8.3 milliseconds).
>
> But the Quarter Frame is more than just a quarter frame "clock tick".
> The Quarter Frame message's data byte contains the SMPTE time (ie,
> hours, minutes, seconds, and frames). SMPTE time is normally expressed
>[...]
>--cut--
>
>So at least here MTC messages seem to have a twofold role. They both
>provide a "sub-frame" clock-reference (~8ms), and the actual absolute wall
>clock time. Now an implementation that sends bursts of MTC-bytes every
>23ms doesn't seem to fullfil the first requirement.

No, this is wrong. First of all, the Quarter frame messages do NOT
provide "subframe" reference. The Quarter frame message does NOT
contain SMPTE time - it contains 1 byte of the current SMPTE time. It
takes 8 such messages to establish a full SMPTE time, and as such,
there is always (as the spec notes), a 2 SMPTE frame delay in
establishing the curent SMPTE time based on quarter frame messages
only.

Second, the spec specifically allows for SMPTE->MTC converters to not
send every quarter frame; they note (1) that the frame count indicated
by quarter frame messages may not increment by 2 (as it "should") and
that (2) it is up to the MTC receiver to *always* looks at the actual
time indicated by the quarter frame messages rather than assume that
they can be used as a "clock tick".

I would expect that an MTC receiver might refuse to sync to a source
that was extremely erratic in its output of quarter frame messages.

>How about generating the MTC-bytes in the audio thread and putting
>them to a lock-free ringbuffer that's between audio and midi
>threads? Midi-thread would handle the actual i/o.

No, that part is fine. The problem is how to wake up the MIDI thread
quickly, and on time, without compromising the audio thread ?

>When sample data passes the engine (input -> processing -> outputs), there
>will be a delay before data is actually outputted from the soundcard. This
>would be between [frag_size,max_frags*frag_size]. If we have a soundcard
>with 64kB buffer, frag size of 4096B, and we want to fully use the
>soundcard's buffer (for instance, we are streaming one audio file to
>soundcard along with MTC_sync), we'll have a max delay of 16 fragments (at
>44100kHz rate -> 300-400ms).
>
>And of course, this delay is not static, but changes all the time. So the
>time used for sending MTC-sync should be 'engine_time - [0ms,400ms]'.

I think you can assume that in any real system, after a couple of
fragments have passed the delay is actually

          [max_frags-1*frag_size .. max_frags*frag_size]

since the buffer will be full. the drift from the upper value is
entirely a function of how much processing time the audio thread takes
to run after the interrupt is generated by the interface. assume for a
moment that the time between the interrupt and the audio thread
regaining control is zero, then you can more or less figure out the
rest for yourself by using the cycle counter. so, consider this:
     
        while (1) {
              poll (...);

              /* we know the effective audio frame time because
                 poll woke us up at a fragment boundary crossing.
               */

              rdtscl (now);
              
              /* now we know a reference point in absolute time */

              ... do audio thread stuff on a fragment ...

              rdtscl (then);

              /* now we know how long that took, which means we
                 know what the effective audio frame time is.
               */
         }

the only remaining part that is a problem that i can see is that the
time between the interrupt and the audio thread running again is *not*
zero. If you could assume that its really < 1 frame (20usecs at
48kHz), then you could assume that it was zero. But this might be
unrealistic. So I'm not quite sure how to solve this without resorting
to a query of the h/w pointer which is not necessarily accurate since
some h/w doesn't support it (and the device driver will simply be
reporting the position at the time of the last interrupt). Hmmmm ....

--p

              


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Fri Dec 22 2000 - 18:35:45 EET