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

# Part II/2B: Control Driver Data Structures

## Sections

- Introduction.
- SAOL Data Structures
  - SAOL Variables. Describes the structure used to describe SAOL variables.
  - Global Variables. The data structures and constants that describe SAOL global variables and future tables.
  - Instrument Information. Describes the `csys_instrstruct` fields.
  - SAOL Instruments. Describes the data structures that list all the instruments in a SAOL program.
  - Target Control Variables. An easier way to find imports control variables.
  - Instr Preset Numbers. Mapping instr names to MIDI preset numbers.
  - Sample Block Data. Data structures that list any sample blocks stored along with the SAOL file.
  - Audio Bussing. Data structures that expose the audio pathways of a SAOL program.
- Other Data Structures
  - SASL Labels. Data structures that list any SASL labels stored along with the SAOL file.
  - System Status. Runtime information available to the control driver.
  - AudioBIFS Standard Names. Control driver access to `params[]` and other AudioBIFS names.
  - Utility Functions. Functions available to the control driver.
  - Command Line Contents. Accessing command-line arguments from sfront and sa.c.
  - MIDI and SASL Constants. Constants useful for handling MIDI and SASL events.

## Types

csys_bussstruct, csys_instrstruct, csys_labelstruct, csys_presetstruct, csys_routestruct, csys_samplestruct, csys_sendstruct, csys_targetstruct, csys_varstruct

## Variables

absolutetime, csys_argc, csys_argv, csys_bus, csys_global, csys_instr, csys_labels, csys_preset, csys_route, csys_sample, csys_send, csys_sfront_argc, csys_sfront_argv csys_target, direction, endtime, globaltune, listenerDirection, listenerPosition, maxBack, maxFront, minBack, minFront, params, position, scorebeats, tempo,

## Introduction

Control drivers communicate SASL, MIDI, and special events to the `sa.c` program. To communicate an event such as the creation of an instrument instance or the updating of a global variable, the control driver needs to be able to specify the name of the instrument or variable, in a language that the main program understands.

This section describes the data structures, constants, and functions that are available to the control driver. These resources serve to map the ASCII name or MP4 symbol number of a SAOL element to an index number that the `sa.c` understands. These resources also supply information about the current state of the `sa.c` program, such as the current score time.

These resources are designed so that the control driver can be written to work with all SAOL programs. By searching through the data structures, the control driver can discover the variables, instruments, and other SAOL elements as part of its initialization (i.e. during the csys_setup call).

In this section, we first describe the resources that pertain to the SAOL program, and then describe the resources that reflect other aspects of the `sa.c` program.

##

## SAOL Variables

A SAOL instrument may have parameter variables and local variables. In addition, the global block of a SAOL program may define global variables, and future global table variables may be defined implicitly.

In the following sections of this chapter, we define data structures that describe SAOL instruments and SAOL global variables. Both of these data structures uses `csys_varstruct` to describe variables. The right panel shows this struct and explains its fields.

The most common reason for a control driver to examine a `csys_varstruct` is to find a particular variable, and then return its `index` value to the main program.

The other fields in `csys_varstruct` are attributes a control driver may need to search over to find the right variable to return. The `name` field is the ASCII name of the variable, useful for SAOL programs presented to sfront via the `-orc` option. The `token` field is the MP4 file symbol number for the variable, useful for SAOL programs presented to sfront via the `-bit` or `-bitc` options.

The remaining fields describe attributes of the variable, such as width, rate, and import status.

## `csys_varstruct`

`

    typedef struct csys_varstruct {
      int index;
      char * name;
      int token;
      int type;
      int tag;
      int width;
      int use;
    } csys_varstruct;

`

## Field descriptions

`

    int index:

      The value that the control driver
      function csys_saslevents() passes
      to the caller, to identify the
      variable. Also passed to service
      functions to identify a variable.

    char * name:

      The ASCII name of the variable,
      if one exists. If the SAOL program
      is part of an MP4 file without a
      symbol table entry for the variable,
      the name is a##, where ## is the MP4
      file token number for the variable

    int token:

      The MP4 symbol number for the
      variable in the MP4 file. This
      value may be -1 if the SAOL did
      not originate in an MP4 file, in
      some versions of sfront.

    int type:

      The type of the variable, which
      takes on one of these constant
       values:

      CSYS_IRATE
      CSYS_KRATE
      CSYS_ARATE
      CSYS_TABLE

      The values of these symbols are
      subject to change, so use the
      symbols to ensure future
      compatability. The type codes
      either the rate of the
      variable, or the fact that it is a
      table (tables are always i-rate).

    int tag:

      Special attributes a SAOL variable
      may have, one of:

      CSYS_NORMAL
      CSYS_IMPORT
      CSYS_EXPORT
      CSYS_IMPORTEXPORT
      CSYS_PFIELD

      The tag indicates if the SAOL
      variable has an imports or exports
      tag, or is a parameter field in
      an instr. If the variable has none
      of these, it is tagged with
      CSYS_NORMAL.

    int width:

      The width of the variable, for
      array signal variables. Scalars
      and tables have width 1.

    int use:

      Codes whether SAOL program could
      potentially read or write the
      variable.  Intended purpose is to
      let control drivers optimize for
      variables that are never read or
      never written. Values are:

      CSYS_UNUSED
      CSYS_READ
      CSYS_WRITTEN
      CSYS_WRITTEN_AND_READ

`

## Global Variables

The right panel shows the two data structures that describe the global variables and future tables in a SAOL program.

The first data structure is an array of `csys_varstruct` structs. It is designed for applications where the control driver does not know the contents of the SAOL program a priori, but needs to build a model of the program as it executes.

The CSYS_GLOBALNUM constant lets the control driver know how many global variables exist. If it is nonzero, it is also the size of the array `csys_global`.

Some control drivers may be written for a specific SAOL program in mind. For these programs, it may be easier to use the second data structure described on the right panel. This set of constants code the `csys_global[].index` value for every global variable directly.

## `csys_global`

`

    #define CSYS_GLOBALNUM ##

    csys_varstruct csys_global
      [max(1,CSYS_GLOBALNUM)];

    The symbol CSYS_GLOBALNUM holds
    the number of global variables
    (signal and table) in the array.
    The array csys_global[] holds the
    csys_varstruct elements
    that describes the variable.

    If CSYS_GLOBALNUM is zero, there
    are no global variables. A dummy
    csys_global[1] will be defined in
    this case.

`

## Global Constants

`

    In addition to the csys_global[]
    array, a global constant:

    #define CSYS_SASL_GBL_varName ##

    is defined for each global variable.

    varName is the ASCII name for the
    variable, or a## if the variable
    is in an MP4 file without a symbol
    table entry for the variable.

    ## is an integer that is the
    csys_varstruct index value for
    the variable varName.

`

## Instrument Information

The control driver may access several datastructures that refer to SAOL instrs. These datastructures use the `csys_instrstruct` struct, shown on the right panel, to describe an instrument.

The `csys_instrstruct` struct shares much in common with the csys_varstruct struct described in the last section. The `index` field of `csys_instrstruct` is returned to functions such as `csys_saslevent` to specify an instrument, while the `name` and `token` fields provide ASCII and MP4 file names for an instrument.

The remaining fields describe attributes of the SAOL instrument code, such as the parameter fields and local variables of the instrument, the output width of the instrument, and the ways the instrument are used in the Structured Audio file.

## `csys_instrstruct`

`

    typedef struct csys_instrstruct
    {
      int index;
      char * name;
      int token;
      int numvars;
      csys_varstruct * vars;
      int outwidth;
      int status;
    } csys_instrstruct;

`

## Field Descriptions

`

    int index:

      The value that the control driver
      function csys_saslevents() passes
      to the caller, to identify the
      instr. Also passed to service
      functions to identify a variable.

    char * name:

      The ASCII name of the instr,
      if one exists. If the SAOL program
      is part of an MP4 file without a
      symbol table entry for the instr,
      the name is a##, where ## is the MP4
      file token number for the instr.

    int token:

      The symbol number for the instr in
      the MP4 file. This value may be -1
      if the SAOL did not originate in an
      MP4 file, in some versions of sfront.
      Note that the startup instrument
      may not have a symbol associated
      with it -- use the status byte
      (see below) to locate the startup
      instrument.

    int numvars:

      The total number of pfields, local
      signal variables, and local table
      variables in the instr. Also
      available as the constant
      CSYS_instrName_VARNUM, with
      instrName matching the name
      string above.

    csys_varstruct * vars:

      An array, of size numvars, of
      csys_varstruct to
      describe each pfield and local
      signal or table variable.

    int outwidth:

      The width of the output()
      statements in the instr.

    int status:

      A status word that describes
      how the instr is used. Different
      bits in the status words are set
      to reflect each use of the instr.
      A bitwise AND of the status word
      with each constant below indicates
      the instr is used in the manner
      described:

      CSYS_STATUS_EFFECTS

          Indicates that the instr is
          used as an effects instrument,
          i.e. it is the target of a
          send() statement in the global
          block.

      CSYS_STATUS_SCORE

          Indicates the instr is used
          by a SASL score line. (for
          binary files, in either the
          configuration or streaming part
          of the file).

      CSYS_STATUS_MIDI

          Indicates the instr is used
          by a MIDI event (for binary
          files, in either the
          configuration or streaming
          part of the file).

      CSYS_STATUS_DYNAMIC

          Indicates the instr is the
          target of a SAOL instr
          statement.

      CSYS_STATUS_STARTUP

          Indictates the instr is the
          startup instr.

`

## SAOL Instruments

The right panel shows the two data structures that describe the instruments in a SAOL program.

The first data structure is the array `csys_instr`. It is designed for applications where the control driver does not know the contents of the SAOL program a priori. The driver may search `csys_instr` to discover the structure of the SAOL program.

The CSYS_INSTRNUM indicates the number of instruments in the SAOL program. The ordering of instruments in `csys_instr` has meaning: it denotes the execution order of the SAOL program.

Uses of the csys_instr array include:

- Looking up the index values for instruments to return in `csys_midievents()` and `csys_saslevents()` calls.
- Looking up the index values for imports variables in the `vars` field to implement labelled control statements (but see the next section for a more efficient data structure for this purpose).

In addition, several data structured described in later sections of this chapter index into `csys_instr[]`.

Some control drivers may be written for a specific SAOL program in mind. For these programs, it may be easier to use the second data structure described on the right panel. This set of constants code the `csys_instr[].index` value for every instrument directly, as well as the `csys_instr[].vars[].index` value for variables that may be targeted by labelled SASL control statements.

## `csys_instr`

`

    #define CSYS_INSTRNUM ##

     csys_instrstruct
         csys_instr[CSYS_INSTRNUM];

    CSYS_INSTRNUM is the number of
    instrument definitions in the
    SAOL or MP4 file. csys_instr
    is an array that describe each
    instrument.

    Useful facts about csys_instr:

    [1] csys_instr[x].index == x

    This fact can simplify coding
    of control driver applications,
    and will not be broken going
    forward.

    [2] The order of instruments
    in csys_instr[] is the execution
    order of the instruments in
    the SAOL program.

`

## Instr Constants

`

##

    In addition to the csys_instr[]
    array, a global constant:

    #define CSYS_SASL_INSTR_instrName  ##

    is defined for each instr.

    instrName is the ASCII name for
    the instr, or a## if the instr
    is in an MP4 file without a symbol
    table entry for the instr.

    ## is an integer that is the
    csys_instrstruct index value for
    the instr instrName. This number
    can also be used to index into
    csys_instr[].

    The symbol CSYS_SASL_NOINSTR can
    be used to specify the "no
    instrument."

    Instr Variable Constants

    If an instr has variables that
    are fair targets for a SASL
    labelled control statements
    (i.e. they are declared with the
    imports tag and do not have a
    matching global variable), there
    will be a definition for

    CSYS_SASL_IMPORT_instrName_varName

    Where instrName is the instrument
    name and varName is the variable
    name (ASCII or a## name, as described
    above for instrName).

    This constant will be the equal to

    csys_instr[].vars[].index

    however, note that

    csys_instr[].vars
     [CSYS_SASL_IMPORT_instrName_varName]

    does not produce valid data -- a
    search needs to be done to find the
    matching vars[] element.

`

## Target Control Variables

The instrument variables that may targeted by a SASL labelled control statement have several properties:

- Variables must be imports.
- Variables must be k-rate.
- Variables must be scalar (not arrays).
- Variables must be signal (not tables).
- Variables must not have a corresponding variable in the global block

Sfront uses these properties to construct the `csys_target` array, shown on the right panel, that lists all local variables of all instruments that may be targeted by labelled control statements.

Implementations of MP4 streaming decoders can search through this short array for a candidate variable, and send the appropriate labelled control events via the `midi_saslevent()` function.

## `csys_targetstruct`

`

    typedef struct csys_targetstruct
    {
      char * name;
      int token;
      int numinstr;
      int * instrindex;
      int * varindex;
    } csys_targetstruct;

    Describes a SAOL variable that
    appears as a local variable in
    one or more instruments, and that
    has the correct properties to be
    a target for a SASL labelled
    control statement.

    char * name:

        The name of the control
        variable, following the
        conventions of the name
        field of csys_instrstruct.

    int token:

        MP4 symbol number, that
        follows the conventions
        of the token field of
        csys_instrstruct.

    int numinstr:

        Number of instrs that have
        this variable in targetable
        form.

    int * instrindex:

        An array, of size numinstr,
        of indexes into csys_instr[],
        one for each instr that has
        the variable in a targetable
        form. The csys_saslevent
        function requires this number
        in the *id field for a
        labelled control statement.

    int * varindex;

       An array, of size numinstr,
       that gives the vars[].index
       value for the targeted
       variable. In other words

       instrindex[i] == x
       varindex[i] == y

       then the

       csys_instr[x].vars[].index == y

       for the element of vars that
       holds the targeted variable.
       Note that y doesn't index
       into the vars[] array itself.

       The csys_saslevent function,
       used for labelled control
       statements, required y in the
       *pnum field.

`

## `csys_target`

`

    #define CSYS_TARGETNUM ##

    csys_targetstruct csys_target
           [max(1,CSYS_TARGETNUM];

    CSYS_TARGETNUM is the number
    of instr variables that are
    targetable by control statements
    in the SAOL program.

    If CSYS_TARGETNUM is greater
    than zero, csys_target is an
    array that holds information
    about each targetable
    variable.

`

## Instr Preset Numbers

As explained in this section of the MP4-SA book, a SAOL instrument that is capable of being controlled by MIDI events has one or more preset numbers. A MIDI event stream sent to the `sa.c` program using the `csys_midievent` function should start with a series of PChange commands, that sets the MIDI preset number (and thus, the SAOL instrument) for each MIDI channel in use.

These PChange commands will be in a valid MP4 file that uses MIDI events in SA_access_units. However, some control driver applications may need to dynamically set the preset number for each MIDI channel.

For example, a program for selecting SAOL instrument voices to be controlled by an MIDI keyboard would let the user choose SAOL instrument voices for each MIDI channel. This program would send PChange commands via the `csys_midievent` function to make the instrument selection happen.

The `csys_presets` array shown the right panel provides the mapping between SAOL instruments and preset numbers. The array contains one entry for each preset number defined in a SAOL instrument definition (recall each instrument may have multiple preset numbers, but no preset number may be used by two instruments).

The `index` entry for each array element points into the `csys_instr` array. The `preset` entry is the preset number. The array is ordered by preset number.

## `csys_presetstruct`

`

    typedef struct csys_presetstruct {
      int index;
      int preset;
    } csys_presetstruct;

    Maps MIDI presets numbers to
    SAOL instruments.

    index:

        An index into array
        csys_instr coding
        the SAOL instr associated
        with preset number.

    preset:

        The preset number.

`

## `csys_presets`

`

    #define CSYS_PRESETNUM    ##

    csys_presetstruct csys_presets
         [max(1,CSYS_PRESETNUM)];

    The constant CSYS_PRESETNUM is the
    number of preset numbers defined
    in the SAOL program. If it is
    non-zero, then the array
    csys_presets holds information
    about each preset defined, using
    the csys_presetstruct fields
    described above.

    Elements in csys_presets are
    ordered with respect to preset
    number.

`

## Sample Block Data

SAOL wavetable declarations that use the sample wavetable generator are coded in an MP4 file by pointing to a sample event block that is encoded in the configuration block. SASL table commands in the configuration block that use the sample wavetable generator also point to a sample event.

These sample events have their own MP4 symbol number, and can be referenced by SASL table commands in the SA_access_unit event stream.

The `csys_samples` array holds information on all sample event blocks encoded in the configuration block.

Note that sfront writes all sample event blocks to WAV files in the local directory, which are read by the `sa.c` program during execution. The `csys_samples` array includes the name of that file.

## `csys_samplestruct`

`

    typedef struct csys_samplestruct
    {
      int index;
      int token;
      char * name;
      char * fname;
    } csys_samplestruct;

    Describes a sample event.

    Fields:

      int index:

         Index number for the
         sample event. Will be
         used by future special
         events.

      int token:

         The MP4 symbol number for
         the sample event in the
         binary file.

      char * name:

         An ASCII version of the
         symbol number for the
         sample event, in the
         form a##.

      char *fname;

         The name of the Microsoft
         WAV file that holds the
         sample block. This file
         is placed in the same
         directory as the MP4 file
         when sfront decodes the file.

`

## `csys_samples`

`

    #define CSYS_SAMPLENUM ##

    csys_samplestruct csys_samples
            [max(1,CSYS_SAMPLENUM)];

    CSYS_SAMPLENUM is the number of
    sample events in the
    configuration block. The array
    csys_samples[] holds information
    about each sample event.

`

## Audio Bussing

The global block of a SAOL program defines an audio signal processing path, through the use of send and route statements. This chapter of the MP4-SA book describes the audio pathway of SAOL programs in-depth.

Audio bus information cannot be directly used in any SASL or MIDI control driver event. However, to support control driver applications that create graphical descriptions of SAOL programs, and to support future special events, the control driver interface includes a set of data structures that reflect the audio path of a SAOL program. The right panel describes these data structures.

The primary data structure, `csys_bus`, describes each bus in the SAOL program, included the special output_bus and input_bus. Two secondary data structures, `csys_route` and `csys_send`, describe each send and route statement.

Note that no data structure exists that holds information about sequence statements. The order of instruments in the csys_instr array denotes the execution order of instruments, and implicitly codes all sequence statements.

## `csys_busstruct`

`

    typedef struct csys_busstruct
    {
      int index;
      char * name;
      int width;
      int oflag;
    } csys_busstruct;

    Describes a bus in a SAOL
    program.

    Fields:

      int index:

         The index value of
         the bus, to be used
         in future special
         events.

      char * name;

         The name of the bus.
         The special buses
         input_bus and
         output_bus will
         always appear as those
         strings. User-defined
         buses may be given names
         from the ASCII SAOL file,
         or tokenized names from
         the MP4-SA symbol numbers
         (i.e. a##).

      int width;

         The width of the bus.

      int oflag;

         The number of outbus()
         statements, in all
         instruments, that write onto
         this bus.

`

## `csys_bus`

`

    #define CSYS_BUSNUM ##

    csys_busstruct csys_bus
        [max(1,CSYS_BUSNUM)];

    CSYS_BUSNUM is the number
    of audio buses in the SAOL
    program. csys_bus is an
    array describing each bus.

    Note that

    csys_bus[i].index == i

`

## `csys_sendstruct`

`

    typedef struct csys_sendstruct
    {
      int instr;
      int nbus;
      int * bus;
    } csys_sendstruct;

    Describes a SAOL send statement.

    Fields:

     int instr:

       The instr the send statement
       creates, coded as an index
       into the csys_instr
       array.

     int nbus:

       The number of buses that
       make up the SAOL input[]
       standard name value sent
       to the instr.

     int *bus:

       An array, of size nbus,
       that lists the buses that
       make up SAOL input[]
       standard name value sent
       to the instr, in order.
       Each element of the array
       indexes csys_bus[].

`

## `csys_send`

`

    #define CSYS_SENDNUM ##

    csys_sendstruct csys_send
          [max(1,CSYS_SENDNUM)];

    CSYS_SENDNUM is the number of
    send statements in the global
    block of the SAOL program.
    csys_send[] is an array that
    describes each send statement.

`

## `csys_routestruct`

`

    typedef struct csys_routestruct
    {
      int bus;
      int ninstr;
      int * instr;
    } csys_routestruct;

    Describes a SAOL route statement.

    Fields:

     int bus:

       The bus the route statement
       writes, coded as an index
       into the csys_bus[] array.

     int ninstr:

       The number of instrs whose
       outputs are written to
       the bus.

      int *instr:

       An array, of size ninstr,
       that lists the instrs whose
       outputs form the value added
       to the bus, in order. Each
       element is an index into
       the csys_instr array.

`

## `csys_route`

`

    #define CSYS_ROUTENUM ##

    csys_routestruct csys_route
           [max(1,CSYS_ROUTENUM)];

    CSYS_ROUTENUM is the number of
    route statements in the global
    block of the program. The
    array csys_route[] describes
    each route statement.

`

## SASL Labels

The MP4 binary file format supports two different ways of coding SASL commands. The configuration block (`StructuredAudioSpecificConfig`) at the start of the MP4 file, which contains the SAOL program, may also hold a SASL score. holds the SAOL program, can also hold a SASL score. In addition, SASL lines can be coded in the `SA_access_unit` streaming events that follow the configuration block.

The control driver interface supports compliant execution of SASL events in `SA_access_unit`s. These events may include labelled SASL control statements whose labels are also used in SASL instrument commands in the configuration block.

The `csys_labels` array shown on the right panel holds information about all labels used in the SASL score in the configuration block.

The array elements are `csys_labelstruct` structs, which provides the ASCII name and MP4 symbol for the label. the index value for the label which should be used as an argument to `csys_saslevent` to identify the label.

The `csys_labels` array is of size CSYS_LABELNUM, and the numeric values for `csys_labels[x].index` is `(x+1)`. Thus, if a control driver wishes to create label values that are not used by any SASL commands in the configuration block, these labels should have a numeric value greater than CSYS_LABELNUM. Use the constant CSYS_NOLABEL to indicate an unlabeled event.

## `csys_labelstruct`

`

    typedef struct csys_labelstruct
    {
      int index;
      char * name;
      int token;
      int iflag[CSYS_INSTRNUM];
    } csys_labelstruct;

    Describes SASL labels used in
    the configuration block.

    Fields:

     int index:

       The value used in
       csys_saslevent calls
       to identify the label.

     char * name:

       The ASCII name of the
       SASL label. If the
       label is part of an
       MP4 file without a
       symbol table entry for
       the label, the name is
       a##, where ## is the
       MP4 symbol number.

     int token:

       The MP4 symbol number
       for the label. This
       number may be -1 if
       the SASL did not come
       from an MP4 file, in
       some versions of sfront.

     int iflag[CSYS_INSTRNUM]:

       For each instr k,
       iflag[k] is 1 if a SASL
       instr statement exists
       for the instr that uses
       this label; otherwise,
       iflag[k] is zero. The
       index position of iflag[]
       matches the index position
       of the csys_instr[]
       array that describes each
       instr in the SAOL program.

`

## `csys_labels`

`

    #define CSYS_LABELNUM  ##

    csys_labelstruct csys_labels
           [max(1,CSYS_LABELNUM)];

    CSYS_LABELNUM is the number of
    unique SASL labels in the
    configuration block of the
    MP4 file (or in the -sco
    ASCII file).

    If CSYS_LABELNUM is nonzero,
    csys_labels holds information
    about each label.

    Note that

    csys_labels[i].index == i + 1

    If a control driver wishes to
    create new label numbers, these
    numbers should be greater than
    CSYS_LABELNUM.

    The constant CSYS_NOLABEL codes
    that a statement is unlabelled.

`

## System Status

When a control driver sends a new MIDI or SASL event to the main program to execute, it does not include a timestamp value. Instead, the control driver checks the value of global variables that hold the current time, and uses this information to send new MIDI or SASl events at the correct time.

The right panel describes these internal variables and associated constants, that hold time and tempo information.

The variables are made available on a read only basis, so that the control driver can present new events at the correct time, notes will be played in tune, ect.

## Time Variables

`

    float scorebeats;

       The current time of the
       score, in units of
       score time (beats).

    float absolutetime;

       The current time of the
       score, in units of
       seconds.

    float endtime;

       The current ending time
       of the score, in units
       of score time (beats).

    float tempo;

       The current tempo, in
       beats per second.

`

## Time Constants

`

    ARATE

      Audio rate of the SAOL
      program, in units of
      Hz.

    ATIME

      1.0F/ARATE

    KRATE

      Control rate of the
      SAOL program, in units
      of Hz.

    KTIME

      1.0F/KRATE

    ACYCLE

      The number of audio
      cycles in a control
      cycle. An integer.

    CSYS_GIVENENDTIME

      Has the value 1 if
      the variable endtime
      was given in a SASL
      statement by the
      user, and thus should
      be respected. If 0,
      it is an estimate by
      sfront of the last
      note played.

`

## Tuning Variable

`

    float globaltune;

      Current tuning of the
      SAOL program. Default
      is 440Hz. It codes the
      frequency of A below
      middle C.

`

## AudioBIFS Standard Names

The MPEG 4 Systems standard includes the audio mixdown tool for MPEG 4 Audio, which is named AudioBIFS.

AudioBIFS uses a SAOL decoder to do audio processing. Several standard names are defined for use in AudioBIFS, including `params[128]`, an application dependent array that Structured Audio programs can read and write to communicate with the decoder.

To support writing control drivers that implement AudioBIFS functionality, the control driver may read and write the global variables shown on the right panel. These variables are the underlying SAOL state variables for the AudioBIFS parameters.

In practice, `params[128]` is the most useful AudioBIFS standard name for most control drivers. Since it may be an lval in SAOL programs, it serves as a standard syntax to communicate application specific data between a SAOL program and an decoder.

## AudioBIFS Variables

`

    float direction[3];
    float listenerDirection[3];
    float listenerPosition[3];
    float minBack;
    float minFront;
    float maxBack;
    float maxFront;
    float params[128];
    float position[3];

`

## Utility Functions

Most communication between a control driver and the main `sa.c` program is done via the `csys_midievent` and `csys_saslevent` functions. A secondary method of communication is via utility functions that the control driver may call.

At present, there is only one utility function, `csys_terminate`, that lets the control driver prematurely terminate the `sa.c` program, and print an error message on `stderr`. The right panel describes this function.

## `csys_terminate`

`

    void csys_terminate(char * message)

    Terminates the sa.c program,
    by printing the Run-Time Error
    banner on stdout. The string message
    is printed as part of the banner.
    sa.c will return -1 as
    its exit code.

`

## Command Line Contents

During initialization, the control driver may need to access the command-line options of the sfront invocation that created the `sa.c` file that created it. The control driver has access to these options in the `csys_sfront_argc` and `csys_sfront_argv` variables shown on the right panel.

These variables are copied from the `argc` and `argv` parameters of the `main` function for sfront. The `csys_sfront_argc` variable indicates the total number of arguments on the command line, including the word "sfront".

The `csys_sfront_argv` variable is an array of strings of size `csys_sfront_argc`. Each string is a command-line token, with separating spaces removed. Like all of the data structures available for inspection by the control driver, `csys_sfront_argv` and `csys_sfront_argc` may not be changed.

The control driver may also access the command line options of the `sa.c` program that contains it, by inspecting the `csys_argc` and `csys_argv` variables described on the right panel. The control driver may also define command line options for users to put on the `sa.c` command line in order to configure the control driver.

The right panel shows the syntax that these driver-specific command line options must follow.

In the section of this chapter that describes registering control drivers with sfront, we show how to communicate these options to users, by printing out help information when sfront executes. Alternatively, it could also print out help information during the `csys_setup` call during `sa.c` execution.

## `sfront` command line

`

    int csys_sfront_argc;
    char ** csys_sfront_argv;

`

## `sa.c` command line

`

    int csys_argc;
    char ** csys_argv;

`

## Command line convention

`

    A control driver may define its own
    command line arguments for the sa.c
    program (but not sfront). For driver
    xx, command line arguments must
    use the following convention:

      -csys_xxx[_yyy] [p1 p2]

    where

       xxx   is the name of the driver
       yyy   is the name of the option
             for the driver. this can
             be deleted if the driver
             only has one option.
       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 when used as the
             sign of a number) and may
             not contain spaces.

    Example:

    The linmidi driver could define:

      -csys_linmidi_transpose p1

    as an option for setting a constant
    transposition of MIDI note number. The
    same program could be invoked with
    transpositions an octave above or below
    normal by using the options:

      -csys_linmidi_transpose 12
      -csys_linmidi_transpose -12

`

## MIDI and SASL Constants

The description of the `csys_midievent` and `csys_saslevent` functions in the next section includes the definition of several constants related to MIDI and SASL. The absolute value of some of these constants were carefully chosen, so that they could be useful in parsing MIDI and MP4 files. Those constants are shown on the right panel, along with the numerical values.

Next section: Part II/2C: Writing the Control Driver.

## SASL Event Constants

    These map to SASL code
    numbers MP4 files.

    CSYS_SASL_INSTR    0x00
    CSYS_SASL_CONTROL  0x01
    CSYS_SASL_TABLE    0x02
    CSYS_SASL_ENDTIME  0x04
    CSYS_SASL_TEMPO    0x05

    These map to wavetable
    generator token numbers

    CSYS_SASL_TGEN_SAMPLE     0x6F
    CSYS_SASL_TGEN_DATA       0x70
    CSYS_SASL_TGEN_RANDOM     0x71
    CSYS_SASL_TGEN_STEP       0x72
    CSYS_SASL_TGEN_LINESEG    0x73
    CSYS_SASL_TGEN_EXPSEG     0x74
    CSYS_SASL_TGEN_CUBICSEG   0x75
    CSYS_SASL_TGEN_POLYNOMIAL 0x76
    CSYS_SASL_TGEN_SPLINE     0x77
    CSYS_SASL_TGEN_WINDOW     0x78
    CSYS_SASL_TGEN_HARM       0x79
    CSYS_SASL_TGEN_HARM_PHASE 0x7A
    CSYS_SASL_TGEN_PERIODIC   0x7B
    CSYS_SASL_TGEN_BUZZ       0x7C
    CSYS_SASL_TGEN_CONCAT     0x7D
    CSYS_SASL_TGEN_EMPTY      0x7E
    CSYS_SASL_TGEN_DESTROY    0x7F

## MIDI Event Constants

    The number of channels in MIDI

    CSYS_MIDI_NUMCHAN  16

    These map to MIDI command
    nibbles

    CSYS_MIDI_NOTEOFF  0x80
    CSYS_MIDI_NOTEON   0X90
    CSYS_MIDI_PTOUCH   0xA0
    CSYS_MIDI_CC       0xB0
    CSYS_MIDI_PROGRAM  0xC0
    CSYS_MIDI_CTOUCH   0xD0
    CSYS_MIDI_WHEEL    0xE0

    These map to MIDI controller
    numbers

    CSYS_MIDI_CC_BANKSELECT_MSB  0x00
    CSYS_MIDI_CC_MODWHEEL_MSB    0x01
    CSYS_MIDI_CC_BREATHCNTRL_MSB 0x02
    CSYS_MIDI_CC_FOOTCNTRL_MSB   0x04
    CSYS_MIDI_CC_PORTAMENTO_MSB  0x05
    CSYS_MIDI_CC_DATAENTRY_MSB   0x06
    CSYS_MIDI_CC_CHANVOLUME_MSB  0x07
    CSYS_MIDI_CC_BALANCE_MSB     0x08
    CSYS_MIDI_CC_PAN_MSB         0x0A
    CSYS_MIDI_CC_EXPRESSION_MSB  0x0B
    CSYS_MIDI_CC_EFFECT1_MSB     0x0C
    CSYS_MIDI_CC_EFFECT2_MSB     0x0D
    CSYS_MIDI_CC_GEN1_MSB        0x10
    CSYS_MIDI_CC_GEN2_MSB        0x11
    CSYS_MIDI_CC_GEN3_MSB        0x12
    CSYS_MIDI_CC_GEN4_MSB        0x13
    CSYS_MIDI_CC_BANKSELECT_LSB  0x20
    CSYS_MIDI_CC_MODWHEEL_LSB    0x21
    CSYS_MIDI_CC_BREATHCNTRL_LSB 0x22
    CSYS_MIDI_CC_FOOTCNTRL_LSB   0x24
    CSYS_MIDI_CC_PORTAMENTO_LSB  0x25
    CSYS_MIDI_CC_DATAENTRY_LSB   0x26
    CSYS_MIDI_CC_CHANVOLUME_LSB  0x27
    CSYS_MIDI_CC_BALANCE_LSB     0x28
    CSYS_MIDI_CC_PAN_LSB         0x2A
    CSYS_MIDI_CC_EXPRESSION_LSB  0x2B
    CSYS_MIDI_CC_EFFECT1_LSB     0x2C
    CSYS_MIDI_CC_EFFECT2_LSB     0x2D
    CSYS_MIDI_CC_GEN1_LSB        0x30
    CSYS_MIDI_CC_GEN2_LSB        0x31
    CSYS_MIDI_CC_GEN3_LSB        0x32
    CSYS_MIDI_CC_GEN4_LSB        0x33
    CSYS_MIDI_CC_SUSTAIN         0x40
    CSYS_MIDI_CC_PORTAMENTO      0x41
    CSYS_MIDI_CC_SUSTENUTO       0x42
    CSYS_MIDI_CC_SOFTPEDAL       0x43
    CSYS_MIDI_CC_LEGATO          0x44
    CSYS_MIDI_CC_HOLD2           0x45
    CSYS_MIDI_CC_SOUNDCONTROL1   0x46
    CSYS_MIDI_CC_SOUNDCONTROL2   0x47
    CSYS_MIDI_CC_SOUNDCONTROL3   0x48
    CSYS_MIDI_CC_SOUNDCONTROL4   0x49
    CSYS_MIDI_CC_SOUNDCONTROL5   0x4A
    CSYS_MIDI_CC_SOUNDCONTROL6   0x4B
    CSYS_MIDI_CC_SOUNDCONTROL7   0x4C
    CSYS_MIDI_CC_SOUNDCONTROL8   0x4D
    CSYS_MIDI_CC_SOUNDCONTROL9   0x4E
    CSYS_MIDI_CC_SOUNDCONTROL10  0x4F
    CSYS_MIDI_CC_GEN5            0x50
    CSYS_MIDI_CC_GEN6            0x51
    CSYS_MIDI_CC_GEN7            0x52
    CSYS_MIDI_CC_GEN8            0x53
    CSYS_MIDI_CC_PORTAMENTOSRC   0x54
    CSYS_MIDI_CC_EFFECT1DEPTH    0x5B
    CSYS_MIDI_CC_EFFECT2DEPTH    0x5C
    CSYS_MIDI_CC_EFFECT3DEPTH    0x5D
    CSYS_MIDI_CC_EFFECT4DEPTH    0x5E
    CSYS_MIDI_CC_EFFECT5DEPTH    0x5F
    CSYS_MIDI_CC_DATAENTRYPLUS   0x60
    CSYS_MIDI_CC_DATAENTRYMINUS  0x61
    CSYS_MIDI_CC_ALLSOUNDOFF     0x78
    CSYS_MIDI_CC_RESETALLCONTROL 0x79
    CSYS_MIDI_CC_LOCALCONTROL    0x7A
    CSYS_MIDI_CC_ALLNOTESOFF     0x7B

Next section: Part II/2C: Writing the Control Driver.

Copyright 1999 John Lazzaro and John Wawrzynek.