少し前に作ったものですが折角の機会なので公開しようと思います。
実験のための実装なのでUIがひどいことになっていますが見逃してください。
ChromeかFirefoxなら動くと思います。
デモ:http://ymmtmdk.github.io/jstuner/
ソース:https://github.com/ymmtmdk/jstuner
少しだけですが、WebRTCに絡む部分で何をしているか説明したいと思います。
getUserMediaを使っている周辺を抜粋します。CoffeeScriptです。
まず初期化の部分から。
Meteor.startup ->
navigator.getUserMedia = navigator.getUserMedia or navigator.webkitGetUserMedia or navigator.mozGetUserMedia or navigator.msGetUserMedia unless navigator.getUserMedia
window.AudioContext = window.webkitAudioContext unless window.AudioContext
if navigator.getUserMedia and window.AudioContext
navigator.getUserMedia
audio: true
,connectRecorder, -> alert "error capturing audio."
else
alert "not supported in this browser."
return
canvas = document.getElementById("wave")
canvasContext = canvas.getContext("2d")
Meteor.startupとなっているのは気にしないでください。onloadのようなものと思っていただければ。
このstartupでやっているのはブラウザ間の差異を吸収した上でconnectRecorder関数をコールバックにgetUserMediaを呼ぶだけです。この辺りは先日までのWebRTCカレンダーで書かれていますので是非読んでください。
次のconnectRecorderがこの記事におけるメインです。
connectRecorder = (stream) ->
audioContext = new AudioContext()
hzElement = document.getElementById("hz")
noteElement = document.getElementById("note")
bufferSize = 2048
recorder = audioContext.createScriptProcessor(bufferSize, 2, 2)
recorder.onaudioprocess = (e) ->
left = e.inputBuffer.getChannelData(0)
drawWave(left)
hz = Pitcher.pitch(left, audioContext.sampleRate)
return unless hz >= 30
note = new Note(hz)
hzElement.innerHTML = 'hz = ' + hz
noteElement.innerHTML = 'note = ' + note.name()
# connect the recorder
input = audioContext.createMediaStreamSource(stream)
input.connect recorder
recorder.connect audioContext.destination
まずWeb Audio APIの司令塔たるAudioContextを用意します。
次にチューナーの処理を担当するノードをaudioContext.createScriptProcessorで作り出します。
ここではrecorderと名づけているこのノードのonaudioprocessハンドラーにチューナー処理を登録します。
このハンドラーがバッファーが貯まるたびに呼ばれ、音程を算出するわけです。
次にaudioContext.createMediaStreamSource(stream)として入力ノードを取り出します。
この入力ノードにさきほどのrecorderノードを接続します。
さらにrecorderノードにaudioContext.destinationノードを接続して完成です。
入力ノード > チューナーノード > 出力ノード
この様にWeb Audio APIでは各役割をこなすノードを作って、それを接続する、という手順でプログラムが構成されます。ここに出た以外に色々なノードが用意されてますの詳しくはリファレンスを御覧ください。
以上、なんとも雑な説明ではありますが、割と簡単に音が扱えるのねと思われたなら幸いです。
Web Audio API (日本語訳):http://g200kg.github.io/web-audio-api-ja/#ModularRouting
Web Audio API:http://www.w3.org/TR/webaudio/