JavaScript HTML
Latest commit c92afa6 Dec 13, 2015 @mohayonao Merge pull request #39 from mohayonao/v0.5.2
v0.5.2
Permalink
Failed to load latest commit information.
build v0.5.2 Dec 13, 2015
src v0.5.2 Dec 13, 2015
test update tests for Illegal constructor Dec 13, 2015
.babelrc update dev tools Dec 10, 2015
.eslintignore update browser test Dec 11, 2015
.eslintrc fix coding style Dec 11, 2015
.gitignore
.travis.yml update travis configuration Dec 12, 2015
README.md update README [ci skip] Dec 12, 2015
index.html
index.js
package.json v0.5.2 Dec 13, 2015

README.md

web-audio-test-api

Build Status NPM Version License

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();

// 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"

License

web-audio-test-api.js is available under the The MIT License.