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

Part II/1: Developing With Sfront

Sections

Introduction

Part II of the sfront reference manual is written for two audiences:

  • People who are writing end-user audio applications, such as sequencers, sound design tools, and streaming audio clients, and who want to use sfront instead of writing a Structured Audio decoder themselves.
  • People who are using sfront directly as a command-line tool, and want to add new functions to the program, such as audio output support for an unsupported operating system.

In this chapter, we introduce both audiences to developing code for sfront. We begin with a description of how to use the off-the-shelf sfront in simple end-user applications, and show the limits of this approach.

We then introduce the driver interface, a mechanism for adding application-specific code to sfront. The driver interface offers a more flexible way for application developers to use sfront in their programs. In addition, people wishing to add a new general-purpose feature to sfront can often use the driver interface, instead of directly modifying the sfront sources.

The chapter ends with a roadmap for the following two chapters, which describe the driver interface in detail. These chapters describe control drivers, which lets user C code directly control the sound generation process, and audio drivers, which handle moving audio-rate streams into and out of the sound engine.

 

Sfront in Applications

Some end-user applications have simple requirements for a sound-generation engine. For example, consider a program that is a graphical score editor, that lets users manually enter traditional music notation onto staves.

A common feature of score editors is an audio preview function, that lets users listen to rendered versions of the audio. The right panel shows a C language code fragment that implements the feature, for Linux systems.

The code on the right panel assumes that the application program has created a SASL file ss, that contains the notes values and durations from the graphical score in SASL notation.

The code also assumes that the program has created a SAOL file, sl, to orchestrate the score. Typically, the application will have a library of SAOL programs available, and includes a user-interface for mapping different musical lines to SAOL instruments.

The code on the right panel uses the ANSI C library call system() to execute other programs. As an ANSI library function, this method should work with any ANSI-compliant C compiler. However, the commands to be executed must exist on the platform.

Three programs are executed in sequence:

  1. sfront. The generated SAOL and SASL files are converted into a C file (sa.c, the default name). Note that the OS-specific audio driver linux is used to specify streaming audio output. A multi-platform application would substitute different drivers for each OS.
  2. gcc. Compiles the sa.c to create an executable. A multi-platform application would need to know the standard compiler for each OS.
  3. sa. The executable that generates the audio.

In practice, a production application would include additional code for error checking and file management, as described on the right panel.

Sample Code

#include <stdlib.h>

/* application first generates */
/* file "sl" holding the SAOL  */
/* program, and file "ss"      */
/* holding the SASL notes.     */


/* run sfront on sl and ss */

system(
"sfront -aout linux -orc sl -sco ss"
);

/* compile sfront's output */

system("gcc -O3 sa.c -o sa");

/* run executable */

system("./sa");


In Production Code:

[1] Write all files to /tmp, use
    tempnam() to create unique names,
    and delete files after use.

[2] Examine return value of system()
    call for errors. 

[3] Use POSIX and Windows replacements
    for system() for enhanced features.

[4] Redirect stdout and stderr for
    each command to a log file:

    system("sa >& /tmp/log");

[5] Make sure the complexity of the
    SAOL code in sl and the note 
    density of the score in ss 
    matches the speed of the CPU.

Adding Features to Sfront

The score transcription application described in the last section specifies the notes to be played in a static manner. It writes a SASL file, and then invokes sfront to create a sound engine that plays the file. The application also statically specifies the audio routing, by invoking sfront with the -aout linux option.

However, some end-user applications are a bad match for a static audio and control approach. Examples of such applications include:

  1. An Internet audio streaming application, that streams SASL or MIDI control events over an IP network and feed them into a running SAOL program.
  2. Interactive music production systems, where knobs and sliders need to be interactively linked to SAOL program variables, external input from a MIDI keyboard needs to be dynamically routed to different SAOL elements, and audio input and output streams need to be patched into the SAOL input_bus and output_bus.

For sfront to support these programs, application-specific code must be added to the sa.c file that sfront produces. A host program would still use system commands to prepare and launch the sa.c program, but the application-specific code in the sa.c program could handle the dynamic functions, perhaps by communicating to the host program using inter-process communication.

The sfront driver interface lets application developers add C or C++ code into the sa.c file in a standardized way. In addition to supporting application-specific uses for sfront, the driver interface is the mechanism for adding general-purpose sfront features that involve control and audio communication.

In the final section of this chapter, we introduce the concept of audio and control drivers. The next two chapters describe the process of writing control and audio drivers in depth.

 

The Driver Interface

The driver interface lets users specify, on the the sfront command line, the inclusion of C or C++ code into the generated C file. Two types of drivers are currently supported:

  1. Control drivers. Control drivers can insert SASL and MIDI commands into a running Structured Audio engine during each k cycle. The semantics of the control driver interface supports the simple creation of MPEG-4 compliant streaming decoders. The control driver API also includes data structures to inform the control driver about the SAOL program structure, as well as functions for reading variables and altering time. These supplementary calls support applications beyond streaming decoders, such as symbolic debugging, patch editors, and interactive sequencer programs.
  2. Audio drivers. Audio drivers can insert audio streams into running SAOL engines, via the SAOL input_bus, and can pipe audio streams out of the SAOL engine, via the SAOL output_bus. The audio driver API supports real-time, low-latency audio I/O, and can also be used for file I/O purposes.

To create a new driver, two tasks are involved. The larger task is to create the C or C++ code that is included into the sa.c file. This code includes a set of functions, described in the API, that are called by sfront at regular intervals. The control driver calls allow the driver to insert control data into the running program, while the audio driver calls let the driver pick up or deliver audio streaming data. During each function call, the driver can communicate with other processes running on the system, as well as read and write external hardware devices such as MIDI In ports.

In addition to creating the included C or C++ code, a new driver needs to be registered with sfront, so that -cin, -ain, and -aout flags recognize the driver. This registration task involves appending information to parsing functions in the sfront source files.

Current Limitations

At the current time, the audio and control driver APIs do not support adding new plug-in formats to sfront. The AudioUnit drivers work using private additions to the driver APIs. We intend to generalize these additions so that they will support other plug-in formats, and add them to the official control and audio driver APIs.

At the current time, only one control driver (specified by the -cin flag on the sfront command line) and two audio control drivers (an audio input driver, specified by the -ain flag, and an audio output driver, specified by the -aout flag) may be specified. However, the APIs have been designed to support future expansion to support multiple audio and control drivers, and we believe that adding this feature would not break backward compatibility for properly written drivers.

At the current time, the registration process requires recompilation of the sfront sources. Future enhancements will support adding new drivers to sfront without recompilation.

 

Next section: Part II/2A: Control Driver Overview

 

Copyright 1999 John Lazzaro and John Wawrzynek.