From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/3: Audio Drivers

Sections

Audio Driver Functions

asys_osetup  asys_isetup  asys_iosetup  asys_preamble  asys_putbuf  asys_getbuf  asys_main  asys_orun   asys_iorun  ksyncinit  ksync  asys_oshutdown  asys_ishutdown  asys_ioshutdown 

Introduction

In this chapter, we describe how to add support for new audio file formats and audio hardware devices to sfront. Adding a new format or device involves writing an audio driver that is included in the C file sfront creates.

Users select the new audio driver through the -ain and -aout command line options.

We begin the chapter by discussing the structure of an audio driver. We describe the functions that an audio driver declares to handle initialization, data movement, and synchronization.

We also describe how to register a new driver with sfront, so that a command-line invocation results in the inclusion of the audio driver into the sa.c file.

 

Driver Structure

An audio driver is a file containing a set of C functions. This file is embedded into the sfront executable during compilation, and is copied into the C program sfront creates. Look in sfront/src/lib/asys/ to see examples of audio driver files.

The right panel shows the set of functions contained in an audio driver. In this chapter, we describe the semantics for these functions.

Not all audio drivers use all of the functions listed on the right hand panel. Several factors determine the subset of functions that are in use:

  • User directives. Users may request that an audio driver to do audio output, audio input, or both. The functions a driver declares depends on this request. A driver uses the symbols ASYS_HASOUTPUT and ASYS_HASINPUT to determine its role.
  • Callback support. In many cases, a simple method suffices for the transfer of audio samples between the driver and sfront: the driver declares functions to send and receive data, and sfront calls these functions to do I/O. We call these simple drivers passive drivers. However, some operating systems use a callback technique for audio access: an application registers a function with the operating system, that is called whenever new data is needed for input or output. Sfront supports a second audio driver approach (called active drivers) to handle callback interfaces.
  • Synchronization. Audio drivers may define functions that act to keep the SAOL program execution synchronized with audio input and output. These functions also act to update the SAOL standard name cputime, which SAOL programs use to avoid output glitches.

Naming conventions

Audio drivers must be careful when defining functions, variables, and pre-processor symbols for its own use, to avoid name-space collisions.

Audio drivers may define elements that begin with asysn_drivername_  and ASYS_DRIVERNAME_ , where drivername is the name of the audio driver file (sans extension) located in sfront/src/lib/asys/

If ASYS_KSYNC exists, elements that begin with sync_  and SYNC_  are also permissible.

In addition, if ASYS_HASOUTPUT exists, elements that begin with asyso_ or ASYSO_ are permissible. If ASYS_HASINPUT exists, elements that begin with asysi_ or ASYSI_ are permissible.

If both ASYS_HASINPUT and ASYS_HASOUTPUT exist, elements that begin with asysio_ or ASYSIO_ are permissible.

Audio Driver Functions


(function arguments not shown)

Initialization

int asys_osetup();
int asys_isetup();
int asys_iosetup();

Passive Audio Output

int asys_preamble();
int asys_putbuf();

Passive Audio Input

int asys_getbuf();

Active Drivers

/* declared by driver */

void asys_main();  

/* called by driver */

int asys_orun();  
int asys_iorun();

Synchronization

int ksyncinit();
int ksync();

Shutdown

int asys_oshutdown();
int asys_ishutdown();
int asys_ioshutdown();

Initialization

Users select audio input and output drivers through the -ain and -aout command line options.

Depending on the selection, a particular audio driver may be required to supply audio input, audio output, or both audio input and audio output.

An audio driver determines its role in an sa.c file by detecting if certain pre-processor symbols have been defined, using the pre-processor utilities  ifdef  or  defined .

Specifically, if both ASYS_HASINPUT and ASYS_HASOUTPUT symbols are defined, an audio driver should perform audio input and audio output. If only one of these symbols is defined, the audio driver should only perform audio input (ASYS_HASINPUT defined) or audio output (ASYS_HASOUTPUT defined).

Initialization functions

An audio driver declares an initialization function, which is called at the start of program execution. The exact form of the initialization function depends on the status of ASYS_HASINPUT and ASYS_HASOUTPUT symbols; see the right panel for details.

The initialization function should perform the initial setup needed for the audio file type or the audio hardware. If this setup is successful, the function should return ASYS_DONE, a pre-defined constant. If driver setup failed, the function should return ASYS_ERROR.

The arguments passed by the initialization function describe the audio input and output environment; the argument list may include:

  • srate. Audio sampling rate of the SAOL orchestra.
  • ochannels. The number of output audio channels (equal to the pre-defined constant ASYS_OCHAN).
  • ichannels. The number of input audio channels (equal to the pre-defined constant ASYS_ICHAN).
  • *oname. The output file name, if applicable, or else NULL.
  • *iname. The input file name, if applicable, or else NULL
  • osample. Output data representation for a sample, see below.
  • isample. Input data representation for a sample, see below.
  • toption. Has the value ASYS_RENDER (offline processing), ASYS_PLAYBACK (real-time mode) or ASYS_TIMESYNC (alternative real-time mode). See the synchronization section for details. The pre-defined constant ASYS_TIMEOPTION has the same value as toption.

The exact argument list depends on the function type.

Audio data types

The audio driver states its data type preference as part of the registration procedure. This preference is coded in the osample and isample variables, which may take on the pre-defined constant values ASYS_SHORT (for 16-bit signed integers) or ASYS_FLOAT (for 32-bit floats).

The pre-defined constant ASYS_OTYPENAME has the same value as osample, and the pre-defined constant ASYS_ITYPENAME has the same value as isample.

The correct C keywords for the input and output datatypes are held in the symbols ASYS_OTYPE and ASYS_ITYPE, and may be used in variable declarations.

Driver identity symbols

In some situations, an audio driver may need to know the presence of other drivers active in the system. The symbols ASYS_OUTDRIVER_XX, ASYS_INDRIVER_YY, and CSYS_CDRIVER_ZZ are defined if an audio output driver, audio input driver, or a control driver is present in the system.

The actual strings for XX, YY, and ZZ are the fully-capitalized versions of the driver names (either the full symbol following -cin, -ain, and -aout, or the extension for filename drivers).

Run-time options

An audio driver may define command-line options. Users types these options when executing an sa.c program that contains the driver, to dynamically configure driver parameters (for example, setting a maximum file size).

The right panel describes audio driver parameters in detail.

Initalization Functions

The audio driver declares
one of three functions for
initialization, depending
on user requests. This 
function will be called
once, at the start of 
program execution.

If the user requests only
output driver service, the
symbol ASYS_HASOUTPUT is 
defined, and the driver
should declare:

int asys_osetup(int srate,
                int ochannels,
                int osample,
                char * oname,
                int toption) 

If the user requests only
input driver service, the
symbol ASYS_HASINPUT is 
defined, and the driver
should declare:

int asys_isetup(int srate, 
                int ichannels, 
                int isample, 
	        char * iname, 
                int toption)

If the user requests both
input and output driver 
service, both ASYS_HASINPUT
and ASYS_HASOUTPUT are
defined, and the driver
should declare:

int asys_iosetup(int srate, 
                 int ichannels,
                 int ochannels,
		 int isample,
                 int osample, 
		 char * iname, 
                 char * oname, 
                 int toption)

These functions should return
ASYS_DONE if the driver is 
able to operate, and ASYS_ERROR
if the initialization failed.

See left panel for description
of function parameters.

Audio Driver Parameters

An audio driver may parse the 
command line of its sa.c file
it is contained in, by accessing:

int asys_argc;
char ** asys_argv

An audio driver may define its own
command-line flags, so that users
can configure drivers at runtime.
A driver must use this convention:

  -asys_xxx[_yyy] [p1 p2]   

where:

xxx   is the driver name
yyy   is the option name (if needed)
p#    is a parameter for the 
      option. options can have
      zero, one, or more than one
      parameters. a parameter can
      not start with a - (except
      as the sign of a number) 
      and may not contain spaces.

For example, the linux driver 
could define:

  -asys_linux_size p1

as an option for setting the size 
of the output data, where

  -asys_linux_size 8bit
  -asys_linux_size 16bit

are the legal parameter values. 

Passive Audio Output

In this section, we describe the functions asys_preamble and asys_putbuf (see right panel for function definitions). Passive audio drivers define these functions to handle audio output.

A passive audio driver does not always define the audio output functions: in some cases, the user may only wish to perform audio input. Passive audio drivers should define the audio output functions only if the symbol ASYS_HASOUTPUT is defined.

Basic operation

The asys_preamble function is called once, at the start of audio playback. The audio driver uses this call to allocate a buffer for audio data, whose location and size it returns to the calling program.

The first call to asys_putbuf returns this buffer to the audio driver, filled with audio sample data. The audio driver outputs the audio data, and returns a memory buffer to be filled with more samples. This cycle repeats until the program ends.

Starting Silence

An audio output driver that controls a soundcard device should output a period of silence to the soundcard during the asys_preamble call. The silent period provides an extra margin of time that sfront may use to compute new sound samples without overruning the soundcard. The silent period also sets the latency of the system.

The appropriate length to choose for the silence period depends on the application. Interactive applications demand latencies of a few milliseconds; audio playback applications work best with several hundred milliseconds of latency.

The pre-defined symbol ASYS_LATENCYTYPE indicates the application type, taking on values ASYS_HIGHLATENCY (audio streaming) or ASYS_LOWLATENCY (real-time interaction).

Audio drivers may use the application type to determine an appropriate latency value, or may use the suggested latency value ASYS_LATENCY, which is a floating-point constant with units of seconds. If the pre-defined symbol ASYS_USERLATENCY is set to 1, the value of ASYS_LATENCY is a user suggestion; if ASYS_USERLATENCY is set to 0, the value is a system default value.

Buffer Management

Passive audio output drivers set the nominal buffer size of an audio output operation, by choosing the return value of *osize in the asys_preamble and asys_putbuf functions.

In a real-time system, the buffer size should be set to be a small integral fraction of the starting silence period. For example, if a silent period of 3 ms is chosen, a good choice for the buffer size is the amount of storage needed to hold 0.75 ms of audio. This approach maximizes the efficiency of sfront execution, while minimizing the risk that a single late buffer can overrun the system.

Compute-Ahead Issues

If an sa.c program is set up as a real-time system, the penalty for computing audio buffers too slowly is obvious: if the interval between asys_putbuf calls is too long, the audio buffer may underrun, producing clicks and glitches.

However, computing audio buffers too quickly also brings problems. For interactive applications, computing ahead too quickly increases the latency between user action and sound output. For streaming applications, computing too far ahead results in too much memory usage to hold the future audio. To avoid these problems, real-time audio drivers should take steps to limit the compute-ahead of the program.

One way to limit the compute-ahead is to allocate a fixed number of buffers during the asys_preamble call, whose combined audio time equals the starting silence period. Buffers from this pool are passed to asys_putbuf to be filled, then passed to the soundcard to be played, which returns them once the audio plays out. If no free buffers are available to return to asys_putbuf, the audio driver sleeps until the soundcard returns a buffer.

This scheme limits the compute-ahead of the program, without the use of explicit timekeeping; it works best with soundcard interfaces such as OSS which maintain fixed buffer pools internally.

An alternative way to limit the compute-ahead is to explicitly keep track of elapsed time inside the audio driver, using operating system time functions. Audio drivers that use this approach may find it easiest to perform compute-ahead monitoring in the ksync function, described in a later section of this chapter.

asys_preamble

int asys_preamble(
    ASYS_OTYPE * asys_obuf[]
    int * osize
    ) 

Called once, at the start of
audio playback. When called, 
*asys_obuf will be set to NULL,
and *osize will be set to 0. 

On return, *asys_obuf must 
point to an array of ASYS_OTYPE,
and *osize must be set to the 
number of elements in the array 
to be filled with audio. The 
*osize value must be evenly 
divisible by the number of 
audio output channels, and 
must not be zero.

Return value should be ASYS_DONE
if preamble succeeded, ASYS_ERROR
to terminate the calling program.

asys_putbuf

int asys_putbuf(
    ASYS_OTYPE * asys_obuf[]
    int * osize
    ) 

asys_obuf points to an array
of audio samples to send to
the audio output. It is 
guaranteed to be filled on
channel-contiguous boundaries.

asys_obuf points to the buffer
returned by asys_putbuf() on
the previous call, or for the
first call to asys_putbuf(), 
the buffer returned by 
sys_preamble().

In most cases, *osize will be
identical to the requested
*osize from the last call.
In some cases (such as the
end of the orchestra) it may
be smaller (but never greater).

On return, *asys_obuf must point
to an array of ASYS_OTYPEs, and
*osize must be set to the number
of elements in the array to be
filled with audio. The *osize
value must be divisible by the
number of audio output channels,
and must not be zero.

Return value should be ASYS_DONE
if preamble succeeded, ASYS_ERROR
to terminate the calling program.

ASYS_TIMEOPTION

The pre-defined constant 
ASYS_TIMEOPTION codes the
temporal mode of the 
program. It may reflect
the presence of the 
-render, -playback,
or -timesync option on the
sfront command line; if
these flags do not appear
on the command line, sfront
chooses a default value.

The -render option requests
off-line file processing:
ASYS_TIMEOPTION has the
value ASYS_RENDER.

The -playback and -timesync
options requests real-time
processing: ASYS_TIMEOPTION
takes on the value 
ASYS_PLAYBACK or ASYS_TIMESYNC
in this case.

If an audio output driver 
that interfaces to a soundcard
finds that -render is in 
effect, it is probably a user
error: the program may ignore
the request, or may force an
exit via an ASYS_ERROR return
during initialization.

Passive Audio Input

Passive audio input drivers route audio input data from a sound file or audio device into the input_bus of a SAOL program.

The function asys_getbuf embodies the passive audio input driver. See the right panel for a complete description of this function.

An audio driver should only define the asys_getbuf function if the ASYS_HASINPUT symbol is defined, indicating the driver was selected via the -ain sfront command-line argument.

Buffer management

As described on the right panel, the calling program does not request a specific number of audio samples, and does not provide a buffer to fill.

Instead, the audio input driver is free to create an input buffering scheme that works well with the underlying file format or hardware device.

Compute-Ahead Issues

If an audio input driver supports a real-time input device, the asys_getbuf may be called before new input samples are ready.

In this case, the audio input driver should not return control to the calling program until the new samples are ready. If possible, the driver should block while waiting for new data, so that other processes may run on the machine.

Note that by holding control in the fashion, the audio input driver acts to prevent the SAOL program from computing ahead too far.

As a result, real-time passive audio drivers usually do not need to provide explicit compute-ahead protection if both ASYS_HASINPUT and ASYS_HASOUTPUT are defined.

asys_getbuf

int asys_getbuf(
    ASYS_ITYPE * asys_ibuf[],
    int * isize
    );

The function asys_getbuf is
called when the sa.c program
needs new input_bus samples
in order to continue SAOL 
processing. 

On the first call to asys_getbuf,
*asys_ibuf will be set to NULL 
and *isize will be set to 0. Upon
return, *asys_ibuf should point
to a buffer of *isize audio 
samples, filled with data from
the input device. ASYS_ITYPE is
is the sample type indicated by
isample during initialization.

On subsequent calls to asys_getbuf,
*asys_ibuf and *isize hold the 
values provided in the previous
call. Upon return, *asys_ibuf 
should point to a buffer of fresh
audio samples, of size *isize.

The contents of the buffer that
asys_getbuf should not be changed
by the audio driver until the next
call to asys_getbuf.

An *isize return value of 0 
indicates EOF.

asys_getbuf() should return 
ASYS_DONE if it was possible 
to process the request, 
including the EOF case.

ASYS_ERROR should be returned
for non-EOF error conditions
(filesystem error, etc).


Active Drivers

The passive audio driver concept is not a good match for a soundcard interface that uses callback semantics, such as MacOS X coreaudio.

In a callback architecture, applications supply a callback function to the soundcard interface as part of the initialization process. The soundcard interface invokes the callback function whenever an audio data transfer is needed.

To support callback semantics, sfront provides an active driver interface as an alternative to normal passive drivers. An audio driver identifies itself as passive or active as part of the registration procedure.

Users specify active drivers using the same -ain and -aout command line options as passive drivers use.

An active driver may be selected for input while a passive driver is selected for output, or vice versa; in addition, the same active driver type may be specified as the input and the output driver. However, two different different active drivers may not be selected for use at the same.

asys_main

Active output drivers declare the single function asys_main, shown on the right panel. This function is called after the SAOL program is initialized, and after all asys_setup functions are called.

Once asys_main is called, it is the responsibility of the active audio driver to control SAOL program execution; the driver exercises this control by calling a service function to compute audio samples. The audio driver exits the asys_main function once the SAOL program completes execution.

We first discuss active audio drivers that interact with SAOL programs that do not use the input_bus. In this case, the symbol ASYS_ACTIVE_O is defined, and the service function asys_orun is provided to compute new audio samples. See the right panel for a full description of asys_orun.

To support a callback system, an active audio driver would define a callback function for the soundcard interface to call. This callback function would in turn call asys_orun to generate the required number of audio samples on demand.

In this approach, the asys_main function would go to sleep once the callback function was installed. The callback function would awaken the asys_main function once the SAOL program ended, so that the asys_main function could return control to the calling program. The callback function becomes aware of the end of the SAOL program by checking the return value of the asys_orun function, which returns ASYS_EXIT once the program ends.

asys_main

void asys_main(void)

This function is called
after SAOL program 
initialization is complete,
and after all asys_setup
functions are called.

When asys_main returns, 
asys_shutdown functions
are called, and the program
exits.

asys_orun

int asys_orun(
    ASYS_OTYPE obuf[], 
    int * osize)

asys_orun is a service 
function, provided for use
by the active audio driver
if the SAOL program does
not use the input_bus. This
function exists if the 
symbol ASYS_ACTIVE_O exists.

asys_orun takes the sample
buffer pointer obuf as an
argument, writes at most
the next *osize channel-
interleaved sample values
into the buffer, and returns.

The *osize value received by
asys_orun must correspond to
an integral number of audio 
sample periods. The return 
value of *osize is the actual
number of ASYS_OTYPE
samples written into obuf. 

If the SAOL program is still
running, asys_orun returns
ASYS_DONE; if the SAOL program
has finished, asys_orun returns
ASYS_EXIT.

SAOL programs that use input_bus

If the SAOL program uses the input_bus, sfront provides the asys_iorun service function for active drivers to use (see right panel for details). This function accepts two audio buffers: an input array to route to input_bus, and an output array to hold generated output_bus samples.

An active audio driver senses the presence of the asys_iorun function by testing to see if the symbol ASYS_ACTIVE_IO is defined. If ASYS_ACTIVE_IO is defined, ASYS_ACTIVE_O is not defined, and asys_orun is not available.

If an active audio driver is expected to provide audio input and audio output from its device, the symbols ASYS_HASINPUT and ASYS_HASOUTPUT are defined. In this case, the driver simply passes the audio input to asys_iorun as it becomes available, and routes audio output to its device each time asys_iorun returns.

However, if ASYS_HASINPUT or ASYS_HASOUTPUT is not defined, the user has specified a passive driver for input or output. In this case, the active driver calls the passive driver functions, in keeping with the semantics of the audio passive driver interface.

For example, if ASYS_HASINPUT is not defined, the active audio driver calls the asys_getbuf function, and passes the buffer returned by this function to asys_iorun.

If ASYS_HASOUTPUT is not defined, the active audio driver calls asys_preamble to initialize the passive audio output driver, and then uses asys_putbuf to process the audio buffers returned by asys_iorun.

Basic information about the passive driver, such as channel size and sample data format, may be discovered by examining pre-defined constants such as ASYS_OCHAN and ASYS_OTYPE. See the initialization section for a description of these constants.

asys_iorun

int asys_iorun(
    ASYS_ITYPE ibuf[],
    int * isize,
    ASYS_OTYPE obuf[], 
    int * osize)

asys_iorun is a service 
function, provided for use
by the active audio driver
if the SAOL program uses
the input_bus. This
function exists if the 
symbol ASYS_ACTIVE_IO exists.

asys_iorun takes two 
audio sample buffers as
input. 

The buffer pointer
ibuf supplies audio input
data to route to the SAOL
input_bus. it contains 
*isize samples, which must
correspond to an integral
number of sample periods.

asys_iorun also takes 
the sample buffer pointer
obuf as an argument. it
writes, at most, the next
*osize channel-interleaved
sample values into the 
buffer, and returns.

asys_iorun handles any 
combination of *isize and
*osize buffers well -- 
it computes new audio
samples until ibuf is
exhausted, obus is fill,
or the SAOL program ends.

If the SAOL program is still
running, asys_iorun returns
ASYS_DONE; if the SAOL program
has finished, asys_iorun returns
ASYS_EXIT.

Synchronization

SAOL programs may read the k-rate standard name cputime, to sense the real-time performance of the program. This floating-point variables has a range of 0.0 to 1.0, and codes CPU utilization as in percentage terms. A cputime value of 1.0 indicates the edge of real-time performance: any additional load may cause a buffer overrun.

Audio drivers can take responsibility for estimating the cputime value seen by the SAOL program. A driver requests this task as part of the registration procedure; if this request is granted, the audio driver finds the symbol ASYS_KSYNC defined. See the right panel for details about the selection algorithm sfront uses for cputime duties.

If ASYS_KSYNC is defined, the audio driver defines the ksync and ksyncinit functions (see right panel for details).

The ksync function is called once per execution cycle, after all audio samples have been computed. The return value of ksync is the new estimate of cputime. The ksyncinit function is called once, right before SAOL program execution begins.

Computing cputime

To compute cputime, audio drivers estimate the real time used to compute the audio samples, and normalize by the total amount of audio generated during the cycle. The predefined floating-point constant KTIME indicates the length of audio generated each execution cycle, in units of seconds.

Compute-ahead issues

Audio drivers may need to actively limit the length of audio compute-ahead during program execution (we discuss compute-ahead issues in detail in an earlier section of this chapter). The ksync function is a convenient place to limit compute-head time.

To limit compute-ahead, the audio driver compares the elapsed real time with the computer audio time during each ksync invocation, and sleeps (or less preferably, spins) if the compute-ahead time exceeds the desired latency of the system.

A user may explicitly request this type of active compute-head limit, by using the -timesync sfront command-line option. If this option is selected, the constant ASYS_TIMEOPTION has the value ASYS_TIMESYNC.

Selection Algorithm

Sfront allocates cputime
calculation chores using
the following algorithm.

If offline render mode is
in effect (ASYS_TIMEOPTION
set to ASYS_RENDER), the
cputime is always set to
0, and no audio driver 
is assigned cputime duties.

Elsewise, the audio
output driver has first
priority for cputime
calculation, the audio
input driver has second
priority, and a default
UNIX-only algorithm for
cputime calculation is
used if neither audio
driver requests cputime
duties.

ksyncinit

void ksyncinit(void)

This function is called at
the start of SAOL program
execution. 

Audio drivers may use this
call to initialize global
state variables. Audio 
driver state variables and
functions related to 
synchronization should use
names that begin with sync_

ksync

float ksync(void)

This function is called at
the end of the audio 
output creation phase of
each execution cycle. 

The return value for this
function is the cputime
value presented to the
SAOL program during the
next execution cycle. It
should be a number in
the range [0.0, 1.0]

Shutdown

An audio driver declares a shutdown function, which is called at the end of SAOL program execution. Audio drivers use the shutdown function to cleanly close audio files and hardware devices.

The name of the shutdown function depends on the status of ASYS_HASOUTPUT and ASYS_HASINPUT, as described on the right panel.

Shutdown Functions

The audio driver declares
one of three functions for
shutdown, depending on its
role as an input driver,
output driver, or input and
output driver.

If the user requests only
output driver service, the
symbol ASYS_HASOUTPUT is 
defined, and the driver
should declare:

void asys_oshutdown(void)

If the user requests only
input driver service, the
symbol ASYS_HASINPUT is 
defined, and the driver
should declare:

void asys_ishutdown(void)

If the user requests both
input and output driver 
service, both ASYS_HASINPUT
and ASYS_HASOUTPUT are
defined, and the driver
should declare:

void asys_ioshutdown(void)

These functions should do
an orderly shutdown of the
audio hardware or file 
processing operations.

Registration

The right panel shows how to register your audio driver with the sfront sources. Registration is necessary in order for sfront to add your control driver flag to the permissible arguments to the -ain and -aout command line options.

Step 1: Create Libraries

[1] Place your audio driver foo
in sfront/src/lib/asys/mydriver.c

[2] cd sfront/src/lib

[3] Edit Makefile, and add 
name of your control driver
to the ASYS list. 

[4] Type "make". This will
create:

sfront/src/asyslib.c 
sfront/src/asyslib.h

which includes an embedded
version of your driver. Search
in the files for your driver
name to verify.

[5] Whenever you change your
driver code in sfront/src/lib/asys
you will need to remake the
asyslib.c file.

Step 2: Edit sfront/src/audio.c

In sfront/src/audio.c, make
these additions, to add driver
"mydriver".

[1] Add the constant definition

#define ADRIVER_MYDRIVER 

top the top of the file. Give it
the current numerical value of
ADRIVER_END, and then increase
the value of ADRIVER_END by 1.

[2] Add a printf line to the
function

void printaudiohelp(void)

that describes the mydriver
flags. This will be printed out
when "sfront -help" is invoked.

[3] Add if statements to the
aoutfilecheck and ainfilecheck
functions, to register the
driver. If the driver is an
active driver, add the lines

aoutflow = ACTIVE_FLOW;

to the aoutfilecheck addition
and add

ainflow = ACTIVE_FLOW;

to the ainfilecheck addition.
Also in ainfilecheck, set 
ainlatency to indicate 
interactive input (like a
microphone):
 
ainlatency = LOW_LATENCY_DRIVER;

or streaming input (like a
fileread):

ainlatency = HIGH_LATENCY_DRIVER;
 
[4] Add an entry for your driver
to:

  makeaudiotypeout  
  makeaudiotypein
  makeaoutsync
  makeainsync
  makeaouttimedefault
  makeaintimedefault
  makeainparams

if needed.

[5] Add your driver to:

void makeaudiodriver(int num)

  case DRIVER_MYDRIVER:
    makemydriver();
    break;

This call actually does the code
insertion into the sa.c file: it
calls the function created in 
asyslib.c from your driver file,
which is named makemydriver.

Step 3: Compile sfront

Type "make" in sfront/src to 
compile sfront with your driver.

During driver development, you 
should edit your original driver
source in

sfront/src/lib/asys/mydriver.c

then to test first:

cd sfront/src/lib/
make

and then:

cd sfront/src
make

Summary

For now, this is the end of the sfront reference manual. Soon, I hope to add new chapters describing sfront and sa.c internals.

Return to Table of Contents.

 

Copyright 1999 John Lazzaro and John Wawrzynek.