AudioContext how to play the notes in a sequence

1.4k views Asked by At

I have followed this tutorial and come up with that code:

context = new AudioContext();
play(frequency) {
    const o = this.context.createOscillator();
    const g = this.context.createGain();
    o.connect(g);
    g.connect(this.context.destination);
    g.gain.exponentialRampToValueAtTime(
      0.00001, this.context.currentTime + 1
    );
    o.frequency.value = frequency;
    o.start(0);
  }

This way I can play any notes from tutorial table by passing the values 1175, 2794, etc

I decided to create an array of notes and just called my play function in the loop and it is just didn't work as all the notes just played at once with no delay.

How would you play the array of notes in a sequence?

I also was looking in to that article but still cant figure out how I can adapt my code above to that.

2

There are 2 answers

0
TGrif On

You can play notes in sequence with an additional parameter time in your play function.This way you can control start time and end time for each note in the sequence.

  var context = new AudioContext();

  var notes = [1175, 2794];
  var duration = 1;
  var interval = 2;

  function play(frequency, time) {
    var o = context.createOscillator();
    var g = context.createGain();
    o.connect(g);
    g.connect(context.destination);
    g.gain.exponentialRampToValueAtTime(
      0.00001, context.currentTime + duration + time
    );
    o.frequency.value = frequency;
    o.start(time);
  }

  for (var i = 0; i < notes.length; i++) {
    play(notes[i], i * interval);
  }

However, if you need a more precise/robust scheduler, you can use a library like WAAClock.js or take inspiration from Chris Wilson metronome to build your own.

0
Sam H. On

This happens because the operations you are doing are non blocking in JavaScript. The most straightforward way to force a delay between these is to use setInterval and setTimeout. I found examples of using those in this article on using AudioContext.

setInterval on MDN setTimeout on MDN

The difference is that setTimeout executes once after a delay, whereas setInterval executes repeatedly until you tell it to stop.