20140830 firefox os-sampler

Preview:

DESCRIPTION

An introduction of Web Audio API and their friends by explaining Web based sampler app for Firefox OS. This slide is for Firefox OS meeting at 2014/08/30 in Hiroshima, Japan.

Citation preview

サンプラーアプリを作ってみた

Mozilla Japan テクニカルマーケティング 清水智公

中国Firefox OS勉強会2nd, 2014/08/30

about:me

2

FFiirreeffooxx をよろしくね!

清水智公(しみずのりただ)

• Mozilla Japan テクニカルマーケティング

• 慶應義塾大学政策・メディア研究科非常勤

• @chikoski • https://slideshare.net/chikoski/

4

サンプラーをつくってみた

5

サンプリング

• https://www.ted.com/talks/mark_ronson_how_sampling_transformed_music

6

Audio 要素

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

7

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

Web Audio API

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

8

オーディオグラフ

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

9

オーディオノード

10

分類 クラス名

入力OscillatorNode, AudioBufferSourceNode, MediaElementAudioSourceNode, MediaStreamAudioSourceNode

エフェクトBiquadFilterNode, ConvolverNode, DelayNode, DynamicsCompressorNode, GainNode, WaveShaperNode, PeriodicWaveNode

出力 AudioDestinationNode, MediaStreamAudioDestinationNode

その他 PannerNode, AnalyserNode, ChannelSplitterNode, ChannelMergerNode, ScriptProcessorNode

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

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

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

11

var elm = document.querySelector("audio");!!var context = new AudioContext();!var source = context.createMediaElementSource(elm);!source.connect(context.destination);

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

12

var elm = document.querySelector("audio");!!var context = new AudioContext();!var source = context.createMediaElementSource(elm);!source.connect(context.destination);

source context.destination

フィルタの追加

13

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

BiquadFilterNode:周波数によるフィルタ

14

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

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

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

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

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

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

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

allpass 全ての音を通過させる

BiquadFilterNodeの使い方

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

15

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

AudioParamオブジェクト

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

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

16

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

ループを伴うグラフの作成

17

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);!

ループを伴うグラフ(つづき)

18

source

context.destination

delayfeedback dry

wet

var source = context.createMediaElementSource(elm);!var delay = context.createDelay();!var wet = context.createGain();!var dry = context.createGain();!var feedback = context.createGain();

ループを伴うグラフ(つづき)

19

source

context.destination

delayfeedback dry

wet

source.connect(dry);!dry.connect(context.destination);

ループを伴うグラフ(つづき)

20

source

context.destination

delayfeedback dry

wet

source.connect(delay);!delay.connect(wet);!wet.connect(context.destination);!

ループを伴うグラフ(つづき)

21

source

context.destination

delayfeedback dry

wet

delay.connect(feedback);!feedback.connect(delay);!

波形の可視化

• フィルタの効き方を目で確認するのに便利 • 概要 • AnalyserNode で高速フーリエ変換する • Canvas 要素へ 1の結果を描画する • 上記二つを1フレームごとに実行する

22

波形の可視化:AnalyserNode

23

var elm = document.querySelector("audio");!!var context = new AudioContext();!var source = context.createMediaElementSource(elm);!var lowpass = context.createBiquadFilter();!lowpass.type = "lowpass";!var analyser = context.createAnalyser();!!source.connect(lowpass);!lowpass.connect(context.destination);!lowpass.connect(analyser);

source context.destinationlowpass

analyser

波形の可視化:波形の描画

24

var update = function(){! var data = ! new Uint8Array(analyser.frequencyBinCount);! analyser.getByteFrequencyData(data);! fadeOut(gc);! gc.beginPath();! for(var i = 0; i < this.data.length; i++){! var pos = position.call(this, i);! if(i == 0){gc.moveTo(pos.x, pos.y);}! else{gc.lineTo(pos.x, pos.y);}! }! gc.stroke();! window.requestAnimationFrame(update);! };

• gcはCanvasの2Dコンテキスト • fadeOut は画面をクリアする自作関数

波形の可視化:周波数成分の分析

• frequencyBinCount属性で分析結果になる、周波数帯の数が取得できる

• getByteFrequencyDataメソッドを呼ぶことで、各周波数帯の強さが0~255の256段階で取得できる

25

var data = ! new Uint8Array(analyser.frequencyBinCount);!analyser.getByteFrequencyData(data);

サンプリング

• MediaRecording APIを利用して音声をblobに変更 • オーディオグラフとの接続にはMediaStreamDestinationNodeを利用する

26

source context.destination

mediaStreamDestination

recorder

オーディオグラフ参照

サンプリング(つづき)

• MediaStreamDestinationNode:WebRTCでのストリーミング先を表すノード

27

var elm = document.querySelector("audio");!var context = new AudioContext();!var source = context.createMediaElementSource(elm);!!var mediaStreamDestination = ! context.createMediaStreamDestination();!!source.connect(context.destination)!source.connect(mediaStreamDestination);

サンプリング(つづき)

• MediaRecorderオブジェクト:WebRTCのストリームを記録する

• MediaStreamDestinationNodeとつなぐことで、オーディオグラフの出力を記録できる

28

var recorder =! new MediaRecorder(mediaStreamDestination.stream);!!recorder.start(); // 録音開始!recorder.stop(); // 録音終了

サンプリング(つづき)

• 記録したデータはすぐ利用できる訳ではない • 利用可能時にdataavailableイベントが発火 • Blob イベントの一種 • イベントオブジェクトのdata属性の参照で、Blobとして記録が取得できる

29

recorder.ondataavailable = function(event){!  console.log(event.data);!};

オーディオデータのデコード

• Blob → ArrayBuffer → AudioBuffer • AudioContextのdecodeAudioDataメソッドを利用してデコードする

30

var reader = new FileReader();!return function(blob, context){! return new Promise(function(resolve, fail){! reader.onload = function(event){! context.decodeAudioData(event.target.result, ! resolve);! };!! reader.readAsArrayBuffer(blob);!! });! };!}

オーディオデータのデコード(つづき)

• デコードされたデータの再生にはBufferSourceNodeを利用 • startメソッドで再生開始、stopメソッドで停止 • loop、開始時間、再生時間などをしてい可能 • stopメソッド呼び出し後、startメソッドを呼べないことに注意

31

var bufferSource = context.createBufferSoruce();!bufferSource.buffer = buffer; // デコードだされたデータ!bufferSource.start(); // 再生開始!bufferSource.stop(); // 再生終了

マイクの利用

• GetUserMedia APIを利用する • 利用にはmanifest.webappへの設定が必要 • 取得したマイクからのストリームからMediaStreamSourceNodeを作成することで、マイクからの入力おWeb Audio APIで処理できる

32

マイクの利用(つづき)

• manifest.webapp の permissionsに設定する • 項目名はaudio-capture • description属性に利用目的などを書いた説明文をつけておく

33

"permissions":{! "audio-capture": {! "description": ! "capture sound with mic input for sampling"! }!},

マイクの利用(つづき)

• navigator. getUserMedia はベンダープレフィックスがついている • 引数:メディアの種類、成功時コールバック、失敗時コールバック

• 成功時のコールバックには、マイクからのストリームが引数として渡される

34

navigator.getUserMedia = ! navigator.getUserMedia || navigator.mozGetUserMedia;!!navigator.getUserMedia({audio:true}, ! resolved, failed);

マイクの利用(つづき)

• GainNodeを挟むと、マイクの入力レベルをコントロールできる

35

var context = new AudioContext();!function resolved(stream){! var source = ! context.createMediaStreamSource(stream);! var gain = context.createGain();! source.connect(gain);! gain.connect(context.destination);!!}

source context.destinationgain

マイクの利用(つづき)

• マイクからのストリームはstopされるまで生きます • 使わなくなったらstopしたほうが良い

36

window.addEventListener("beforeunload", ! function(event){! stream.stop();!});

まとめ

37

サンプラーをつくろう

• Web Audio API:音声の処理 • オーディオグラフ • オーディオコンテキスト • GetUserMedia API:マイクの扱い • Media Recording API:録音

38

Web Audio Editor

• Firefox の開発ツールにある機能 • オーディオグラフの可視化、パラーメータの変更が可能

39

デモアプリ

• https://github.com/chikoski/sample-sampler

• 依存するライブラリ • RequireJS : http://requirejs.org/

• framework7:http://www.idangero.us/framework7/

40

レファレンス

• Web Audio API の利用https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API

• Web Audio APIhttps://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API

• Web Audio Toyhttp://uglyhack.appspot.com/webaudiotoy/

• Vocoderhttp://webaudiodemos.appspot.com/Vocoder/

41