From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part III/3: SAOL Instrument Control

Sections

In This Chapter

Statements:

instr extend turnoff

Standard Names:

cpuload dur itime time released

Introduction

In the previous chapters in Part III, we describe the SASL and MIDI commands that create and control instrument instances. In this chapter, we describe SAOL statements that support instrument control.

We describe the SAOL instr statement, that supports dynamic instance creation. An algorithmic score generator may be written directly in SAOL using this statement.

We describe several SAOL standard names for status monitoring that are useful for algorithmic score generation.

These standard names hold information such as the elapsed time since instantiation, and whether an instrument is scheduled to be terminated before the next k-pass.

We describe several SAOL statements that let instances change their status. The turnoff statement lets an instance schedule its termination, while the extend statement lets an instance delay its termination.

Finally, we present a chart that shows the complete execution timeline of a SAOL program.

The timeline shows the order of events during program startup, as well as the sequencing of events during an orchestra cycle of i-pass, k-pass, and a-pass.

 

Dynamic Instruments

The SAOL instr statement performs dynamic instrument instantiation, so that a parent instrument may spawn copies of a child instrument. This statement supports applications such as sequencers, arpeggiators, and algorithmic composition.

The instr statement runs at the i-rate or the k-rate, and may not be used in the global block. The right panel shows the syntax for the SAOL instr statement.

The statement syntax begins with the keyword instr, followed by the name of the child instrument to instantiate.

The parameters are i-rate or k-rate scalar expressions that control the instantiation process. All expressions evaluate to constant values before the child instrument spawns.

The dly and dur parameters control the starting time and duration for the new instance.

The remaining parameters (p1, p2 ...) are the initial values for the instrument parameters of the new instance. The number of p parameters must match the number of instrument parameters in the new instance.

dly and dur

The dur parameter specifies how long (in scorebeats) the instance should execute before terminating. If dur has a value of -1, the instance runs indefinitely.

The dly parameter specifies the length of time (in scorebeats) to delay the instantiation of the new instrument.

If the dly parameter has a value less than the k-period (1/k_rate) the instrument is created as soon as the instr statement executes. The i-pass of the new instance is run immediately, and the following rules hold for the first k-pass and a-pass of the new instance:

  • If the instanced instrument occurs earlier in the execution order than the instrument containing the instr statement, the first k-pass and a-pass for the new instance are delayed until the next orchestra cycle.
  • If the instanced instrument does not occur earlier, the k-pass and a-pass of the new instance run in the current cycle.

If the dly parameter of the instr statement has a value greater than or equal to the k-period, the new instance is not created immediately.

Instead, a start time (in scorebeats) is computed for the new instance, by adding the dly parameter to the current score time. The instance is created when the score time exceeds this start time.

Rate Semantics

The instr statement may be an i-rate or a k-rate statement. It is an i-rate statement unless one of these conditions hold, in which case it runs at k-rate:

  1. Any of its parameters are k-rate.
  2. If the instr statement is enclosed in an if, if-else, or while statement and the rate of the guard expression of the enclosing statement is k-rate. It is an error if this guard expression is a-rate.

The right panel shows examples of the rate semantics of the instr statement.

Instr Statement


instr name(dly, dur [, p1, p2 ...]); 


name: name of the instrument 
      to instantiate

dly : delay time, in scorebeats, 
      before instantiation.

dur : duration (in scorebeats) of 
      instance execution. a 
      value of -1 codes indefinite
      execution.

p1, : values for instrument 
p2, : parameters to use for
... : instantiation.


Rate Semantics


instr spawn(num) {}


instr mom() {

ivar i1, i2;
ksig k1, k2;
asig a;


// runs at i-rate

instr spawn(0, i1, i2);


// runs at k-rate

instr spawn(0, i1, k2);


// instr runs at k-rate

if (k1 > k2) 
 {
   k1 = k1 - 1;
   instr spawn(0, i1, i2);
 }


// guard is a-rate
// breaks rule 2

if (a > 0) 
 {
   a = a - 1;
   instr spawn(0, i1, i2);
 }


// instr is i-rate
// if is k-rate
// breaks if rule 1

if (i1 > i2) 
 {
   k1 = k1 - 1;
   instr spawn(0, i1, i2);
 }

}

Instrument Status

Five SAOL standard names let an instance monitor its execution status. The right panel lists the full semantics for these standard names.

These standard names work in instances generated using any MP4-SA technique: SASL instr lines, SAOL instr and send statements, and MIDI note-on commands.

time and itime

The time standard name holds the creation time for the instance, measured in seconds. The itime standard name is the elapsed time since the instance was created. See the right panel for full semantics.

These two names support algorithmic scores, by letting an instance track simulation time and dynamically create other instances at the appropriate times.

dur

The expected duration of the instance, in seconds. An indefinite duration is indicated by -1. Although this standard name is an ivar. its value changes during the life of the instance, as explained on the right panel.

released

This standard name normally has a value of zero. If the instance is slated to be terminated at the end of the next series of a-passes, released takes on the value 1.

The released standard name is often used in conjunction with the extend statement (covered later in this chapter) to add a release phase to an instance created with a definite duration.

cpuload

This standard name is intended for applications where real-time decoding is needed, such as streaming audio to a D/A converter.

It tracks what percentage of system resources are currently being used, scaled to the amount of resources needed to maintain real-time operation. See the right panel for full semantics.

ivar time;

The time of instantiation for the
instance. In seconds, not scorebeats.
Zero seconds is start of simulation.

ksig itime;

The elapsed time since the instance
was created. In seconds, not 
scorebeats. Zero seconds is the
first k-pass. Note that (itime
+ time) is always the current 
absolute time.

ivar dur;

The intended duration (in 
seconds, not scorebeats) of
the instrument, as set by
the duration parameter in the 
SAOL instr statement
or SASL instr command.

MIDI and send instances
always set dur to -1. SAOL and
SASL instr commands may also
set dur to -1. A -1 indicates
indefinite duration.

Although it is an ivar, the 
value changes to reflect tempo
changes and the extend
statement.

ksig released;

Set to 1 if the instrument is 
scheduled for termination after
the last a-pass of the current
cycle. Otherwise set to 0. 

ksig cpuload;

Measures the load on the CPU
that this instance in running
on most often. A value of
0 indicates an idle CPU. A 
value of 1 indicates that the
edge of real-time performance
has been reached. Temporal
dynamics of cpuload are 
decoder dependent.

The Extend Statement

An instance may delay its termination by executing the extend statement. This statement is often run in response to the setting of the released standard name.

The right panel shows the syntax for the extend statement. The statement has a single parameter delay, an i-rate or k-rate signed expression for the amount of time to extend or reduce the instance (in seconds, not scorebeats).

If an instance has a scheduled termination time, executing the extend statement adds the value of delay to that termination time. If the new termination time is less than or equal to the current simulation time, the extend acts like the turnoff statement (described in the next section).

If an instance has an indefinite termination time (i.e. a duration of -1) executing the extend statement sets the new termination time to be the current simulation time plus the value of delay. If delay is less than or equal to zero, the extend acts like the turnoff statement.

The dur standard name is updated to reflect the execution of the extend statement.

The extend statement may be an i-rate or a k-rate statement. It is an i-rate statement unless one of these conditions hold, in which case it runs at k-rate:

  1. The delay expression is k-rate.
  2. If the extend statement is enclosed in an if, if-else, or while statement and the rate of the guard expression of the enclosing statement is k-rate. It is an error if this guard expression is a-rate.

The extend statement may not be used in an instance created by a send statement that uses the output_bus.

Statement Syntax

extend(delay);

Example


instr lengthen() {

ksig done;

if (!done && released)
 {
   // runs at k-rate
   extend(0.5); 
   done = 1;
 }

}


The Turnoff Statement

An instance may force its own termination by executing the turnoff statement. The right panel shows the syntax of this k-rate statement.

The turnoff statement is particularly useful for instances that are not scheduled for termination automatically, such as instances created with the SASL instr command and the SAOL instr statement with a duration of -1.

If the turnoff statement executes during a k-pass, it schedules the instance to be terminated at the end of the following (not the current) orchestra cycle.

During the next (and "final") k-pass, the released standard name has a value of 1. An extend statement execution during this k-pass would delay instance termination.

The turnoff statement may not be used in an instance created by a send statement that uses the output_bus.

Statement Syntax

turnoff;

statement is k-rate

Example


instr random_duration() {

// instance lasts at 
// least 500 ms. and
// at most 2.5 sec

if (!released && 
    (itime - 1.5 > krand(1)))
 {
   turnoff;
 }

}

Decoder Execution Order

We conclude this chapter with a table showing the order of execution of a SAOL program, shown on the right panel.

The first part of the table covers the initialization of the simulation done at the start of execution.

The second part of the table covers a single orchestra cycle. Orchestra cycles are continued indefinitely until the end time of the simulation is reached (set by the SASL endtime command).

The third part of the table covers instance creation. The fourth part of the table covers the execution of an i-pass, k-pass, or a-pass of an instance.

Links in this table refers to section of the book that explains the operation in more detail.

This chapter completes Part III of the book. In Part IV, we take a comprehensive look at opcodes in SAOL.

Next: Part IV: Opcodes

I. Initial Execution Order

  1. Determine instrument order. Use this information to determine output width of instruments and the width of user-defined buses.
  2. Instance and run the i-pass of the startup instrument to initialize i-rate global variables.
  3. Initialize global wavetables.
  4. Create instances generated by send statements, and execute the i-pass of these instruments in the order dictated by the sequence rules.
  5. Set the absolute simulation time to zero. Set the score time to zero.

II. Orchestra Cycle Execution Order

  1. Check if the score time is less than or equal to the end time for the simulation. If it is, stop executing orchestra cycles.
  2. Any SASL instruments or dynamically generated instruments that are ready to start execution are created. The i-pass for each instance is run, in the order dictated by the sequence rules. Instruments are ready when their start time is less than or equal to the current score time, or if they are streaming events that have no timestamps that have been received since the last orchestra cycle.
  3. If any instances are ready for termination at the end of this orchestra cycle, the released flag is set for the instance. Instances are ready for termination when their end time is less than or equal to the current score time, or when they ran a turnoff statement in the last k-pass, or when they received a MIDI noteoff command.
  4. SASL control commands that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  5. SASL table commands that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  6. MIDI events that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  7. SASL or MIDI tempo commands that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  8. One k-pass and srate/krate a-passes are run for all the instruments in the program, obeying the execution order rules. At the start of each a-pass, buses are initialized, and during each a-pass, audio output is generated, following the semantic rules of the system buses.
  9. Instruments scheduled for termination are terminated, except if an extend statement was executed during its k-pass.
  10. The absolute time is advanced by the 1/krate, and the score time updated appropriately given the current tempo.

III. Instance Creation Execution Order

  1. Instrument parameters are initialized.
  2. All signal variables set to zero.
  3. All imports ivar signal variables are set to the value of their associated global variables.
  4. Wavetable generators are executed.
  5. All imports table wavetables (but not imports exports table wavetables) are initialized to the value of their associated global table or future table.

IV. [I/A/K]-Pass Execution Order

  1. Local signal variables declared at the rate of the pass with the imports tag are set to the value of their corresponding global variables, if any.
  2. All imports exports table wavetables are linked to their associated global wavetables. Note that changes made to imports exports wavetables during an a-pass by an instance may or may not be seen by other instances accessing the table until the next k-pass.
  3. All statements at the rate of the pass are executed.
  4. Local signal variables declared at the rate of the pass with the exports tag write their value to their corresponding global variables, if any.

Copyright 1999 John Lazzaro and John Wawrzynek.