From alsa-devel-owner@alsa.jcu.cz  Sat Feb 20 11:08:37 1999
Received: from smtp2.mindspring.com (smtp2.mindspring.com [207.69.200.32])
	by marvin.jcu.cz (8.9.1a/8.9.1) with ESMTP id LAA00788
	for <alsa-devel@alsa.jcu.cz>; Sat, 20 Feb 1999 11:08:28 +0100
Received: from [209.138.63.223] (pool-209-138-63-223.dlls.grid.net [209.138.63.223])
	by smtp2.mindspring.com (8.8.5/8.8.5) with SMTP id QAA19644
	for <alsa-devel@alsa.jcu.cz>; Fri, 19 Feb 1999 16:13:11 -0500 (EST)
Message-Id: <199902192113.QAA19644@smtp2.mindspring.com>
Subject: Re: More PCM/RT stuff (replies mostly)
Date: Fri, 19 Feb 99 15:14:01 -0000
From: Data <data@havoc.gtf.org>
To: <alsa-devel@alsa.jcu.cz>
Mime-Version: 1.0
Content-Type: text/plain; charset="US-ASCII"
Reply-To: alsa-devel@alsa.jcu.cz
Sender: alsa-devel-owner@alsa.jcu.cz
Precedence: list


Some replies to Mr. Van de Pol (and all other interested parties of 
course) 
about the sequencer/audio syncup ..

>Creating an ALSA timer that makes use of a PCM device would be
>the way to go.

Most definitely ..

>This fragment size is definitely some that should not be dictated by the
>sequencer but by the application that uses the PCM services. The fragment
>size is application and hardware dependent. For example when doing hard disk
>recording I'd prefer a larger fragment size (to prevent over/under-runs) then
>when using the machine for real-time effects.

True, but the fragment interrupt is the only _direct_ synchro source we 
have from the ADC clock.  To get the interrupt to appear at the right 
time 
we have to set the fragment size - therefore I suggested that the 
sequencer 
should set this.
  I don't think I mentioned the following idea last time, but I should 
have.
Perhaps we could set things up so that the _actual_ fragment used by the 
sequencer is different from that seen / set by the application.  That way 
the 
application could see an 'apparent' fragment size and use that for 
watching 
buffers / queues / etc.  Since the fragment size would actually vary if 
it 
were being used for an interrupt source (that is, if it were done _my_ 
way :) )
this would be horribly confusing for an application expecting to get the 
size it requested.  Letting the app see an 'apparent' fragment instead 
would 
solve this problem, at the expense of slight overhead.

>If I understood correctly it is possible to get an interrupt every fragment.
>At 44.1kHz/16bit/stereo playback this would give us next frequencies
>(freq=44100*2*2/fragsize)
>
>	fragment	frequency
>	--------	---------
>	128 bytes	1378 Hz
>	512		344 Hz
>	1024		172 Hz
>	4096		43 Hz
>
>With this popular audio format we would have betting timing resolution that
>the standard 100Hz clock on Intel platform when using a fragment size of
>1024 or smaller. 

Right, but this still requires us to poll the PCM queue pos.  The point 
of 
using the fragment interrupt is to obviate the need for polling at all.  
It 
would be better really to just use some other fixed-frequency interrupt 
source if we were going to poll.  Bear in mind also that for decent 
accuracy 
a polling routine would have to run far more often than would a simple 
int 
callback, and it would have the overhead of checks and comparisons 
besides, 
and wouldn't be as accurate.  That's why I don't like polling.

>Jaroslav, how about this 'workaround' to overcome timer limitations on Intel
>platform? Off subject: It might by the way also allow us to to get better
>MIDI output on (SoundBlaster!) MIDI hardware that does not generate TX
>interrupts.

.. but not when the DAC clock isn't running ..

>If the sequencer is clocked from PCM timer these two audio sources are
>always in sync, as the only master clock is the crystal clock of the codec:
>audio and MIDI in sync for free.

Right-O.

>> -- JK: --
>> We need add generic MTC/SMPTE support to sequencer code. Please,
>> keep this in your mind. 
>
>Indeed, and therefore the sequencer clock should be able to run asynchronous
>from the timing source. To synchronise the sequencer to an external source
>it would require adjusting the perceived period time for the sequencer -
>just about the same as is done when synchronising the computer's date to an
>NTP time server. This generic synchronisation is needed for both time (eg.
>MTC, and possibly PCM playback/recording - depending on timer source used)
>and song position (eg. midi clock) sources.

Yes, but the computer only has to adjust its date every day or so for 
reasonable accuracy.  To keep the sequencer clocked this way and not 
introduce 
bad jitter would require - I think - a lot of computation and overhead, 
since 
it has to be done so often.

>Data:
>> but I've been under the impression, from reading Mr. van
>> der Pol's proposal, that the intention was to leave that sort of thing
>> to clients.  However, I do think it would make good sense in this case to
>
>Please keep in mind that these sequencer clients can be interrupt driven
>kernel code, and also be as standard included in the sequencer kernel.

An excellent point.  I'll keep that in mind.

><SHUDDER> Brrrrr, I very much dislike that idea. Using SMPTE time would be
>very inefficient as we need to compare timestamps in many places (eg. in the
>priority queues). A simple high resolution linear time format (like the
>sec/nsec format) is really preferred for internal time stamps. No, using
>SMPTE as internal format is a bad plan.

I had not considered the problem of timestamp comparison.  But I don't 
think 
it would be so difficult to compare SMPTE timestamps.  Consider that 
SMPTE - as 
I would use it - has five fields: hour, minute, second, frame, subframe.  
At worst case we have five comparisons on a timestamp.  For example: if 
we have 
a timestamp that is 4:31:15:20:2, and we compare it to 5:22:18:19:1, we 
can see 
by looking at the hour fields only that the second is greater than the 
first.  
In the case where we compare, for example, 2:46:10:8:4 to 2:46:10:9:1, we 
must 
do four comparisons to determine that the second timestamp is greater 
than the 
first.  This could of course be optimised; but as a comparison is usually 
the 
same as a subtraction, it is not processor-intensive.
  On the other hand, converting seconds/nS to SMPTE requires at least one 
or 
two _divisions_ which are of course far more time-consuming.  Besides, 
doing 
compares with the present timestamps still can require more than one 
comparison.
I'm not sure that comparisons are as great a problem as divisions.

>> The thing I would like to know is how best to change the sequencer's
>> sync source; I suggest via ioctls, but there may be a way that better
>> fits the sequencer's design.  If need be I will be happy to code these
>> changes into the sequencer - they should not be especially difficult.
>
>I did not have any plans for that. An ioctl() interface seems most obvious
>to me, but perhaps the new ALSA ctl interface might be a good idea - I'm not
>sure on that, as it seems to me that it is meant for device configuration.
>Jaroslav, should application dynamicly fiddle with these ctl things?

I'll wait for more words from the Man on that one.  Mr. Kysela has said 
previously that it should be done with ioctls but perhaps the ctl 
interface 
would be a better way.  Others are more competent than I to judge this, I 
think.

>I like the idea of using asynchronous applications for these timing critical
>tasks instead of all being coupled. For each application the best trade-off
>can be made. Instead of polling PCM driver I'd suggest to fetch time from
>sequencer to make the MTC generator more generic. A disadvantage of using
>sequencer time over PCM time would be that the sequencer time is only
>updated periodically, and therefore it's granularity should be taken into
>account.

I like your idea of fetching time from the sequencer instead of the 
PCM driver.  This way an MTC generator would not have to worry about what 
the 
sync source is - that is properly the business of the sequencer core.

>Perhaps an other timing clock can be considered: the RTC (real-time clock)
>which is standard available on Intel systems and is capable of (but almost
>never used for) generating interrupts. Frequencies up to 8192 kHz should be
>possible, with 1024Hz being default. See Documentation/rtc.txt in the Linux
>sources for more information. This would also be a great candidate for the
>sequencer timer.

Hmm .. I will look in to that.  Seems that this could be implemented as a 
time source throughout ALSA, if it's standard on Intel hardware.  Of 
course 
we would have to consider other platforms as well.  I suppose timer.c 
could 
be made to use this RTC instead of the kernel interrupt if it found 
itself 
running on an IBM-compatible.

>Just some question: how much jitter is tolerable for this MTC
>synchronisation? It appears to me that you are worried about the error
>introduced by rounding off by one audio sample (ie. max 11.3 us at 44.1kHz)
>while the MIDI bytes are transmitted only at 31.25kb/s (32 us per bit). What
>is the problem? Even the best hardware sync box can't get better than this
>32 us. Are we chasing ghosts?

I must confess that I don't really know what the various systems will 
tolerate; but I can't imagine that constant 1 mS errors (out of 8 mS) 
would
be very good.
  I'm not a bit concerned about the _immediate_ error from rounding off a 
sample.  My main concern is the _accumulative_ effect of roundoff errors. 
 
For example, using a constant fragment size, and (for example) rounding 
up, 
would cause the sequencer to fall behind by half a sample time on every 
fragment interrupt.  This would be unnoticeable for a bit; but after a 
few 
seconds or minutes the sequencer would have fallen noticeably behind the 
audio stream.  This could, no doubt, be periodically corrected for; but 
this 
would require additional computation on the part of the sequencer.  I've 
suggested using a variable fragment since that would eliminate the need 
for 
that computation, and since it's always quicker (and easier) to 
precalculate 
the fragment sizes based on a known target, than it is to correct for 
errors 
after the fact.
  Don't worry, I'm a EE - I know quite well that jitter is a pest one can 
never be entirely rid of :)

>If this cycle counter can't generate interrupts and thus be used as a clock
>it won't do any good for synchronisation or sequencer purposes. It can only
>be used to get an (super) accurate timeofday, which is not relevant if we
>are syncing to an external source (eg. audio playback)

Well, at least for things like MIDI note sequencing it could be used to 
generate highly accurate clocktimes by oversampling it.  I know I've 
denigrated 
this method regarding audio, but here the data rate is much lower, low 
enough 
that polling is quite practical.  (I still don't like polling though :) )
  You're right though .. as a primary sync source it's useless if it 
doesn't 
generate interrupts.

>Is there any reason why we should be afraid of your code ? :-) 

Be afraid .. be _very_ afraid. 8-)

Cheerio
Michael Ashton

