Skip to content
This repository has been archived by the owner on Jun 9, 2019. It is now read-only.

mohayonao/web-audio-test-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

web-audio-test-api

Build Status NPM Version Bower Coverage Status License

Web Audio API test library for CI

Installation

browser

replace existing Web Audio API with web-audio-test-api

<script src="/path/to/web-audio-test-api.js"></script>

set WEB_AUDIO_TEST_API_IGNORE flag if you won't use web-audio-test-api

WEB_AUDIO_TEST_API_IGNORE = true;
<script src="/path/to/web-audio-test-api.js"></script>

node.js

% npm install web-audio-test-api

install Web Audio API interfaces as global variables

require("web-audio-test-api");

Online Test Suites

Reference

Features

Strict type check more than original Web Audio API

describe("Strict Type Check", function() {
  var ctx = new AudioContext();
  var osc = ctx.createOsillator();

  it("throw error if uses wrong", function() {
    expect(function() {
      osc.frequency = 880;
    }, "uses wrong").to.throw(Error, "OscillatorNode#frequency is readonly");
    expect(function() {
      osc.frequency.value = 880;
    }, "uses correctly").to.not.throw();
  });

  it("throw error if receives an invalid value", function() {
    expect(function() {
      osc.type = 2;
    }).to.throw(Error,
      "OscillatorNode#type should be any [ sine, square, sawtooth, triangle, custom ], but got 2"
    );
  });

});

Convert to JSON from modular routing

describe("Modular Routine", function() {
  it("should generate audio graph", function() {
    var ctx = new AudioContext();
    var osc = ctx.createOscillator();
    var lfo = ctx.createOscillator();
    var amp = ctx.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(ctx.destination);

    // ctx.VERBOSE_JSON = true; // set this flag if you need more detailed data

    expect(ctx.toJSON()).to.eql({
      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

describe("OscillatorNode#$stateAtTime(t)", function() {
  it("works", function() {
    var ctx = new AudioContext();
    var osc = ctx.createOscillator();

    expect(osc.$state).to.equal("UNSCHEDULED");

    osc.start(1);
    osc.stop(2);

    expect(osc.$stateAtTime(0.5)).to.equal("SCHEDULED");
    expect(osc.$stateAtTime(1.5)).to.equal("PLAYING");
    expect(osc.$stateAtTime(2.5)).to.equal("FINISHED");
  });
  it("with audioContext.$process()", function() {
    var ctx = new AudioContext();
    var osc = ctx.createOscillator();

    expect(osc.$state).to.equal("UNSCHEDULED");

    osc.start(1);
    osc.stop(2);

    expect(osc.$state, "00:00.000").to.equal("SCHEDULED");

    ctx.$processTo("00:00.500");
    expect(osc.$state, "00:00.500").to.equal("SCHEDULED");

    ctx.$processTo("00:01.000");
    expect(osc.$state, "00:01.000").to.equal("PLAYING");

    ctx.$processTo("00:01.500");
    expect(osc.$state, "00:01.500").to.equal("PLAYING");

    ctx.$processTo("00:02.000");
    expect(osc.$state, "00:02.000").to.equal("FINISHED");

    ctx.$processTo("00:02.500");
    expect(osc.$state, "00:02.500").to.equal("FINISHED");
  });
});

AudioParam simulation

describe("AudioParam", function() {
  it("works", function() {
    var ctx = new AudioContext();
    var osc = ctx.createOscillator();

    osc.frequency.setValueAtTime(880, 0.5);
    osc.frequency.linearRampToValueAtTime(440, 1.5);

    expect(osc.frequency.$valueAtTime(0.000), "00:00.000").to.equal(440);
    expect(osc.frequency.$valueAtTime(0.250), "00:00.250").to.equal(440);
    expect(osc.frequency.$valueAtTime(0.500), "00:00.500").to.equal(880); // <- setValueAtTime
    expect(osc.frequency.$valueAtTime(0.750), "00:00.750").to.equal(770); //  ^
    expect(osc.frequency.$valueAtTime(1.000), "00:01.000").to.equal(660); //  | linearRampToValueAtTime
    expect(osc.frequency.$valueAtTime(1.250), "00:01.250").to.equal(550); //  v
    expect(osc.frequency.$valueAtTime(1.500), "00:01.500").to.equal(440); //
    expect(osc.frequency.$valueAtTime(1.750), "00:01.750").to.equal(440);
  });
  it("with audioContext$process()", function() {
    var ctx = new AudioContext();
    var osc = ctx.createOscillator();

    osc.frequency.setValueAtTime(880, 0.5);
    osc.frequency.linearRampToValueAtTime(440, 1.5);

    expect(osc.frequency.value, "00:00.000").to.equal(440);

    ctx.$processTo("00:00.250");
    expect(osc.frequency.value, "00:00.250").to.equal(440);

    ctx.$processTo("00:00.500");
    expect(osc.frequency.value, "00:00.500").to.equal(880); // <- setValueAtTime
                                                            //  ^
    ctx.$processTo("00:00.750");                            //  |
    expect(osc.frequency.value, "00:00.750").to.equal(770); //  |
                                                            //  |
    ctx.$processTo("00:01.000");                            //  |
    expect(osc.frequency.value, "00:01.000").to.equal(660); //  | linearRampToValueAtTime
                                                            //  |
    ctx.$processTo("00:01.250");                            //  |
    expect(osc.frequency.value, "00:01.250").to.equal(550); //  |
                                                            //  |
    ctx.$processTo("00:01.500");                            //  v
    expect(osc.frequency.value, "00:01.500").to.equal(440); //

    ctx.$processTo("00:01.750");
    expect(osc.frequency.value, "00:01.750").to.equal(440);
  });
});

ScriptProcessing simulation

describe("ScriptProcessorNode#onaudioprocess(e)", function() {
  it("works", function() {
    var ctx = new AudioContext();
    var scp = ctx.createScriptProcessor(1024, 2, 2);

    var count = 0;

    scp.onaudioprocess = function(e) {
      count += 1;
    };

    ctx.$process(0.5);           // advance 0.5 sec
    expect(count).to.equal(22); // 22times call (0.5 / (1024 / 44100) = 21.5332)
  });
});

DecodeAudioData simulation

describe("AudioContext#decodeAudioData()", function() {
  it("should return decoded buffer in async", function(done) {
    var ctx = new AudioContext();

    // ctx.DECODE_AUDIO_DATA_RESULT = customResult;
    // ctx.DECODE_AUDIO_DATA_FAILED = true;

    ctx.decodeAudioData(audioData, function(result) {
      // successCallback
      expect(result).to.be.instanceOf(AudioBuffer);
      done();
    }, function() {
      // errorCallback
      throw new ERROR("NOT REACHED");
    });
  });
});

License

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