2013年3月22日金曜日

WebAudioとgetUserMediaをつかって外部入力にエフェクトをかける【JS】

最近Javascriptにはまっています。 HTML5ではハードウエアの機能にアクセスする手段が整い始めていて、加速度センサやマイク入力を使用することが簡単にできるそうです。

WebAudio
 WebAudioを使用すると事前に用意したオーディオファイルを再生するだけでなく、その場で波形を生成して再生することも可能です。近年ではこれをつかったおもしろいWebサイトが登場しています。

WebAudio Drum Machine
 実際にあるドラムマシンをシミュレートしたもの






RealTime Analyser
音声を解析してビジュアル表示したもの







他にもたくさんあるのですが、サンプルとして2例ほど紹介しました。

 WebAudioでは用意された様々なノードをConnectすることで波形を生成したり、フィルターやディレイをかけたり、フーリエ変換をかけて音声を数値化することも簡単にできてしまいます。

getUserMedia
 getUserMediaはクライアントのWebカメラやマイク入力を扱うことができます。これはWebブラウザを通してP2Pでコミュニケーションをとるということを目指しているようで、ドキュメントを見るとP2Pに関する関数などもあることがわかります。今回はVideoの入力は用いず、Audioのみ用いました。

実装の説明とか
 実装に関する説明はググってみれば詳しく乗っているサイトがあるはずなので見てみてください。今回私が参考にさせていただいたサイトさまを以下に載せさせて頂きます。

  1. WebAudio API 解説
  2. SlideShare WebRTC + WebAudio API = スーパーサイヤ人 by girigiribauer
  3. WebAudio: live input / Stoyan's phpied.com
作ったもの
  1. 聴覚遅延フィードバックの簡単なデモ
  2. 2012年のイグ・ノーベル章のスピーチジャマーっぽいものを作ってみました。
  3. 低い周波数のSin波を流すデモ
  4. 0〜30Hzの音を聞いた時に脳はどういう反応するか調べてみたくて作りました。
ぶっちゃけ1は先程示した参考サイトの3を2は参考サイト1のコードを一部改変したものなのでアレですが、WebAudioとgetUserMediaの連携あたりのコードが日本語で検索してもあまり出ないので誰かの参考になったらいいなということでソースコードを載せときます。

聴覚遅延フィードバックの簡単なデモ

HTML

JavaScript
 function fire(e, data) {    
    log.innerHTML += "\n" + e + " " + (data || '');
  }

  var audio_context;
  var volume;

  function iCanHazUserMedia(stream) {
    
    fire('I haz live stream');
    
    var input = audio_context.createMediaStreamSource(stream);
    volume = audio_context.createGainNode();
    volume.gain.value = 0.8;
    var delay = audio_context.createDelay();
    delay.delayTime.value = 0.2;
    input.connect(volume);
    volume.connect(delay);
    delay.connect(audio_context.destination);
    
    fire('input connected to destination');
  }


  function changeDelayTime(value) {
    if (!delay) return;
    delay.delayTime.value = value;
    fire('DelayTime' + value);
  }

  function changeVolume(value) {
    if (!volume) return;
    volume.gain.value = value;
    fire('volume' + value);
  }

  (function init(g){
    try {
      audio_context = new (g.AudioContext || g.webkitAudioContext);
      fire('Audio context OK');
      // shim
      navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
      fire('navigator.getUserMedia ' + (navigator.getUserMedia ? 'OK' : 'fail'));
      // use
      navigator.getUserMedia(
        {audio:true},
        iCanHazUserMedia, 
        function(e){fire('No live audio input ' + e);}
      );
    } catch (e) {
      alert('No web audio support in this browser');
    }
  }(window));

低い周波数のSin波を流すデモ

HTML

JavaScript
  var audio = new webkitAudioContext();
  var osc = audio.createOscillator();
  var volume = audio.createGainNode();
  osc.connect(volume);
  volume.connect(audio.destination);
  osc.frequency.value = 12;
  osc.type = "sine";

  function show(data){
    log.innerHTML = "\n" + " "+(data || '');
  }

  function changeVolume(value){
    if(!volume)return;
    volume.gain.value = value;
  }
  
  function changeFreq(value){
    osc.frequency.value = value;
    show("Freq."+value+"Hz");
  }

  function play(){
    osc.start(0);
  }

マイク入力なんかは工夫すればギターのエフェクターの簡単なシミュレートなんかができるんじゃないかと思います。興味がある方挑戦してみてはいかがでしょうか。

0 件のコメント:

コメントを投稿