A wrapper for a graph of AudioNodes that exposes their AudioParam values as simple getter/setters on a plain ol' JS object
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
js
modules
test
.eslintrc
.gitignore
README.md
gulpfile.js
index.html
package.json

README.md

AudioObject

A wrapper for a graph of AudioNodes that exposes AudioParam values as getter/setters on an plain ol' JS object. An AudioObject can serve as an observable, JSONifiable model of an audio sub-graph – an audio 'plugin' – in an app.

During an automation a property of an AudioObject is updated from it's audio param value at the browser frame rate. Changes are Object.observe-able (or observable using that technique where the getter/setter is redefined).

AudioObject(context, input, output, params)

Here is an example of a compressor and a gain wrapped into a single audio object:

var audio = new AudioContext();
var compressor = audio.createDynamicsCompressor();
var gain = audio.createGain();

compressor.connect(gain);

var audioObject = new AudioObject(audio, compressor, gain, {
    threshold: compressor.threshold,
    ratio: compressor.ratio,
    level: gain.gain
});

Now audioObject is an object with the enumerable properties:

{
    threshold: -20,
    ratio: 8,
    level: 1
}

Easy to JSONify. Easy to observe. Setting a property updates the corresponding audio param behind the scenes. Automating a property via .automate() updates the audio param and notifies any property observers of changes at the browser frame rate for the duration of the automation.

Multiple inputs and outputs

An AudioObject can have more than one input and/or more than one output. They are named in a definition object:

var compressor = audio.createDynamicsCompressor();
var sideGain = audio.createGain();
var outGain = audio.createGain();

var audioObject = new AudioObject(audio, {
    default: compressor,
    sidechain: sideGain
}, outGain);

Exposing audio params as properties

To read more about what can be passed into AudioObject() as params, see AudioObject.defineAudioProperties().

Instance methods

An instance of AudioObject has the methods .automate() and .destroy().

var audioObject = AudioObject(audio, input, output, params);
automate(name, time, value, curve, duration)

Automate a property. The property name will ramp to value from it's current value over duration (in seconds). The optional parameter curve can be either "step" (the default), "linear", "exponential" or "target".

audioObject.automate('level', 1.2, 0)

Properties of the audioObject are externally updated at the browser's frame rate during an automation, while internally the Web Audio API schedules them at the sample rate (or at the relevant rate of the audio param).

Note that while the Web Audio API only accepts positive non-zero values for exponential curves, an audioObject will accept a zero value. It exponentially automates to as near zero as possible and sets 0 at the end of the ramp. Negative values are still a no-no.

destroy()

Destroy is a noop by default. It should be overidden so that it destroys the nodes in the audioObject's audio graph.

audioObject.destroy()

AudioObject functions

automate(param, time, value, curve, duration)

Automates a value change on an AudioParam.

time is the time to start the automation. param is the AudioParam. value is the value to automate to. curve is the name of the automation curve. Choices are:

  • "step"'step' uses param.setValueAtTime() to set value immediately
  • "linear" uses param.linearRampToValue() to automate to value over duration
  • "exponential" uses param.exponentialRampToValue() to automate to value over duration
  • "decay" uses param.setTargetAtTime() to automate to value with the time constant duration

duration is the duration of the automation. Not used for "step" events.

returns undefined.

valueAtTime(param, time)

Returns the value of param at time.

defineAudioProperties(object, audioContext, audioParams)

.defineAudioProperties() takes a map of audio params and defines properties on object that are bound to the values of those params. It's used by the AudioObject() constructor to set up an audio object.

Echoes the JS function Object.defineProperties(), but an audio property is a getter/setter that is bound to the value of an audio param.

var object = {};

AudioObject.defineAudioProperties(object, audioContext, {
    // Define the property with an object...
    level: {
        param: gain.gain,
        curve: 'exponential',
        enumerable: false
    },

    // ...or as a shortcut, pass in the param directly.
    ratio: compressor.ratio
});

As with .defineProperties(), enumerable and configurable can be set, although they are true by default. curve can also be set, which, if object is an AudioObject, sets the default curve to be used by .automate().

To control more than one audio param with a single property, define a setter. It is the setter's responsibility to automate the audio param values with the given value, time, duration and curve. AudioObject.automate() Can help with that.

AudioObject.defineAudioProperties(object, audioContext, {
    response: {
        set: function(value, time, duration, curve) {
            AudioObject.automate(compressor.attack, time, value, curve, duration);
            AudioObject.automate(compressor.release, time, value * 6, curve, duration);
        },

        defaultValue: 1,
        curve: 'linear'
    }
});

Returns object.

defineAudioProperty(object, name, audioContext, audioParam)

As .defineAudioProperties(), but defines a single property with name name.

Returns object.

isAudioObject(object)

Returns true if object is an has AudioObject.prototype in it's prototype chain.

AudioObject properties

features

A key-value store of results from feature tests in the browser. Currently there is one feature test, disconnectParameters:

// Does the audioNode.disconnect() method accept parameters?
if (AudioObject.features.disconnectParameters) {
    node1.disconnect(node2, output, input)
}
else {
    node1.disconnect();
    // Reconnect nodes that should not have been disconnected...
}

Development

Getting started

Install the dependencies

npm install

Compile the source and run the tests

gulp

or run this tasks when a file changes

gulp watch

Release a new version

Increment the version number according to SemVer in the package.json