AudioContext, как играть ноты в последовательности

Я последовал за этим учебником и придумал этот код:

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

Таким образом, я могу воспроизводить любые заметки из таблицы tutorial, передавая значения 1175, 2794 и т.д.

Я решил создать массив заметок и просто вызвал функцию play в цикле, и это просто не сработало, так как все ноты, которые только что играли сразу, без задержки.

Как вы будете играть в массив нот в последовательности?

Я также искал статью но все еще не могу понять, как я могу адаптировать мой код к этому.

Ответ 1

Вы можете воспроизводить ноты в последовательности с дополнительным временем параметра в вашей функции воспроизведения. Таким образом вы можете контролировать время начала и время окончания каждой ноты в последовательности.

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

Однако, если вам нужен более точный/надежный планировщик, вы можете использовать библиотеку, например WAAClock.js или вдохнуть вдохновение в Chris Wilson metronome, чтобы создать свой собственный.

Ответ 2

Это происходит потому, что выполняемые вами операции не блокируются в JavaScript. Самый простой способ заставить задержку между ними - использовать setInterval и setTimeout. Я нашел примеры использования в этой статьи об использовании AudioContext.

setInterval в MDN setTimeout в MDN

Разница заключается в том, что setTimeout выполняется один раз после задержки, тогда как setInterval выполняется несколько раз, пока вы не прекратите его.