web-audio-scheduler

1.4.0 • Public • Published

web-audio-scheduler

Build Status NPM Version License

Event Scheduler for Web Audio API

This module is developed based on the idea of this article.

Installation

npm
npm install web-audio-scheduler
downloads

Examples

metronome

const audioContext = new AudioContext();
const sched = new WebAudioScheduler({ context: audioContext });
let masterGain = null;
 
function metronome(e) {
  const t0 = e.playbackTime;
 
  sched.insert(t0 + 0.000, ticktack, { frequency: 880, duration: 1.0 });
  sched.insert(t0 + 0.500, ticktack, { frequency: 440, duration: 0.1 });
  sched.insert(t0 + 1.000, ticktack, { frequency: 440, duration: 0.1 });
  sched.insert(t0 + 1.500, ticktack, { frequency: 440, duration: 0.1 });
  sched.insert(t0 + 2.000, metronome);
}
 
function ticktack(e) {
  const t0 = e.playbackTime;
  const t1 = t0 + e.args.duration;
  const osc = audioContext.createOscillator();
  const amp = audioContext.createGain();
 
  osc.frequency.value = e.args.frequency;
  osc.start(t0);
  osc.stop(t1);
  osc.connect(amp);
 
  amp.gain.setValueAtTime(0.5, t0);
  amp.gain.exponentialRampToValueAtTime(1e-6, t1);
  amp.connect(masterGain);
 
  sched.nextTick(t1, () => {
    osc.disconnect();
    amp.disconnect();
  });
}
 
sched.on("start", () => {
  masterGain = audioContext.createGain();
  masterGain.connect(audioContext.destination);
});
 
sched.on("stop", () => {
  masterGain.disconnect();
  masterGain = null;
});
 
document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "visible") {
    sched.aheadTime = 0.1;
  } else {
    sched.aheadTime = 1.0;
    sched.process();
  }
});
 
document.getElementById("start-button").addEventListener("click", () => {
  sched.start(metronome);  
});
 
document.getElementById("stop-button").addEventListener("click", () => {
  sched.stop(true);
});

API

WebAudioScheduler

  • WebAudioScheduler(opts = {})
    • context: AudioContext
    • interval: number default: 0.025 (25ms)
    • aheadTime: number default: 0.1 (100ms)
    • timerAPI: object default: window || global

Instance properties

  • context: AudioContext
  • interval: number
  • aheadTime: number
  • timerAPI: object
  • playbackTime: number
  • currentTime: number
  • state: string
  • events: object[]

Instance methods

  • start([ callback: function, args: any ]): self
    • Start the timeline.
    • The callback is inserted in the head of the event list if given.
  • stop([ reset = true: boolean ]): self
    • Stop the timeline.
    • The event list is cleared if reset is truthy.
  • insert(time: number, callback: function, [ args: any ]): number
    • Insert the callback into the event list.
    • The return value is schedId. It is used to .remove() the callback.
  • nextTick([ time: number ], callback: function, [ args: any ]): number
    • Same as .insert(), but this callback is called at next tick.
    • This method is used to disconnect an audio node at the proper timing.
  • remove(schedId: number): number
    • Remove a callback function from the event list.
  • removeAll(): void
    • Remove all callback functions from the event list.
  • process(): void
    • process events immediately (this is useful when transition to background tabs)

Events

  • "start"
    • emitted when the scheduler started.
  • "stop"
    • emitted when the scheduler stopped.
  • "process"
    • emitted before each scheduler process.
  • "processed"
    • emitted after each scheduler process.

Callback

A callback function receives a schedule event and given arguments at .insert().

A schedule event has two parameters.

  • playbackTime: number
  • args: any
sched.insert(0, callback, [ 1, 2 ]);
 
function callback(e) {
  assert(e.playbackTime === 0);
  assert(e.args[0] === 1);
  assert(e.args[1] === 2);
}

Customize

timeline

time(ms) 0----25---50---75---100--125--150--175--200---->
         =====|====|====|====|    |    |    |    |
         |    =====|====|====|====|    |    |    |
         |    |    =====|====|====|====|    |    |
         |    |    |    | ===|====|====|====|==  |
         |    |    |    |    | ===|====|====|====|==
         :    :    :    :    :    :    :    :    :
         |<-->|    :    :      |<------------------>|
         interval (25ms)       aheadTime (100ms)
                             = range of execution to events

The below example is the same configuration as defaults.

const sched = new WebAudioScheduler({ interval: 0.025, aheadTime: 0.1 });

timerAPI

TimerAPI is used instead of the native timer API. TimerAPI should have two functions, setInterval and clearInterval.

The below example uses stable-timer instead of the native timer API.

const WorkerTimer = require("worker-timer");
const sched = new WebAudioScheduler({ timerAPI: WorkerTimer });

License

MIT

Package Sidebar

Install

npm i web-audio-scheduler

Weekly Downloads

22

Version

1.4.0

License

MIT

Last publish

Collaborators

  • mohayonao