43
Web Audio API Biquad Filter 編 清水智公 [email protected] / @chikoski Firefox OS コードリーディング

20141115 fx os-codereading

Embed Size (px)

DESCRIPTION

BiquadFilterNode in WebAudio API

Citation preview

Page 1: 20141115 fx os-codereading

Web Audio API Biquad Filter 編

清水智公 [email protected] / @chikoski

Firefox OS コードリーディング

Page 2: 20141115 fx os-codereading

@chikoski

• 関数プログラミングわなびー • プログラミング言語論 • Emacs • 機械学習 • ニューラルネットワーク • Bayesian • TaPL / PRMLを読みたい!

Page 3: 20141115 fx os-codereading

音を扱うアプリを作りたい!

Page 4: 20141115 fx os-codereading

Audio 要素

• 音声コンテンツを表すHTML要素 • src属性で埋め込む音声リソースを指定 • コントロール、ロード方法なども属性で指定

<audio src="foo.mp3" autoplay control loop></audio>

Page 5: 20141115 fx os-codereading

Web Audio API

• 音声の処理を行うためのAPI • できること • 音声データのデコード • 変調、FFT、ミキシング、パンニング • オシレーション • オーディオグラフ

Page 6: 20141115 fx os-codereading

オーディオグラフ

• 音声データの処理の流れ • オーディオノードをつないで作成 • ノードはオーディオコンテキストから作成

Page 7: 20141115 fx os-codereading

簡単なオーディオグラフの作成例

• AudioContextオブジェクトのファクトリメソッドを利用してオーディオノードを作成

• connectメソッドでノードを接続 • context.destination がスピーカー

var elm = document.querySelector("audio");

var context = new AudioContext();var source = context.createMediaElementSource(elm);source.connect(context.destination);

Page 8: 20141115 fx os-codereading

簡単なオーディオグラフの作成例

var elm = document.querySelector("audio");

var context = new AudioContext();var source = context.createMediaElementSource(elm);source.connect(context.destination);

source context.destination

Page 9: 20141115 fx os-codereading

ディレイを行うグラフvar elm = document.querySelector("audio");var context = new AudioContext();var source = context.createMediaElementSource(elm);

var delay = context.createDelay();var wet = context.createGain();var dry = context.createGain();var feedback = context.createGain();

source.connect(dry);dry.connect(context.destination);source.connect(delay);delay.connect(wet);wet.connect(context.destination);delay.connect(feedback);feedback.connect(delay);

Page 10: 20141115 fx os-codereading

ディレイを行うグラフsource

context.destination

delayfeedback dry

wet

Page 11: 20141115 fx os-codereading

Web Audio エディタ

Page 12: 20141115 fx os-codereading

BiquadFilter Node

Page 13: 20141115 fx os-codereading

BiquadFilter:周波数によるフィルタ種類 効果

lowpass 指定された周波数より低い音のみ通過させる

highpass 指定された周波数より高い音のみ通過させる

bandpass 指定された範囲の周波数の音のみ通過させる

lowshelf 指定された値よりより低い周波数の音を増幅する

highshelf 指定された値よりより高い周波数の音を増幅する

peaking 指定された範囲の周波数の音を増幅する

notch 指定された範囲以外の周波数の音をのみを通過させる

allpass 全ての音を通過させる

Page 14: 20141115 fx os-codereading

ローパスフィルタ

var elm = document.querySelector("audio");

var context = new AudioContext();var source = context.createMediaElementSource(elm);var lowpass = context.createBiquadFilter();lowpass.type = "lowpass";

source.connect(lowpass);lowpass.connect(context.destination);

source context.destinationlowpass

Page 15: 20141115 fx os-codereading

BiquadFilterの使い方

• フィルタの種類はtype属性に名前を代入して指定 • frequency, Q, gain のパラメータを持つ • パラメータの役割はMDNを参照してくださいhttps://developer.mozilla.org/ja/docs/Web/API/BiquadFilterNode

var context = new AudioContext();var lowpass = context.createBiquadFilter();lowpass.type = "lowpass";lowpass.frequency.value = 2000;lowpass.Q.value = 30;

Page 16: 20141115 fx os-codereading

AudioParamオブジェクト

• パラメータを表すオブジェクトhttps://developer.mozilla.org/docs/Web/API/AudioParam

• 例:BiquadFilterNodeオブジェクトのfrequency属性 • value と defaultValue の2つの属性を持つ • タイミングにあわせた値設定なども可能

var context = new AudioContext();var lowpass = context.createBiquadFilter();lowpass.frequency.value = 2000;

Page 17: 20141115 fx os-codereading

フィルタ種類の変更をしたい

Page 18: 20141115 fx os-codereading

source destinationBiquadFilter

Page 19: 20141115 fx os-codereading

destination

BiquadFilterGain

BiquadFilterGain

BiquadFilterGain

BiquadFilterGain

source

Page 20: 20141115 fx os-codereading

コードを読んでみる

Page 21: 20141115 fx os-codereading

ソースコードを取ってくる

• しばらく時間がかかります • お風呂に入ったりすると良いかも

% git clone https://github.com/mozilla-b2g/B2G% cd B2G% ./config.sh flame-kk

Page 22: 20141115 fx os-codereading
Page 23: 20141115 fx os-codereading

gecko/dom/webidl

Page 24: 20141115 fx os-codereading

gecko/dom/media/webaudio

Page 25: 20141115 fx os-codereading

BiquadFilterNode.cpp

Page 26: 20141115 fx os-codereading

BiquadFilterNode::BiquadFilterNode(AudioContext* aContext) : AudioNode(aContext, 2, ChannelCountMode::Max, ChannelInterpretation::Speakers) , mType(BiquadFilterType::Lowpass) , mFrequency(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(), SendFrequencyToStream, 350.f)) , mDetune(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(), SendDetuneToStream, 0.f)) , mQ(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(), SendQToStream, 1.f)) , mGain(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(), SendGainToStream, 0.f))

Page 27: 20141115 fx os-codereading

voidBiquadFilterNode::SetType(BiquadFilterType aType){ mType = aType; SendInt32ParameterToStream(BiquadFilterNodeEngine::TYPE, static_cast<int32_t>(aType));}

Page 28: 20141115 fx os-codereading

AudioNode.cpp

Page 29: 20141115 fx os-codereading

AudioNode::SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue){ AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get()); MOZ_ASSERT(ns, "How come we don't have a stream here?"); ns->SetInt32Parameter(aIndex, aValue);}

Page 30: 20141115 fx os-codereading

AudioNodeStream::SetInt32Parameter(uint32_t aIndex, int32_t aValue)

{

class Message : public ControlMessage {

public:

Message(AudioNodeStream* aStream, uint32_t aIndex, int32_t aValue)

: ControlMessage(aStream), mValue(aValue), mIndex(aIndex) {}

virtual void Run()

{

static_cast<AudioNodeStream*>(mStream)->Engine()->

SetInt32Parameter(mIndex, mValue);

}

int32_t mValue;

uint32_t mIndex;

};

MOZ_ASSERT(this);

GraphImpl()->AppendMessage(new Message(this, aIndex, aValue));

}

Page 31: 20141115 fx os-codereading

BiquadFilterNodeEngine

Page 32: 20141115 fx os-codereading

ProcessBlock

Page 33: 20141115 fx os-codereading

SetParamsOnBiquad

Page 34: 20141115 fx os-codereading

gecko/dom/media/webaudio/blink

Page 35: 20141115 fx os-codereading

Biquad.cpp

Page 36: 20141115 fx os-codereading

setNormalizedCoefficients

Page 37: 20141115 fx os-codereading

void Biquad::setNormalizedCoefficients(double b0, double b1, double b2, double a0, double a1, double a2)

{

double a0Inverse = 1 / a0;

m_b0 = b0 * a0Inverse;

m_b1 = b1 * a0Inverse;

m_b2 = b2 * a0Inverse;

m_a1 = a1 * a0Inverse;

m_a2 = a2 * a0Inverse;

}

Page 38: 20141115 fx os-codereading

まとめ

Page 39: 20141115 fx os-codereading

Digital Biquad Filter

Page 40: 20141115 fx os-codereading

http://en.wikipedia.org/wiki/Digital_biquad_filter

Page 41: 20141115 fx os-codereading

http://en.wikipedia.org/wiki/Digital_biquad_filter

Page 42: 20141115 fx os-codereading

AudioNode

BiquadFilterNode BiquadFilterNodeEngine

WebCore::Biquad

AudioNodeEngine

Page 43: 20141115 fx os-codereading

source destinationBiquadFilter