16.5 Web Audio API(网页音频接口) 创建音效“类”对象

一旦振荡器停止后就不能重新启动。你没有做错任何事,这只是网络音频接口为了优化性能而设的特性。但我们可以创建一个可以负责创建振荡器节点、播放和停止声音的”类“,这样我们就可以多次调用声音。下面我们用ES6语法做了这么一个:

class Sound {

  constructor(context) {
    this.context = context;
  }

  init() {
    this.oscillator = this.context.createOscillator();
    this.gainNode = this.context.createGain();

    this.oscillator.connect(this.gainNode);
    this.gainNode.connect(this.context.destination);
    this.oscillator.type = 'sine';
  }

  play(value, time) {
    this.init();

    this.oscillator.frequency.value = value;
    this.gainNode.gain.setValueAtTime(1, this.context.currentTime);
            
    this.oscillator.start(time);
    this.stop(time);

  }

  stop(time) {
    this.gainNode.gain.exponentialRampToValueAtTime(0.001, time + 1);
    this.oscillator.stop(time + 1);
  }

}

我们将Audio Context传递给构造函数,这样我们就可以在相同的Context中创建声音类的所有实例。然后"init"方法来创造振荡器和其它所有必要的滤波器节点并连接它们。"PLAY播放"方法在即将播放时接受值(音符的赫兹频率)。但首要的是它创建了振荡器,我们每次在调用播放方法的时候都要发生。"STOP停止"方法在1秒钟内降低音量指数直到振荡器完全停止工作。因此,每当我们需要再次播放声音时,我们创建一个声音类的新实例,并调用播放方法。现在我们可以播放一些音符:

let context = new (window.AudioContext || window.webkitAudioContext)();
let note = new Sound(context);
let now = context.currentTime;
note.play(261.63, now);
note.play(293.66, now + 0.5);
note.play(329.63, now + 1);
note.play(349.23, now + 1.5);
note.play(392.00, now + 2);
note.play(440.00, now + 2.5);
note.play(493.88, now + 3);
note.play(523.25, now + 3.5);

上面的代码在同一个Context中播放了音符 C D E F G A B C 。你可以在这里找到所有音符的赫兹频率。

知道了这一些后使我们有可能能够创建一个像演奏木琴这样的小程序!下面的例子就是使用鼠标点击来创建一个实例并使其发生声音来。您可以好好的学习这个例子并尝试自己做一个作为练习。