|
From: Ian P. <ian...@in...> - 2002-05-25 21:10:18
|
Lex,
> That wasn't the issue. It was something along the lines of:
> StartRecording does not get called if CanRecordWhilePlaying is turned
> on.
Ok, thanks. I'll watch out for this.
> Right. Though using a sound server is nice, too. :)
I'll resist the temptation (for now) to air my observations about NAS
running over the net between different endian machines. ;-)
> There is a difference in the handling of stereo: with playback, monaural
> sounds are encoded as stereo but with one chanel always set to 0.
Ahh, I'd missed that one.
Err, then again... are you sure? Without digging as deeply as I should,
here's the beginning of playLoop:
| bytesPerSlice count willStop mayStop |
mayStop _ Preferences soundStopWhenDone.
bytesPerSlice _ Stereo ifTrue: [4] ifFalse: [2].
which seems to suggest that mono really is 1 channel.
> Also, I don't see why recording could not be stereo -- there is a flag
> for it in StartRecording.
I meant it's (currently) always set to mono in the image. (The support
code makes no assumptions about # of Squeak channels in either direction.
Everything is completely symmetric.)
> True, but in what case will this happen? The device should still be
> operating a fragment at a time.
Absolutely. There's no other way it can work, given that something is
eventually going to DMA all those samples. The problem is with select()
itself.
Try this:
- compile the attached program
- launch xmixer (or somesuch)
- select CD digital output as your recording source
- set all relevant in/out volumes so you'll here something from the CD
(analog CD and/or "monitor" at zero [if you have it] but PCM and
IGain turned up [just a little -- if you value your speakers ;])
- put a very calming CD into the drive (you'll need it ;)
- start the CD playing (with cdplay, or somesuch)
- run the program you just compiled.
If all is well you should hear music with no gaps, clicks, or repeated
fragments. The program should be printing lots and lots of `.'s
(indicating that select() is twiddling thumbs furiously) with the
occasional `r' and `w' interspersed (approx the same number of each).
On the other hand, if your OSS drivers are as broken as all those that
I've come across so far, you'll see something like this:
- lines of `rw.' with the cursor sitting mostly over the `w'. This
means that select() is saying the input device is readable even
when it isn't, and read is blocking on input.
or maybe:
- lots of repeated `.w<N' which means the input side of the device
is never being select()ed for read.
(The offending drivers ignore O_NONBLOCK too, just to add insult to
injury.)
FWIW, all of the OSS-based sound programs/daemons that I've downloaded and
autopsied in the last week (disregarding the trivial ones that just pump
data using blocking read/write) use clocked i/o rather than select().
FWIW #2, it was the first problem that started this saga. Squeak was so
stuck in blocked reads (blocking every time it did a quickCheckForIntrs)
that it became literally uninterruptable.
I wouldn't hesitate to put SIGALRM back into the VM (I've already got all
the code to implement ITIMER-based periodic "triggers") if I weren't so
terrified by the potential number of syscalls that might break from EINTR
and which are currently not checked (not to mention the amount of work
needed to resuscitate my slowly-rusting SunOS box to be absolutely sure
about it ;).
> The only bad case I can think of is
> because of the 100 frame limitation: the device may have 10 frames left
> in a fragment, but Squeak might refuse to use them. If that limitation
> were removed, then select() would work fine, wouldn't it?
I don't think so. It was one of the first things I tried. (I removed the
minimum limit altogether.) The only thing that did work was preventing
the output from being select()ed on each and every poll. (Failing
snd_Start when semaIndex > 0 makes the image use the old-style polling
loop. Then don't bother registering the dsp output fd with aio, and use
GETOSPACE in snd_availSpace. Works like a dream: Squeak eats zero CPU and
sound output is flawless. If the same aproach would worked for input
there would be no problem, but O_NONBLOCK is broken in several drivers
which also don't implement [or return garbage for] GETISPACE.)
So the problem really is in the totally broken interaction between the OSS
drivers and select().
I started fixing this for PowerBook (at least on the driver side) but
having been dropped into xmon for the Nth time due to a kernel exception
down in the bowels of do_select() I rapidly lost motivation for it. It's
the wrong (short-term) solution anyway: the OSS drivers are thoroughly
broken on PowerMac and NM256/AC97 (which crops up in a _lot_ of PC
hardware), and it's anybody's guess on how many others too. So I think it
makes more sense to assume an absolute minimum of functionality from the
OSS drivers (including the absence of select()) and then try to make the
VM code sufficiently intelligent to cope using only what's left.
(Or I could just give up right now and go make all my stuff compatible
with VMMaker instead, which was supposed to be the next thing on the
"to-do" list two weeks ago. ;-)
Ian
PS: A quick-and-dirty solution would be to spawn a thread to talk to the
device, connected to the VM through a pipe or two with which select()
could happily work. But this is total overkill.
|