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

Part II/4: SAOL Wavetables

Sections

Core Opcodes:

doscil ftbasecps ftlen ftloop ftloopend ftsetsr ftsetbase ftsetloop ftsetend ftsr koscil loscil oscil speedt tableread tablewrite

Wavetable Generators:

buzz concat cubicseg data empty expseg harm harm_phase lineseg periodic polynomial random sample spline step window

Introduction

Sound generation methods often involve the playback of audio samples from large data buffers.

These buffers may contain computed waveforms, digital recordings of natural sounds, or may be a scratch pad memory for dynamic synthesis.

The SAOL language includes the table data type for implementing wavetable buffers. A wavetable stores a sample array and a header of related information (including table length, sample rate, and loop points) in one structure.

A set of core opcodes support wavetable playback. Other core opcodes read and write parts of the wavetable data structure. Wavetable generators may be used to initialize wavetable values at declaration.

We begin this chapter with an example that introduces wavetable operation. We then detail the table declaration syntax, and describe wavetable generators and core opcodes for the most common table applications.

We conclude with descriptions of the wavetable core opcodes and generators that are useful for programming at a low level of abstraction.

 

An Example

The second example in the tutorial in Part I uses a shaped sine wave instrument model. In the tutorial example, the sine wave is computed used an iterative algorithm and the envelope is computed using a core opcode.

The right panel shows another implementation of this instrument, that uses wavetables to generate the sine wave and the envelope. We use this example to introduce the basic usage of the table data type.

The wavetable used to generate the sinusoid, cyc, is declared as a global variable, and imported into the instrument vtone.

A table declaration includes instructions for setting the initial values of the table. In the declaration for cyc, the wavetable generator harm initializes the 128-sample wavetable with one cycle of a sine wave.

The wavetable shape holds the envelope for the instrument, and is declared in vtone. The lineseg generator, specialized for creating piece-wise linear envelopes, initializes shape.

The shape declaration shows that the parameters of a generator may be expressions. In this case, we use the standard name dur to customize the envelope to match the length of the note.

The code block for vtone is very simple. One i-pass statement converts the MIDI note number parameter into a frequency. One k-pass statement uses the core opcode ftsetsr to set the sample rate of the envelope wavetable.

The real work is done in the a-pass. Two core opcodes, doscil and oscil, play back the envelope and sine wave tables. The return values of these opcodes are multiplied to create the final waveform, which is sent to the output_bus.

The a-rate core opcode doscil plays a table back once. The opcode does sample rate conversion between the sample rate of the table and the global sample rate.

The a-rate core opcode oscil plays a table back in a loop, treating the table as a single cycle of a periodic waveform.

By default, the table playback core opcodes uses linear interpolation.

We used the SASL file from the second tutorial example to drive the vtone instrument. If you are connected to the Internet, and if your web browser supports WAV file playback, you can click here to listen to audio output created using sfront.

We also used sfront to create a binary encoding of the SAOL and SASL file for this performance. This MP4 file is 399 bytes.

Note that this file is small, even tharray may be used only in an instrument, and holds the value of the audio input port. It's companion array, inGroup, codes the bus structure of the send statement that created the instance. See the code examples on the right panel for the semantics of inGroup.

In an instrument, inchan and outchan refer to the width of the audio input port and the audio output port of the instrument. In the global block, inchan refers to the width of the input_bus, and outchan refers the width of output_bus.

Bus Standard Names

ivar inchan;
asig input[inchannels];
ivar inGroup[inchannels];
ivar outchan;

InGroup Examples


// width of bus1: 4
// width of bus2: 2
// width of bus3: 1

send(test1; ; bus1);

// inside test1, standard name
// inGroup is width 4, and has 
// the value [1 1 1 1]

send(test2; ; bus2, bus3);

// inside test2, standard name
// inGroup is width 3, and has 
// the value [1 1 2]

send(test3; ; bus1, bus2, bus3);

// inside test3, standard name
// inGroup is width 7, and has 
// the value [1 1 1 1 2 2 3]


outbus and spatialize

The output statement is the primary way for an instrument to generate audio output. In this section, we describe two other a-rate statements that may generate audio output, the outbus and spatialize statements.

outbus

The outbus statement adds a value directly to a bus. This statement is useful for creating secondary bus structures that are independent from the main signal path flowing through the audio input and output ports of the instruments. These secondary buses may play a role similar to effects and monitor buses on audio mixing consoles.

The first parameter of the outbus statement is the bus name, and the remaining parameters are a list of expressions to add to the bus. The outbus statement has a width, which is the sum of the widths of its expression parameters. The right panel shows the syntax of the statement.

If the outbus statement has a scalar width, the value of the expression is added to each channel of the named bus. Otherwise, the width of the outbus statement must match the width of the named bus, and the array value formed by the concatenation of the expressions in the outbus statement is added to the named bus.

The outbus statement does not create new buses, and does not play a role in determining the width of buses. The statement can only write to buses that already exist: the output_bus, or user-defined buses created in send statements. If only outbus statements write to a user-defined bus, the send statement that creates the bus should declare the bus width explicitly.

An outbus statement may not appear in an instrument that is instantiated by a send statement that uses the output_bus. The outbus statement may not target the special system input_bus.

outbus

outbus(busname, exp1 [,exp2, ...]);

spatialize

The spatialize statement places a monophonic sound in the 3-dimensional space surrounding a listener. The spatialize statement bypasses the SAOL bus system entirely, and adds audio sample data to the final audio output.

The right panel shows the syntax of the spatialize statement. The first parameter to spatialize is a scalar expression of the monophonic sound, and may be a-rate or slower.

The remaining parameters describe the position the monophonic sound should be placed in space. These parameters may be k-rate or slower.

The second parameter codes the azimuthal angle where the sound should be placed, in radians. Zero degrees is directly in front of the listener, and pi/2 is to right of the listener.

The third parameter codes the elevation angle where the sound should be placed, in radians. Zero degrees is in the horizontal plane of the listener, and pi/2 is directly above the listener.

The fourth parameter codes the distance the sound is from the listener, in meters.

All spatialize statements sum onto the final audio output of the system. As usual, the output_bus (or the output of the instance that is sent the output_bus) also sums onto the final audio output of the system.

The final audio output is clipped to [-1,1] at the end of the a-pass, and is then usually sent to a file (for storage) or to a D/A converter (for listening).

The method the spatialize statement uses to place sound is non-normative. The final audio result may sound different on different decoders.

spatialize

spatialize(audio, azimuth, 
           elevation, distance);

Summary

This chapter is the last chapter of Part II. In Part II, we have described most of the SAOL language in a detailed way.

Several statements and standard names that involve the control of instruments have been postponed until Part III/3, since a complete knowledge of SASL (Part III/1) and MIDI (Part III/2) is necessary to understand these structures.

In addition, we postpone a description of user-defined opcodes until Part IV/4. Part IV specializes in opcodes, and includes a complete description of the core opcode library, as well as a few language structures specialized for opcodes.

We also postpone a discussion of templates, a language feature for constructing families of instruments that share common code, until Part V/2.

Next: Part III: Instrument Control

 

Copyright 1999 John Lazzaro and John Wawrzynek. ./usr/share/doc/sfront/html/book/saol/wave/0000755000000000000000000000000011345323143017501 5ustar rootroot./usr/share/doc/sfront/html/book/saol/wave/index.html0000644000000000000000000014316311345323143021506 0ustar rootroot The MP4-SA Book: Part II/4: SAOL Wavetables

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

Part II/4: SAOL Wavetables

Sections

Core Opcodes:

doscil ftbasecps ftlen ftloop ftloopend ftsetsr ftsetbase ftsetloop ftsetend ftsr koscil loscil oscil speedt tableread tablewrite

Wavetable Generators:

buzz concat cubicseg data empty expseg harm harm_phase lineseg periodic polynomial random sample spline step window

Introduction

Sound generation methods often involve the playback of audio samples from large data buffers.

These buffers may contain computed waveforms, digital recordings of natural sounds, or may be a scratch pad memory for dynamic synthesis.

The SAOL language includes the table data type for implementing wavetable buffers. A wavetable stores a sample array and a header of related information (including table length, sample rate, and loop points) in one structure.

A set of core opcodes support wavetable playback. Other core opcodes read and write parts of the wavetable data structure. Wavetable generators may be used to initialize wavetable values at declaration.

We begin this chapter with an example that introduces wavetable operation. We then detail the table declaration syntax, and describe wavetable generators and core opcodes for the most common table applications.

We conclude with descriptions of the wavetable core opcodes and generators that are useful for programming at a low level of abstraction.

 

An Example

The second example in the tutorial in Part I uses a shaped sine wave instrument model. In the tutorial example, the sine wave is computed used an iterative algorithm and the envelope is computed using a core opcode.

The right panel shows another implementation of this instrument, that uses wavetables to generate the sine wave and the envelope. We use this example to introduce the basic usage of the table data type.

The wavetable used to generate the sinusoid, cyc, is declared as a global variable, and imported into the instrument vtone.

A table declaration includes instructions for setting the initial values of the table. In the declaration for cyc, the wavetable generator harm initializes the 128-sample wavetable with one cycle of a sine wave.

The wavetable shape holds the envelope for the instrument, and is declared in vtone. The lineseg generator, specialized for creating piece-wise linear envelopes, initializes shape.

The shape declaration shows that the parameters of a generator may be expressions. In this case, we use the standard name dur to customize the envelope to match the length of the note.

The code block for vtone is very simple. One i-pass statement converts the MIDI note number parameter into a frequency. One k-pass statement uses the core opcode ftsetsr to set the sample rate of the envelope wavetable.

The real work is done in the a-pass. Two core opcodes, doscil and oscil, play back the envelope and sine wave tables. The return values of these opcodes are multiplied to create the final waveform, which is sent to the output_bus.

The a-rate core opcode doscil plays a table back once. The opcode does sample rate conversion between the sample rate of the table and the global sample rate.

The a-rate core opcode oscil plays a table back in a loop, treating the table as a single cycle of a periodic waveform.

By default, the table playback core opcodes uses linear interpolation.

We used the SASL file from the second tutorial example to drive the vtone instrument. If you are connected to the Internet, and if your web browser supports WAV file playback, you can click here to listen to audio output created using sfront.

We also used sfront to create a binary encoding of the SAOL and SASL file for this performance. This MP4 file is 399 bytes.

Note that this file is small, even tharray may be used only in an instrument, and holds the value of the audio input port. It's companion array, inGroup, codes the bus structure of the send statement that created the instance. See the code examples on the right panel for the semantics of inGroup.

In an instrument, inchan and outchan refer to the width of the audio input port and the audio output port of the instrument. In the global block, inchan refers to the width of the input_bus, and outchan refers the width of output_bus.

Bus Standard Names

ivar inchan;
asig input[inchannels];
ivar inGroup[inchannels];
ivar outchan;

InGroup Examples


// width of bus1: 4
// width of bus2: 2
// width of bus3: 1

send(test1; ; bus1);

// inside test1, standard name
// inGroup is width 4, and has 
// the value [1 1 1 1]

send(test2; ; bus2, bus3);

// inside test2, standard name
// inGroup is width 3, and has 
// the value [1 1 2]

send(test3; ; bus1, bus2, bus3);

// inside test3, standard name
// inGroup is width 7, and has 
// the value [1 1 1 1 2 2 3]


outbus and spatialize

The output statement is the primary way for an instrument to generate audio output. In this section, we describe two other a-rate statements that may generate audio output, the outbus and spatialize statements.

outbus

The outbus statement adds a value directly to a bus. This statement is useful for creating secondary bus structures that are independent from the main signal path flowing through the audio input and output ports of the instruments. These secondary buses may play a role similar to effects and monitor buses on audio mixing consoles.

The first parameter of the outbus statement is the bus name, and the remaining parameters are a list of expressions to add to the bus. The outbus statement has a width, which is the sum of the widths of its expression parameters. The right panel shows the syntax of the statement.

If the outbus statement has a scalar width, the value of the expression is added to each channel of the named bus. Otherwise, the width of the outbus statement must match the width of the named bus, and the array value formed by the concatenation of the expressions in the outbus statement is added to the named bus.

The outbus statement does not create new buses, and does not play a role in determining the width of buses. The statement can only write to buses that already exist: the output_bus, or user-defined buses created in send statements. If only outbus statements write to a user-defined bus, the send statement that creates the bus should declare the bus width explicitly.

An outbus statement may not appear in an instrument that is instantiated by a send statement that uses the output_bus. The outbus statement may not target the special system input_bus.

outbus

outbus(busname, exp1 [,exp2, ...]);

spatialize

The spatialize statement places a monophonic sound in the 3-dimensional space surrounding a listener. The spatialize statement bypasses the SAOL bus system entirely, and adds audio sample data to the final audio output.

The right panel shows the syntax of the spatialize statement. The first parameter to spatialize is a scalar expression of the monophonic sound, and may be a-rate or slower.

The remaining parameters describe the position the monophonic sound should be placed in space. These parameters may be k-rate or slower.

The second parameter codes the azimuthal angle where the sound should be placed, in radians. Zero degrees is directly in front of the listener, and pi/2 is to right of the listener.

The third parameter codes the elevation angle where the sound should be placed, in radians. Zero degrees is in the horizontal plane of the listener, and pi/2 is directly above the listener.

The fourth parameter codes the distance the sound is from the listener, in meters.

All spatialize statements sum onto the final audio output of the system. As usual, the output_bus (or the output of the instance that is sent the output_bus) also sums onto the final audio output of the system.

The final audio output is clipped to [-1,1] at the end of the a-pass, and is then usually sent to a file (for storage) or to a D/A converter (for listening).

The method the spatialize statement uses to place sound is non-normative. The final audio result may sound different on different decoders.

spatialize

spatialize(audio, azimuth, 
           elevation, distance);

Summary

This chapter is the last chapter of Part II. In Part II, we have described most of the SAOL language in a detailed way.

Several statements and standard names that involve the control of instruments have been postponed until Part III/3, since a complete knowledge of SASL (Part III/1) and MIDI (Part III/2) is necessary to understand these structures.

In addition, we postpone a description of user-defined opcodes until Part IV/4. Part IV specializes in opcodes, and includes a complete description of the core opcode library, as well as a few language structures specialized for opcodes.

We also postpone a discussion of templates, a language feature for constructing families of instruments that share common code, until Part V/2.

Next: Part III: Instrument Control

 

Copyright 1999 John Lazzaro and John Wawrzynek. ./usr/share/doc/sfront/html/book/saol/wave/0000755000000000000000000000000011345323143017501 5ustar rootroot./usr/share/doc/sfront/html/book/saol/wave/index.html0000644000000000000000000014316311345323143021506 0ustar rootroot The MP4-SA Book: Part II/4: SAOL Wavetables

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

Part II/4: SAOL Wavetables

Sections

Core Opcodes:

doscil ftbasecps ftlen ftloop ftloopend ftsetsr ftsetbase ftsetloop ftsetend ftsr koscil loscil oscil speedt tableread tablewrite

Wavetable Generators:

buzz concat cubicseg data empty expseg harm harm_phase lineseg periodic polynomial random sample spline step window

Introduction

Sound generation methods often involve the playback of audio samples from large data buffers.

These buffers may contain computed waveforms, digital recordings of natural sounds, or may be a scratch pad memory for dynamic synthesis.

The SAOL language includes the table data type for implementing wavetable buffers. A wavetable stores a sample array and a header of related information (including table length, sample rate, and loop points) in one structure.

A set of core opcodes support wavetable playback. Other core opcodes read and write parts of the wavetable data structure. Wavetable generators may be used to initialize wavetable values at declaration.

We begin this chapter with an example that introduces wavetable operation. We then detail the table declaration syntax, and describe wavetable generators and core opcodes for the most common table applications.

We conclude with descriptions of the wavetable core opcodes and generators that are useful for programming at a low level of abstraction.

 

An Example

The second example in the tutorial in Part I uses a shaped sine wave instrument model. In the tutorial example, the sine wave is computed used an iterative algorithm and the envelope is computed using a core opcode.

The right panel shows another implementation of this instrument, that uses wavetables to generate the sine wave and the envelope. We use this example to introduce the basic usage of the table data type.

The wavetable used to generate the sinusoid, cyc, is declared as a global variable, and imported into the instrument vtone.

A table declaration includes instructions for setting the initial values of the table. In the declaration for cyc, the wavetable generator harm initializes the 128-sample wavetable with one cycle of a sine wave.

The wavetable shape holds the envelope for the instrument, and is declared in vtone. The lineseg generator, specialized for creating piece-wise linear envelopes, initializes shape.

The shape declaration shows that the parameters of a generator may be expressions. In this case, we use the standard name dur to customize the envelope to match the length of the note.

The code block for vtone is very simple. One i-pass statement converts the MIDI note number parameter into a frequency. One k-pass statement uses the core opcode ftsetsr to set the sample rate of the envelope wavetable.

The real work is done in the a-pass. Two core opcodes, doscil and oscil, play back the envelope and sine wave tables. The return values of these opcodes are multiplied to create the final waveform, which is sent to the output_bus.

The a-rate core opcode doscil plays a table back once. The opcode does sample rate conversion between the sample rate of the table and the global sample rate.

The a-rate core opcode oscil plays a table back in a loop, treating the table as a single cycle of a periodic waveform.

By default, the table playback core opcodes uses linear interpolation.

We used the SASL file from the second tutorial example to drive the vtone instrument. If you are connected to the Internet, and if your web browser supports WAV file playback, you can click here to listen to audio output created using sfront.

We also used sfront to create a binary encoding of the SAOL and SASL file for this performance. This MP4 file is 399 bytes.

Note that this file is small, even tharray may be used only in an instrument, and holds the value of the audio input port. It's companion array, inGroup, codes the bus structure of the send statement that created the instance. See the code examples on the right panel for the semantics of inGroup.

In an instrument, inchan and outchan refer to the width of the audio input port and the audio output port of the instrument. In the global block, inchan refers to the width of the input_bus, and outchan refers the width of output_bus.

Bus Standard Names

ivar inchan;
asig input[inchannels];
ivar inGroup[inchannels];
ivar outchan;

InGroup Examples


// width of bus1: 4
// width of bus2: 2
// width of bus3: 1

send(test1; ; bus1);

// inside test1, standard name
// inGroup is width 4, and has 
// the value [1 1 1 1]

send(test2; ; bus2, bus3);

// inside test2, standard name
// inGroup is width 3, and has 
// the value [1 1 2]

send(test3; ; bus1, bus2, bus3);

// inside test3, standard name
// inGroup is width 7, and has 
// the value [1 1 1 1 2 2 3]


outbus and spatialize

The output statement is the primary way for an instrument to generate audio output. In this section, we describe two other a-rate statements that may generate audio output, the outbus and spatialize statements.

outbus

The outbus statement adds a value directly to a bus. This statement is useful for creating secondary bus structures that are independent from the main signal path flowing through the audio input and output ports of the instruments. These secondary buses may play a role similar to effects and monitor buses on audio mixing consoles.

The first parameter of the outbus statement is the bus name, and the remaining parameters are a list of expressions to add to the bus. The outbus statement has a width, which is the sum of the widths of its expression parameters. The right panel shows the syntax of the statement.

If the outbus statement has a scalar width, the value of the expression is added to each channel of the named bus. Otherwise, the width of the outbus statement must match the width of the named bus, and the array value formed by the concatenation of the expressions in the outbus statement is added to the named bus.

The outbus statement does not create new buses, and does not play a role in determining the width of buses. The statement can only write to buses that already exist: the output_bus, or user-defined buses created in send statements. If only outbus statements write to a user-defined bus, the send statement that creates the bus should declare the bus width explicitly.

An outbus statement may not appear in an instrument that is instantiated by a send statement that uses the output_bus. The outbus statement may not target the special system input_bus.

outbus

outbus(busname, exp1 [,exp2, ...]);

spatialize

The spatialize statement places a monophonic sound in the 3-dimensional space surrounding a listener. The spatialize statement bypasses the SAOL bus system entirely, and adds audio sample data to the final audio output.

The right panel shows the syntax of the spatialize statement. The first parameter to spatialize is a scalar expression of the monophonic sound, and may be a-rate or slower.

The remaining parameters describe the position the monophonic sound should be placed in space. These parameters may be k-rate or slower.

The second parameter codes the azimuthal angle where the sound should be placed, in radians. Zero degrees is directly in front of the listener, and pi/2 is to right of the listener.

The third parameter codes the elevation angle where the sound should be placed, in radians. Zero degrees is in the horizontal plane of the listener, and pi/2 is directly above the listener.

The fourth parameter codes the distance the sound is from the listener, in meters.

All spatialize statements sum onto the final audio output of the system. As usual, the output_bus (or the output of the instance that is sent the output_bus) also sums onto the final audio output of the system.

The final audio output is clipped to [-1,1] at the end of the a-pass, and is then usually sent to a file (for storage) or to a D/A converter (for listening).

The method the spatialize statement uses to place sound is non-normative. The final audio result may sound different on different decoders.

spatialize

spatialize(audio, azimuth, 
           elevation, distance);

Summary

This chapter is the last chapter of Part II. In Part II, we have described most of the SAOL language in a detailed way.

Several statements and standard names that involve the control of instruments have been postponed until Part III/3, since a complete knowledge of SASL (Part III/1) and MIDI (Part III/2) is necessary to understand these structures.

In addition, we postpone a description of user-defined opcodes until Part IV/4. Part IV specializes in opcodes, and includes a complete description of the core opcode library, as well as a few language structures specialized for opcodes.

We also postpone a discussion of templates, a language feature for constructing families of instruments that share common code, until Part V/2.

Next: Part III: Instrument Control

 

Copyright 1999 John Lazzaro and John Wawrzynek. ./usr/share/doc/sfront/html/book/saol/wave/0000755000000000000000000000000011345323143017501 5ustar rootroot./usr/share/doc/sfront/html/book/saol/wave/index.html0000644000000000000000000014316311345323143021506 0ustar rootroot The MP4-SA Book: Part II/4: SAOL Wavetables

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

Part II/4: SAOL Wavetables

Sections