This is a relatively old package, which wasn't maintained for several years. We've forked it so that we have the ability to update bits of it that are no longer compliant with the Web Audio API.
To release a new version:
- Make your changes
- Bump the version in package.json
- type
npm publish
If publishing doesn't work, you must be logged into the npm account with the command npm login
Web Audio API test library for CI
$ npm install --save-dev web-audio-test-api
Install Web Audio API interfaces to global scope
import "web-audio-test-api";
Replace existing Web Audio API with web-audio-test-api
<script src="/path/to/web-audio-test-api.js"></script>
if you won't use web-audio-test-api
WebAudioTestAPI.unuse();
- Strict type check more than original Web Audio API
var audioContext = new AudioContext();
var osc = audioContext.createOsillator();
// correct
osc.frequency.value = 880;
// wrong
assert.throws(function() {
osc.frequency = 880;
}, function(e) {
return e instanceof TypeError &&
e.message === "OscillatorNode#frequency is readonly";
});
assert.throws(function() {
osc.type = 2;
}, function(e) {
return e instanceof TypeError &&
e.message === "OscillatorNode#type should be an enum { sine, square, sawtooth, triangle }, but got: 2";
});
});
- Convert to JSON from audio graph
var audioContext = new AudioContext();
var osc = audioContext.createOscillator();
var lfo = audioContext.createOscillator();
var amp = audioContext.createGain();
lfo.$id = "LFO"; // name for debugging
osc.type = "sawtooth";
osc.frequency.value = 880;
lfo.frequency.value = 2;
lfo.connect(amp.gain);
osc.connect(amp);
amp.connect(audioContext.destination);
assert.deepEqual(audioContext.toJSON(), {
name: "AudioDestinationNode" // +------------------+
inputs: [ // | OscillatorNode |
{ // | - type: sawtooth |
name: "GainNode", // | - frequency: 220 |
gain: { // | - detune: 0 |
value: 1, // +------------------+
inputs: [ // |
{ // +-----------+ +--------------------+
name: "OscillatorNode#LFO", // | GainNode | | OscillatorNode#LFO |
type: "sine", // | - gain: 1 |--| - frequency: 2 |
frequency: { // +-----------+ | - detune: 0 |
value: 2, // | +--------------------+
inputs: [] // |
}, // +----------------------+
detune: { // | AudioDestinationNode |
value: 0, // +----------------------+
inputs: []
},
inputs: []
}
]
},
inputs: [
{
name: "OscillatorNode",
type: "sawtooth",
frequency: {
value: 880,
inputs: []
},
detune: {
value: 0,
inputs: []
},
inputs: []
}
]
}
]
});
- OscillatorNode/BufferSourceNode state
var audioContext = new AudioContext();
var node = audioContext.createOscillator();
assert(node.$state === "UNSCHEDULED");
node.start(0.100);
node.stop(0.150);
node.connect(audioContext.destination);
audioContext.$processTo("00:00.000");
assert(node.$state === "SCHEDULED", "00:00.000");
audioContext.$processTo("00:00.099");
assert(node.$state === "SCHEDULED", "00:00.099");
audioContext.$processTo("00:00.100");
assert(node.$state === "PLAYING", "00:00.100");
audioContext.$processTo("00:00.149");
assert(node.$state === "PLAYING", "00:00.149");
audioContext.$processTo("00:00.150");
assert(node.$state === "FINISHED", "00:00.150");
// other way
assert(node.$stateAtTime("00:00.000") === "SCHEDULED");
assert(node.$stateAtTime("00:00.099") === "SCHEDULED");
assert(node.$stateAtTime("00:00.100") === "PLAYING");
assert(node.$stateAtTime("00:00.149") === "PLAYING");
assert(node.$stateAtTime("00:00.150") === "FINISHED");
- AudioParam simulation
var audioContext = new AudioContext();
var node = audioContext.createOscillator();
node.frequency.setValueAtTime(880, 0.500);
node.frequency.linearRampToValueAtTime(440, 1.500);
node.connect(audioContext.destination);
audioContext.$processTo("00:00.000");
assert(node.frequency.value === 440, "00:00.000");
audioContext.$processTo("00:00.250");
assert(node.frequency.value === 440, "00:00.250");
audioContext.$processTo("00:00.500");
assert(node.frequency.value === 880, "00:00.500"); // <- setValueAtTime
// ^
audioContext.$processTo("00:00.750"); // |
assert(node.frequency.value === 770, "00:00.750"); // |
// |
audioContext.$processTo("00:01.000"); // |
assert(node.frequency.value === 660, "00:01.000"); // | linearRampToValueAtTime
// |
audioContext.$processTo("00:01.250"); // |
assert(node.frequency.value === 550, "00:01.250"); // |
// |
audioContext.$processTo("00:01.500"); // v
assert(node.frequency.value === 440, "00:01.500"); //
audioContext.$processTo("00:01.750");
assert(node.frequency.value === 440, "00:01.750");
// other way
assert(node.frequency.$valueAtTime("00:00.000" === 440);
assert(node.frequency.$valueAtTime("00:00.250" === 440);
assert(node.frequency.$valueAtTime("00:00.500" === 880); // <- setValueAtTime
assert(node.frequency.$valueAtTime("00:00.750" === 770); // ^
assert(node.frequency.$valueAtTime("00:01.000" === 660); // | linearRampToValueAtTime
assert(node.frequency.$valueAtTime("00:01.250" === 550); // v
assert(node.frequency.$valueAtTime("00:01.500" === 440); //
assert(node.frequency.$valueAtTime("00:01.750" === 440);
- ScriptProcessing simulation
var audioContext = new AudioContext();
var node = audioContext.createScriptProcessor(1024, 2, 2);
node.onaudioprocess = sinon.spy();
node.connect(audioContext.destination);
audioContext.$processTo("00:00.500");
assert(node.onaudioprocess.callCount === 22);
// 22times call (0.5 / (1024 / 44100) = 21.5332)
- DecodeAudioData simulation
var audioContext = new AudioContext();
// audioContext.DECODE_AUDIO_DATA_RESULT = customResult;
// audioContext.DECODE_AUDIO_DATA_FAILED = true;
audioContext.decodeAudioData(audioData, function(result) {
// successCallback
assert(result instanceof AudioBuffer);
}, function() {
// errorCallback
throw new ERROR("NOT REACHED");
});
- New API support
WebAudioTestAPI.setState({
"AudioContext#createStereoPanner": "enabled",
});
var audioContext = new AudioContext();
var node = audioContext.createStereoPanner();
console.log(WebAudioTestAPI.getState("AudioContext#createStereoPanner")); // "enabled"
API Name | states |
---|---|
AnalyserNode#getFloatTimeDomainData |
"enabled" or "disabled" |
AudioBuffer#copyToChannel |
"enabled" or "disabled" |
AudioBuffer#copyFromChannel |
"enabled" or "disabled" |
AudioContext#createAudioWorker |
"disabled" |
AudioContext#createStereoPanner |
"enabled" or "disabled" |
AudioContext#close |
"enabled" or "disabled" |
AudioContext#suspend |
"enabled" or "disabled" |
AudioContext#resume |
"enabled" or "disabled" |
AudioContext#decodeAudioData |
"promise" or "void" |
OfflineAudioContext#startRendering |
"promise" or "void" |
AudioNode#disconnect |
"selective" or "channel" |
web-audio-test-api.js is available under the The MIT License.