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
- PS.audioLoad()
- PS.audioPlay()
- Advanced audio control
- PS.audioPlayChannel()
- PS.audioPause()
- PS.audioStop()
- Terms to know
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:
- .volume : float or PS.DEFAULT
- .loop : boolean or PS.DEFAULT
- .lock : boolean or PS.DEFAULT
- .onLoad : function or PS.DEFAULT
- .onEnd : function or PS.DEFAULT
- .data : any JavaScript value or PS.DEFAULT
- .path : string, or PS.DEFAULT
- .fileTypes : string array or PS.DEFAULT
- .autoplay : boolean or PS.DEFAULT (PS.audioLoad() only)
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.
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.
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.
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
- Audio library
- preload
- PS.audioLoad()
- PS.audioPlay()
- channel ID
- PS.audioPlayChannel()
- PS.audioPause()
- PS.audioStop()
Next: Coding strategies