Можете ли вы остановить OscillatorNode рано? - PullRequest
0 голосов
/ 24 марта 2020

Фон: я создал OscillatorNode, запустил его с .start() и установил время его остановки с .stop(). Он представляет собой тон, который длится 1 сек c. Но я хочу иметь возможность остановить генератор на ранней стадии, в ответ на щелчок мышью пользователя, то есть, чтобы остановить тональный сигнал до времени окончания, которое было установлено .stop(). Мой подход состоит в том, чтобы вызвать новый метод .stop() с событием onmouseup.

Проблема: вместо этого щелчок мыши приводит к InvalidStateError: «Объект находится в недопустимом состоянии». Я предполагаю, что это потому, что я применяю второй .stop() метод к одному OscillatorNode. OscillatorNodes, очевидно, может поддерживать только один .start() вызов и один .stop() вызов.

Вопрос: действительно ли нет способа обновить время остановки, установленное .stop() метод? Это кажется странным. (Мне известны некоторые потенциальные обходные пути, такие как установка усиления на ноль; эти обходные пути были неприемлемы. Я действительно чувствую, что OscillatorNode должен иметь возможность программно прерваться.)

Увеличенный контекст: это часть пользовательский интерфейс, в котором мелодии воспроизводятся в ответ на ввод пользователя. В настоящее время, если пользователь переключает тоны слишком быстро, у нас возникают проблемы с перекрывающимися звуковыми сигналами, вызывающими неприятные акустические помехи c. Мне нужен любой воспроизводимый в данный момент звуковой сигнал, чтобы остановить его, как только будет запущен новый тон.

var ac = new (window.AudioContext || window.webkitAudioContext)();
var gainNode=ac.createGain();
gainNode.connect(ac.destination)
var playing=false
var oscillator

function setFrequency() { // captures the frequency from an input slider
  frequency=document.getElementById("frequency").value
  document.getElementById("frequency_log").innerHTML=frequency
}

function play(frequency) { // plays 0.5s tone (w/gain envelope) at given frequency

if(playing){ // stop currently playing tone
  oscillator.stop() // !! THIS IS WHAT GIVES THE INVALID STATE ERROR !!
  playing=false
}

if (!playing){ // play tone
  oscillator=ac.createOscillator();
  oscillator.onended=function(){playing=false}
  oscillator.connect(gainNode)
  oscillator.frequency.value = frequency;

  gainNode.gain.setValueAtTime(0.001,0);
  gainNode.gain.exponentialRampToValueAtTime(0.8,ac.currentTime+0.1);
  gainNode.gain.setValueAtTime(0.8,ac.currentTime+0.3);
  gainNode.gain.exponentialRampToValueAtTime(0.1, ac.currentTime+0.4);
  gainNode.gain.exponentialRampToValueAtTime(0.001, ac.currentTime+0.5);

  oscillator.start();
  playing=true
  oscillator.stop(ac.currentTime+0.5)
}
}
<span class="math-container">```</span>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...