1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Web Audio APIでカスタムAudioNodeを作る方法

Posted at

Web Audio APIのノードをconnectで繋いで音を作る方法はわかりやすいのですが、ノードの種類自体は多くなく、複数のノードを組み合わせて一つのエフェクターなどを作っていく感じのようです。
そのため、既存ノードを組み合わせてエフェクターなどの単位で新しいAudioNodeを作ってconnectできるようにすれば便利なんじゃないかと思いました。

とりあえず、以下のようにAudioNodeを継承できるか試してみましたが、Uncaught TypeError: Illegal constructorというエラーがでてこれは無理そうです。

class MyAudioNode extends AudioNode {}
const myAudioNode = new MyAudioNode();

AudioNodeを継承したサブクラスならと思って以下も試してみましたが、これもUncaught TypeError: Failed to construct 'OscillatorNode': 1 argument required, but only 0 present.というエラーが出て駄目そうです。

class MyOscillatorNode extends OscillatorNode {}
const myOscillator = new MyOscillatorNode();

いろいろ調べた結果、直接AudioNodeを継承することはできないようです。
そのかわりに、以下のように入出力をGainNodeでラップして、内部で音を作ったり、加工したりしてあげることでほぼ既存のAudioNodeと同じように振る舞う自作ノードを作ることができます。
この方法だと他のノードを接続するときに、squareOscNode.connect(highpassFilter.in)というように自作ノードのinプロパティに接続しないといけないことが既存のノードに接続するときとは異なります。


class BaseCustomNode {
  constructor(context) {
    this._context = context;
    this.in = context.createGain();
    this._out = context.createGain();
  }

  connect(audioNode) {
    this._out.connect(audioNode);
  }
}

class SquareOscillatorNode extends BaseCustomNode {
  constructor(context) {
    super(context);
    this._osc = context.createOscillator();
    this._osc.type = 'square';
    this._osc.connect(this._out);
  }

  start(when) {
    this._osc.start(when);
  }

  stop(when) {
    this._osc.stop(when);
  }

  get frequency() {
    return this._osc.frequency;
  }
}

class HighpassFilter extends BaseCustomNode {
  constructor(context) {
    super(context);
    this._filter = context.createBiquadFilter();
    this._filter.type = 'highpass';
    this.in.connect(this._filter);
    this._filter.connect(this._out);
  }

  get frequency() {
    return this._filter.frequency;
  }
}

const context = new AudioContext(),
      squareOscNode = new SquareOscillatorNode(context),
      highpassFilter = new HighpassFilter(context);

squareOscNode.frequency.value = 880;
highpassFilter.frequency.value = 440;
squareOscNode.connect(highpassFilter.in); // 自作ノードに接続するときだけ、inプロパティに接続する
highpassFilter.connect(context.destination);

squareOscNode.start();

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?