lumen5-web-audio-test-api

0.5.2 • Public • Published

Disclaimer

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.

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.

Readme

Keywords

Package Sidebar

Install

npm i lumen5-web-audio-test-api

Weekly Downloads

235

Version

0.5.2

License

MIT

Unpacked Size

518 kB

Total Files

69

Last publish

Collaborators

  • lumen5-team