0

我正在使用 WebAudio 播放一系列音符。我有一个运行良好的 playNote 功能;我向它发送音符频率以及每个音符的开始和停止时间。序列参数的生成发生实际声音开始之前,这有点令人困惑。该函数只是为每个音符创建一个振荡器。(我尝试了其他方法,这是最干净的)。

但我想异步停止序列(例如,当发生外部事件时)。我尝试设置一个可用于门控输出的主增益节点,但它似乎需要在函数“内部”,因此以后无法控制。如果我尝试关闭函数内的增益对象,则为时已晚 - 因为开始和停止时间已经传递给函数。

这是我的功能:

function playNote(audioContext,frequency, startTime, endTime, last) {
  gainNode = audioContext.createGain(); //to get smooth rise/fall
  oscillator = audioContext.createOscillator();
  oscillator.frequency.value=frequency;
  oscillator.connect(gainNode);
  gainNode.connect(analyserScale); //analyser is global
  analyserScale.connect(audioContext.destination);
  gainNode.gain.exponentialRampToValueAtTime(toneOn,  startTime + trf);
  gainNode.gain.exponentialRampToValueAtTime(toneOff, endTime+trf);
  oscillator.start(startTime);
  oscillator.stop(endTime);
}

任何帮助表示赞赏!

4

1 回答 1

0

这样做:Web Audio API:停止播放所有预定的声音。解决方案是使用数组跟踪计划的振荡器。

函数现在变为: var oscs = []; //振荡器列表

function playNote(audioContext,frequency, startTime, endTime, last, index) {
  gainNode = audioContext.createGain(); //to get smooth rise/fall

  oscillator = audioContext.createOscillator();
  oscillator.frequency.value=frequency;
  oscillator.connect(gainNode);
  //keep track of alll the oscs so that they can be switched off if scale is stopped by user
    oscs[index] = oscillator;

  gainNode.connect(analyserScale); //analyser is global
  analyserScale.connect(audioContext.destination);
  gainNode.gain.exponentialRampToValueAtTime(toneOn,  startTime + trf);
  gainNode.gain.exponentialRampToValueAtTime(toneOff, endTime+trf);
  oscillator.start(startTime);
  oscillator.stop(endTime);
}

然后代码停止振荡器:

for(let i=0; i<oscs.length; i++) {
    if(oscs[i]){
      oscs[i].stop(0);
    }
  }
于 2020-05-02T15:51:08.070 回答