RE: sfront drivers and other topics

From: Michael Gogins (gogins@nyc.pipeline.com)
Date: Sun Aug 29 1999 - 21:45:30 EDT


A propos the discussion on drivers, attached is javadoc documentation for
Noise, my proposed Java interface to a shared library version of sfront.
Basically, the idea is that from Java, Noise just looks like a Java class
that compiles SAOL files to executable form and plays them. The C compiler
is hidden away inside Noise.

Note that in addition to the sfront drivers, which remain, 3 drivers need to
be added to sfront for adapting it to JavaSound. They are:

-cin JavaSound

Set into Noise a proxy for javax.media.sound.midi.ByteArrayOutputStream
written to by a javax.media.sound.midi.StreamGenerator. csysi_newdata calls
OutputStream.toByteArray() and then calls csysi_midievent.

-ain JavaSound

Set into Noise a proxy for javax.media.sound.sampled.TargetDataLine.
asysi_getbuf calls TargetDataLine.read().

-aout JavaSound

Set into Noise a proxy for javax.media.sound.sampled.SourceDataLine.
asyso_putbuf calls SourceDataLine.write().

I don't think there are any special difficulties here.

If my suggestion about abstract drivers were taken up, they might look like
the following. But note that this question of switchable drivers is separate
from the JavaSound requirements, which are more important.

typedef struct csysStruct
{
        int (*setup)(void);
        int (*newdata)(void);
        int (*midievent)(unsigned char *cmd,
                unsigned char *ndata,
                unsigned char *vdata,
                unsigned short *extchan,
                float *fval);
        int (*saslevent)(unsigned char *cmd,
                unsigned char *priority,
                unsigned short *id,
                unsigned short *label,
                float *fval,
                unsigned short *pnum,
                float **p);
        void (*csys_shutdown)(void);
}
csys;

typedef struct asysoStruct
{
        int (*setup)(long srate,
                long ochannels,
                long osize,
                char *oname);
        int (*putbytes)(unsigned char *c,
                int numbytes);
        int (*getbuf)(short *asys_ibuf[],
                long *isize);
        int (*putlong)(unsigned long val,
                int numbytes);
        void (*shutdown)(void);
}
asyso;

typedef struct asysiStruct
{
        int (*setup)(long srate,
                long ichannels,
                long isize,
                char *iname);
        int (*putbytes)(unsigned char *c,
                int numbytes);
        int (*putbuf)(short *asys_obuf[],
                long *isize);
        long (*getslong)(int numbytes,
                long *ret);
        int (*flushbytes)(int numbytes);
        int (*soundtypecheck)(char *d);
        void (*shutdown)(void);
}
asysi;

Each driver in the code would fill one of these structures in. At runtime,
during the parsing of the command options, one of these structures would be
selected for csin, ain, and aout, and its functions would be assigned to the
csys and asys functions, which would be global function pointers instead of
(as now) global functions. This, by the way, also would make it easy to run
multiple outputs or inputs, if the global function pointers were actually
null-terminated arrays of function pointers:

for(asyso_putbuf_type iterator = asyso_putbuf; iterator != 0; iterator++)
{
        (*iterator )(aysys_obuf, asys_obuf_size);
}

-----Original Message-----
From: John Lazzaro [mailto:lazzaro@cs.berkeley.edu]
Sent: Sunday, August 29, 1999 8:16 PM
To: saol-dev@media.mit.edu; saol-users@media.mit.edu
Subject: sfront drivers and other topics

Hi Everyone,

        Lots of interesting email on saol-devs in the past 24 hours
about sfront, given that a lot of the messages are convergent on a few
topics, I thought it made sense to reply in a single email that
was organized by issue:

-- A -double flag for sfront --
--------------------------------

        Eric Schierer and Michael Gogins have had an interesting
discussion on this over several postings -- totally apart from
generating floating-point audio output files, should there be a way to
get MP4-SA tools to do their computations in double-precision? Or
does this path lead to "embrace and extend"?

        John Wawrzynek brought up a pretty convincing reason to
implement a -double flag -- if you're an MP4-SA programmer who's
trying to figure out why a recursive filter program isn't working, a
-double flag is an indispensable debugging tool. In addition, if your
completed MP4-SA composition sounds great on your IEEE Standard FP
machine, but sounds bad when you add the -double flag, it might not
sound that good on a single-precision DSP with a non-standard
floating-point unit either.

        So, primarily a debugging aid, we'll be implementing a -double
switch in sfront, that will print a warning message about its
non-compliance when used.

-- Sfront win32 real-time? --
--------------------------------

> From: "Ross Bencina" <rossb@audiomulch.com>

> Just wondering if anyone has started work on supporting real-time audio
i/o
> for sfront on win32? [...]

        Here's the story on the "-cin win32" and "-aout dsound"
options on sfront. JohnW did an experimental version of real-time
audio output and MIDI control input for Windows this summer -- it was
the prototype project for developing the driver architecture in
sfront. The code he wrote (sfront/src/lib/asys/dsound.c for the audio
driver, sfront/src/lib/asys/win32.c for the control driver, and
sfront/src/lib/asys/{winmmp.c,winmmt.c} for the time drivers) runs
on a pretty limited OS/soundcard pairing, because it uses audio
functionality that was only supported in the latest DirectSound
versions. He ended up changing his OS from NT to Win98 Second Edition,
downloading the latest DirectSound off of microsoft.com, and upgrading
his soundcard to an SBLive value, to get it to work at all, and its
not very stable.

        He's not planning to do any more work on the driver in the
foreseeable future, since the (stable, relatively low-latency on a PCI
128 card) Linux drivers are what we now use for testing changes to the
sfront sound architecture. If someone feels that this experimental
driver is a good starting place for a robust Windows real-time audio
driver, you're welcome to use it -- if you'd rather start from
scratch, that's fine too.

-- The Audio Driver Interface --
--------------------------------

        Seems like there are several projects that are getting
under way to add audio (and probably control) drivers to sfront,
and everyone is starting to bump up against the current limits
of the driver interface. I actually did update the relevant
page of the manual when I did 0.37, to reflect the current
state of the interface:

http://www.cs.berkeley.edu/~lazzaro/sa/sfman/devel/driver/index.html

        Some of the issues seem to be:

-1- Sfront currently does the float -> signed short conversion
along with the clipping to 1.0/-1.0, before calling the audio
driver. Given some of audio driver projects wish to use 32-bit
floats as the core output representation (Richard Dobson and
Michael Gogins), there's a problem here.

-2- Right now, audio and control drivers can't take parameters
from the sfront command line -- the only way to have a
parameterized driver is to register several different driver
names that share the same code. (A WAV file writer that could
write many different flavors of WAV file under command-line control
could have problems).

-3- As shown on the HTML page, adding a new driver also requires
hacking several sfront C files as well (audio.c, control.c) in order
to register the driver.

-4- Only one audio input driver, audio output driver, and control
input driver may be specified on the sfront command line. Some
of the projects seem to want either [1] compile in multiple drivers
in an sa.c file, and select which one during execution (Michael Gogins)
or [2] specify multiple drivers running together, so that (say) audio
can be sent both to a soundcard and to a WAV file.

        If I were just to go off and solve these problems, here is
what I would do:

-1- Part of the registration process should be what datatype you want
your input/output buffers to be -- floats, signed shorts, 8-bit u-law,
ect. Sfront will generate the equivalent of
"sfront/src/lib/csrc/runtime.c" that is customized for the driver.

-2- I'll come up with a simple way to do parameters, probably by
setting up #define's for the audio driver to see that contain any
parameters the user entered.

-3- This one is harder than it looks -- if you look at audio.c,
there's a lot of information that a driver writer hacks into code,
like what gets printed for help commands, ect. The simplest solution
is probably a second stereotypical C file that audio driver writes,
that gets linked into sfront itself.

-4- Solving -4- is an extension of 1 -- the customized
sfront/src/lib/csrc/runtime.c can have multiple audio input and output
driver calls in parallel, under command-line control if necessary.

        Basically, these solutions fit into a few basic themes:

-A- Sfront and the sa.c files are C, not C++.

-B- Sfront and the non-driver parts of sa.c files need to be standard
ANSI C, that use no external facilities or libraries.

-C- Dynamically-generating C code to solve problems in an efficient
optimal way is better than including static C code that handles the
general case.

        Keeping these themes in mind, if anyone has:

-- Sfront driver projects they are considering doing that can't be
done because of specification show-stoppers that aren't on the list
above, or

-- Objections/suggestions to the proposed solutions above that fit
into the basic themes above.

        now is the time to post them to the list or send email to me
privately about it.

                                                        --john lazzaro





This archive was generated by hypermail 2b29 : Mon Jan 28 2002 - 11:46:35 EST