Learning 12: Audio library and control

This page describes the Perlenspiel audio library, together with the commands for loading, playing, pausing and stopping sounds.

 

Audio library

Perlenspiel includes a built-in audio library containing nearly 400 sounds, including a full range of piano, harpsichord and xylophone notes, dozens of percussion instruments, and sound effects ranging from simple to silly.

A complete list of all library sounds is available here.

Each sound is identified by a unique lower-case string. For example, the string "fx_click" identifies a simple click effect. These strings are used in the filename parameter of the PS.audioLoad() and PS.audioLoad() commands (explained below) to specify which sound should be played.

The PS.audioPlay() and (optionally) PS.audioLoad() commands are often the only ones needed for projects requiring basic audio playback. Refer to the Advanced audio control section below if you need more control.

 

PS.audioLoad ( filename, options )

The sounds in the Perlenspiel audio library are stored on an Internet server, and can take a few moments to load if there's a lot of network traffic. The PS.audioLoad() command lets you preload an audio file from the server, making it available for immediate playback later, when you need it. It also provides access to information associated with the loaded sound.

The filename parameter should be a case-sensitive string matching the filename of the audio to be played, without a path specifier or file extension (example: "fx_click"). By default, the file is assumed to reside in the Perlenspiel Audio Library. Note that library filenames are all lower-case.

SAMPLE USAGE

PS.audioLoad( "fx_click" );

The options parameter provides additional capabilities explained in the Advanced audio control section below.

Usage notes

1. If you know your project will use a particular sound frequently, calling PS.audioLoad() in your PS.init() function will insure that the sound data will be available on demand.

2. Calling PS.audioLoad() for a sound that is already available in memory has no effect.

Demonstration

See PS.audioStop() below for a demonstration that uses PS.audioLoad() to preload sounds.

Return value

PS.audioLoad() returns PS.DONE, or PS.ERROR if an error occurs.

 

PS.audioPlay ( filename, options )

The PS.audioPlay() command begins playback of a specified sound file. It also provides access to information associated with the played sound.

The filename parameter should be a case-sensitive string matching the filename of the audio to be played, without a path specifier or file extension (example: "fx_click"). By default, the file is assumed to reside in the Perlenspiel Audio Library. Note that library filenames are all lower-case.

SAMPLE USAGE

PS.audioPlay( "fx_click" );

The options parameter provides additional capabilities explained in the Advanced audio control section below.

Usage notes

1. It is not necessary to explicitly preload a sound with PS.audioLoad() before playing it with PS.audioPlay(). If the sound specified in the call to PS.audioPlay() is not already available in memory, the engine will automatically load it, and begin playback immediately when the load is complete. For this reason, there may be a slight delay the first time a sound is played with PS.audioPlay().

2. If you have previously loaded a sound, either directly with PS.audioLoad() or indirectly with PS.audioPlay(), and subsequently specify the same sound in a call to PS.audioPlay(), the engine will use the preloaded sound data if it is still available in memory.

Return value

PS.audioPlay() returns PS.DONE, or PS.ERROR if an error occurs.

 

Advanced audio control

The options parameter of PS.audioLoad() and PS.audioPlay() lets you access additional information and functionality related to each instance of a sound.

If supplied, the options parameter should by an object containing one or more of the following case-sensitive properties:

See the API documentation for PS.audioLoad() for a detailed description of these properties.

If you want to pause, stop or fade a sound, you first need to obtain its channel ID.

A channel ID is a unique string automatically assigned to any sound loaded by a call to PS.audioLoad() or PS.audioPlay(). It can be accessed by using the options.onLoad parameter of either command.

Techniques for obtaining and using channel IDs are demonstrated below.

 

PS.audioPlayChannel( channel )

The PS.audioPlayChannel() command lets you play a previously established audio channel.

The channel parameter should be a channel ID previously returned by a call to an options.onLoad function assigned to PS.audioLoad() or PS.audioPlay().

If channel is playing, it will pause immediately. If channel is already paused as a result of a previous call to PS.audioPause(), it resumes playing at the point from which it was paused.

If channel is not playing, paused, stopped or invalid, nothing happens.

SAMPLE USAGE

let channel = ""; // variable to store channel ID

// Loader function called by PS.audioLoad()
// Saves channel ID of loaded sound

const loader = function ( result ) {
 channel = result.channel; // save ID
};

// Preload sound, save channel ID

PS.audioLoad( "l_piano_c5", { onLoad : loader } );

// Begin playback of preloaded channel

PS.audioPlayChannel( channel );

Demonstration

See PS.audioStop() below for a demonstration of how to use channel IDs to play, pause, unpause and stop channels.

Return value

PS.audioPlayChannel() returns its channel parameter upon successful completion, or the constant PS.DONE if an empty string is passed to its channel parameter.

PS.ERROR is returned if an error occurs.

 

PS.audioPause( channel )

The PS.audioPause() command lets you pause and restart a previously established sound channel.

The channel parameter should be a channel ID previously returned by a call to an options.onLoad function assigned to PS.audioLoad() or PS.audioPlay().

If channel is playing, it will pause immediately. If channel is already paused as a result of a previous call to PS.audioPause(), it resumes playing at the point from which it was paused.

If channel is not playing, paused, stopped or invalid, nothing happens.

SAMPLE USAGE

let channel = ""; // variable to store channel ID

// Loader function called by PS.audioLoad()
// Saves channel ID of loaded sound

const loader = function ( result ) {
 channel = result.channel; // save ID
};

// Preload sound, save channel ID

PS.audioLoad( "l_piano_c5", { onLoad : loader } );

// Begin playback of preloaded channel

PS.audioPlayChannel( channel );

// After playback has started ...

PS.audioPause( channel ); // pause it

// After sound is paused ...

PS.audioPause( channel ); // restart it

Demonstration

See PS.audioStop() below for a demonstration of how to use channel IDs to play, pause, unpause and stop channels.

Return value

PS.audioPause() returns its channel parameter upon successful completion, or the constant PS.DONE if an empty string is passed to its channel parameter.

PS.ERROR is returned if an error occurs.

 

PS.audioStop ( channel )

The PS.audioStop() command lets you halt playback of a previously established sound channel.

The channel parameter should be a channel ID previously returned by a call to an options.onLoad function assigned to PS.audioLoad() or PS.audioPlay().

If channel is playing, it stops immediately.

If channel is not playing, paused, already stopped or invalid, nothing happens.

SAMPLE USAGE

let channel = ""; // variable to store channel ID

// Loader function called by PS.audioLoad()
// Saves channel ID of loaded sound

const loader = function ( result ) {
 channel = result.channel; // save ID
};

// Preload sound, save channel ID

PS.audioLoad( "l_piano_c5", { onLoad : loader } );

// Begin playback of preloaded channel

PS.audioPlayChannel( channel );

// After playback has started ...

PS.audioStop( channel ); // halt playback

Demonstration

This demo creates an 8x3 grid representing one octave of piano notes. The top beads play a note, the middle beads pause/unpause a note in progress, and the bottom beads stop playback.

[Run Demo]

PS.init = function( system, options ) {
 PS.gridSize( 8, 3 ); // set up grid
 PS.borderColor( PS.ALL, PS.ALL, PS.COLOR_BLACK );
 PS.scale( PS.ALL, PS.ALL, 90 ); // scale down
 PS.radius( PS.ALL, PS.ALL, 50 ); // circle

 // Color top row of glyphs

 PS.glyphColor( PS.ALL, 0, PS.COLOR_WHITE );

 // Add pause/stop symbols to bottom rows

 PS.glyph( PS.ALL, 1, 0x23EF ); // Unicode pause/play
 PS.glyph( PS.ALL, 2, 0x23F9 ); // Unicode stop

 // This array of objects stores
 // the properties/status of each note
 // including its channel ID

 const NOTES = [
 {
 letter : "C",
 filename : "l_piano_c4",
 color : PS.COLOR_RED,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "D",
 filename : "l_piano_d4",
 color : PS.COLOR_ORANGE,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "E",
 filename : "l_piano_e4",
 color : 0xE0E000,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "F",
 filename : "l_piano_f4",
 color : PS.COLOR_GREEN,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "G",
 filename : "l_piano_g4",
 color : PS.COLOR_BLUE,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "A",
 filename : "l_piano_a4",
 color : PS.COLOR_INDIGO,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "B",
 filename : "l_piano_b4",
 color : PS.COLOR_VIOLET,
 playing : false,
 paused : false,
 channel : ""
 },
 {
 letter : "C",
 filename : "l_piano_c5",
 color : PS.COLOR_RED,
 playing : false,
 paused : false,
 channel : ""
 }
 ];

 // Called when a note is loaded
 // Saves channel ID in associated data

 const loaded = function ( result ) {
 result.data.channel = result.channel;
 };

 // Called when a note stops playing
 // Updates status of note

 const ended = function ( result ) {
 result.data.playing = false;
 result.data.paused = false;
 };

 // Set up note glyphs and colors,
 // preload the eight note sounds and
 // initialize note data

 for ( let x = 0; x < NOTES.length; x += 1 ) {
 let note = NOTES[ x ]; // note data
 PS.color( x, 0, note.color ); // note color
 PS.glyph( x, 0, note.letter ); // note letter

 // Note data passed to onLoad function
 // and also onEnd function
 // through .data parameter

 PS.audioLoad( note.filename, {
 data : note,
 lock : true,
 onLoad : loaded,
 onEnd : ended
 } ); // preload and lock sound

 // Store note data in all beads
 // associated with this note

 PS.data( x, 0, note );
 PS.data( x, 1, note );
 PS.data( x, 2, note );
 }
};

PS.touch = function( x, y, data, options ) {
 // Pressed play?

 if ( y === 0 ) {
 data.playing = true;
 data.paused = false;
 PS.audioPlay( data.note );
 PS.glyphColor( x, y, PS.COLOR_GREEN );
 }

 // Pressed pause?

 else if ( y === 1 ) {
 if ( data.playing ) {
 data.playing = false;
 data.paused = true;
 PS.audioPause( data.channel );
 }
 else if ( data.paused ) {
 data.playing = true;
 data.paused = false;
 data.channel = PS.audioPause( data.channel );
 }
 PS.glyphColor( x, y, PS.COLOR_YELLOW );
 }

 // Must have pressed stop

 else if ( data.playing ) {
 PS.audioStop( data.channel );
 data.playing = false;
 data.paused = false;
 PS.glyphColor( x, y, PS.COLOR_RED );
 }
};

PS.release = function( x, y, data, options ) {
 PS.glyphColor( x, y, PS.COLOR_WHITE );
};

PS.enter = function( x, y, data, options ) {
 if ( y > 0 ) {
 PS.color( x, y, PS.COLOR_BLACK );
 PS.glyphColor( x, y, PS.COLOR_WHITE );
 }
};

PS.exit = function( x, y, data, options ) {
 if ( y === 0 ) {
 PS.glyphColor( x, y, PS.COLOR_WHITE );
 }
 else {
 PS.color( x, y, PS.COLOR_WHITE );
 PS.glyphColor( x, y, PS.COLOR_BLACK );
 }
};

Return value

PS.audioStop() returns its channel parameter upon successful completion, or the constant PS.DONE if an empty string is passed to its channel parameter.

PS.ERROR is returned if an error occurs.

 

Terms to know

Next: Coding strategies