web-audio-test-api

Web Audio API test library for CI
Installation
node.js
$ npm install --save-dev web-audio-test-api
Install Web Audio API interfaces to global scope
import "web-audio-test-api";
browser
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();
Online Test Suite
Documents
Features
- Strict type check more than original Web Audio API
var audioContext = new AudioContext();
var osc = audioContext.createOsillator();
osc.frequency.value = 880;
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";
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: [
{
name: "GainNode",
gain: {
value: 1,
inputs: [
{
name: "OscillatorNode#LFO",
type: "sine",
frequency: {
value: 2,
inputs: []
},
detune: {
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");
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");
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");
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");
audioContext.$processTo("00:01.250");
assert(node.frequency.value === 550, "00:01.250");
audioContext.$processTo("00:01.500");
assert(node.frequency.value === 440, "00:01.500");
audioContext.$processTo("00:01.750");
assert(node.frequency.value === 440, "00:01.750");
assert(node.frequency.$valueAtTime("00:00.000" === 440);
assert(node.frequency.$valueAtTime("00:00.250" === 440);
assert(node.frequency.$valueAtTime("00:00.500" === 880);
assert(node.frequency.$valueAtTime("00:00.750" === 770);
assert(node.frequency.$valueAtTime("00:01.000" === 660);
assert(node.frequency.$valueAtTime("00:01.250" === 550);
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);
- DecodeAudioData simulation
var audioContext = new AudioContext();
audioContext.decodeAudioData(audioData, function(result) {
assert(result instanceof AudioBuffer);
}, function() {
throw new ERROR("NOT REACHED");
});
WebAudioTestAPI.setState({
"AudioContext#createStereoPanner": "enabled",
});
var audioContext = new AudioContext();
var node = audioContext.createStereoPanner();
console.log(WebAudioTestAPI.getState("AudioContext#createStereoPanner"));
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" |
License
web-audio-test-api.js is available under the The MIT License.