From alsa-devel-owner@alsa.jcu.cz  Sun Feb 21 11:39:04 1999
Received: from smtp0.mindspring.com (smtp0.mindspring.com [207.69.200.30])
	by marvin.jcu.cz (8.9.1a/8.9.1) with ESMTP id LAA01803
	for <alsa-devel@alsa.jcu.cz>; Sun, 21 Feb 1999 11:37:11 +0100
Received: from [209.138.62.221] (pool-209-138-62-221.dlls.grid.net [209.138.62.221])
	by smtp0.mindspring.com (8.8.5/8.8.5) with SMTP id FAA06965
	for <alsa-devel@alsa.jcu.cz>; Sun, 21 Feb 1999 05:37:04 -0500 (EST)
Message-Id: <199902211037.FAA06965@smtp0.mindspring.com>
Subject: Re: More PCM/RT stuff (replies mostly)
Date: Sun, 21 Feb 99 04:37:54 -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


Fred Floberg deftly wrote:

>Just to complicate matters [:-)], what happens in the case of a system
>with multiple cards with midi ports? If you're going to sync a given
>midi port with its associated crystal oscilator and you have an app
>that wants to use several cards/hardware midi ports (such as the one
>I'm writing right now) the two midi streams will be out of sync with
>each other (won't they?), just as is the case with trying to use two
>separate cards for multi-channel audio input/output -- the crystal 
>oscilators on
>each card are not necessarily in sync with each other.

I figured that the multiple MIDI ports thing could be handled with the 
'client-only' design of the ALSA sequencer.  Selecting a synchronisation 
master would, I suppose, require something more - but I don't think it's
really a problem, technically speaking.  We have to have a way to select 
between sync sources anyway, whether they be PCM drivers, MIDI ports 
getting 
MTC from somewhere, etc. etc.  Of course that, too, might wind up being 
handled by sequencer clients.

>Has any thought been given to deciding which card in a multi-card set up
>will be used to provide timing interrupts?

Right now timer.c handles that.  You request a timer resolution, and it 
finds the timer that best fits your request.  If none of the soundcards 
have timers (or timer drivers, as the case may be) it uses the system 
timer.

>According to rtc.txt:
>
>"All PCs (even Alpha machines) have a Real Time Clock built into them."

Cool.  Maybe I should learn to read, I guess I'd learn something :)

Although .. isn't this RTC referring to the time-of-day chips present on 
most any PC?  Those aren't always terribly accurate, and don't always 
provide much in the way of resolution.  Anyway ..

>actually, as I understand that _some_ 486's may have an equivalent 
>instruction,

probably they're failed Pentiums ..

>As I say, I'm in the process of writing a midi music sequencer (called
>HyperSeq) which is inspired by Paul Barton-Davis's excellent SoftWerk 
>"analogue"
>midi sequencer emulator package http://www.op.net/~pbd/softwerk/softwerk.html

COOL!  I _love_ that program, bugs & all.  Haven't written any major 
world 
hits with it yet but it's a great bit of coding.
  I'm definitely looking forward to seeing your program, it
sounds like loads of fun.

>Fred "Frightened by his _own_ code" Floberg

that was cool :)

And then Mr. Barton-Davis wrote:

>On the other hand, as I've already discussed with Fred, there is an
>even more basic problem with multicard setups. I can see no way to get
>them both to be in sync. You've got to execute at least one
...

You've addressed two issues:

1. Triggering latency (inter-card)

Fortunately there's a (relatively) easy work-around for this one: 
merely use an offset for one of the cards - i.e. play a few samples ahead 
on one card, to compensate.
  Usually this is not much of a problem for multiple streams carrying 
spectrally unrelated signals (e.g. drums on one output, horns or 
something 
on another, etc.).  However, you could have phase problems for spectrally 
related signals.  The only thing I can think of where this might happen 
is 
if somebody were playing the left channel on one card and the right 
channel 
on another.  Why anybody would do that, I don't know.
  Now, actually the reason I have two soundcards is I wanted to be  
able to send SMPTE LTC out on one card, or use it for an effects send, 
using Multitrack.  But even in a situation like that the latency is no 
big deal - those errors are dwarfed by the other latencies in the system.

2. Clock mismatch

_This_ is the _real_ problem.  Clocks are always mismatched, not by much, 
but _any_ mismatch is enough to send sources out of sync after an 
extended 
period.  I ought to do a study on commonly available crystals and see 
what 
worst-case error would arise from two mismatched crystals at either end 
of 
the tolerance band.  Anyway I think it's possible that they would stay 
within reasonable range for a few minutes, but not after an 
hour or so of playback - that's just a guess though.
  The only way to get them to lock to each other is to sync one off of 
the 
other.  This could be done a couple of ways, none of them very nice.  The 
lazy way to do it would be to run both streams to both cards as usual, 
and 
retrigger the 'slave' card whenever the master sent its fragment 
interrupt, 
regardless of whether the slave was done playing its stuff or not.  The 
trouble is this would introduce artefacts into the slave's stream.  I 
don't 
know how bad they would be, but it would depend (I suppose) on just how 
far off the slave and master were from each other.
  The non-lazy way to do it would be to measure, at intervals, the 
difference 
between the two cards' actual sample rates, which could be done by 
measuring 
the length of time occurring between each card's fragment interrupt.  
This 
wouldn't have to be done at each interrupt - maybe every tenth one or so 
- 
besides, at first the difference would be tough to measure (although you 
know, 
it could be done with that nifty rtdsc instruction, couldn't it?  
hmm...).  
Then you would adjust the sampling rate of the slave stream to 
compensate.  
You'd do this by using drop-sample interpolation - some DSP would have to 
be 
done in the driver - not good.  Probably there's a slick way to handle it 
that wouldn't require such drastic measures.  Perhaps some samples could 
be 
dropped to compensate every so often, at some non-annoying interval.
By the way, these methods are applicable to more than two cards.
  So you see, there's ways around it, even though they're not very 
pretty.  
Now, in point of fact, it's absolutely impossible to synchronise two 
events 
exactly, without foreknowledge; but Mr. Einstein knows a bit more 
about that than I do, so I refer you to the source :)
  Another point I should make is that multichannel audio is a specialised 
application, usually requiring special (read: 'expensive') equipment.  
For 
eight channels, it's best to get a device designed to handle eight 
channels, 
rather than getting four cheap stereo soundcards and saddling the CPU 
with 
work it's not really much good at.  Now, such cards exist, and they can 
be 
put in PCs, and a few companies are bound to release programming info, so 
those who are serious about multichannel audio will invest in cards made 
for the job, and use those.  But cheap soundcards are, well, cheap, and 
you 
tend to get what you pay for.  It's certainly fun to make these devices 
do 
things they were never intended for, but people who depend on this stuff 
have far better options available.
  Of course, that's not the point.  The point is that we're going to make 
cheapo soundcards work in lock-step, because we _can_, and because 
some of us, being too broke to pay attention, haven't got many options, 
for the moment.  Do you know, I think poverty must be one of the most 
important reasons for the success of Linux, and free software in general, 
actually ..

>Warning! The kernel prevents the RTC ioctls from setting an interrupt
>rate much greater than HZ. You could get around this with your own
>module, but presumably Linus or someone else saw a good reason to
>prevent the RTC from being used in this way. I suggest you ask about
>this before using the RTC for high-frequency interrupts.

Rubini has an excellent discussion of this very issue in his book 
_Linux Device Drivers_.  If any of the programmers on this list don't 
have 
this book (well, ok, I borrow it from my roommate :) ) they should be 
ashamed of themselves, or really proud for being real men and learning 
by studying the kernel source code ..

Cheers,
Michael 'It's _way_ past my bedtime' Ashton

