2012年は新しいものに関わり、いろいろ感じ、いろいろ試しと、ここ数年の中で最も変化に富んだ一年で、かつ、本当に楽しい一年でした。忙しかったですけどねf(^-^;)

今年の個人的なキーワードはこんな感じです。

2012年個人的キーワード

  • JavaScript
  • Web Audio API
  • Web MIDI API
  • Web RTC
  • HTML5
  • 信号処理
  • 音源(アナログ、FM)
  • ハッカソン
  • Google I/O
  • コミュニティ
  • アドベントカレンダー

そして、今年最大の残念な出来事はこれですね。

忘れもしない8月31日。現地でチャリの状態を確認をしたら壊れてて走れなかった事件。部品は取寄せ中だけど、フレームを変えてもいいかもと考え中。さて、来年は何回走りにいけるのかな〜。

2012年中は本当にお世話になりました。2013年もどうぞよろしくお願いいたします。

Web Music Developers JPのアドベントカレンダーの12月25日の記事です!

前回、前々回とWeb MIDI APIのレビューとエミュレーションライブラリ(WebMIDIAPIShim:Polyfill)を使ったMIDI INのサンプルを紹介してきました。MIDI INを紹介したのでMIDI OUTで何か作ろうと頭をひねったのですが「やっぱりMIDIファイルプレーヤーがいいかな〜?」という結論になりました。ちょっと思い返したら、12月2日のアドベントカレンダーで @toyoshim さんが「WebMidiLinkで遊んでみた」と題してSMFプレーヤーを公開されていることに気がつき、横着応用をして対応することにしましたf(^-^;) 数行の改変ですので、改変に関しては文字で説明させていただき、動作に関しては動画でお送りすることにしました。曲はYs2のオープニングでMIDIデータはOnLine Game Friend’sからダウンロードして使用しています。

原理はWebMIDLinkでは別ウィンドウに開いているWebシンセを鳴らす為にpostMessage() (HTML5 Web Messaging)を使い独自メッセージ(ほぼMIDIメッセージです)を送っていますが、このデモではそれをWeb MIDI APIのgetOutput()で取得したMIDIデバイスにsend()メソッドを使って送信しています。

またデモではエミュレーションライブラリとプラグイン(Jazz-Soft.netのJazz-Plugin)を使っていますが、数行のJavaScriptだけでMIDI機器を手軽に操ることのできる時代がそこまで来ていると思うとワクワクしちゃっていますf(^-^;) ちなみに今年2012年はMIDIの仕様が正式に世の中に出て30周年の節目(あと数日ですが、、、)。その節目の年にWeb MIDI APIという形で、もっと世の中に浸透するといいですね。

Web MIDI API 2nd WDについて3回に分けての紹介してきました。せっかくなので、すっごく簡単なまとめとしてスライドにもしましたので、もしよろしかったらどうぞ!! (追記:Web MIDI APIの仕様は日に日に更新されています。2013年1月8日の段階で既にこの説明の説明からは変更されていますのでご注意ください。)

Web MIDI API 2nd WD from Ryoya Kawai

というネタでWeb Music Developers JPの2012年のアドベントカレンダーを〆させて頂きます!!


Web Music Developers JPのアドベントカレンダーは2012年10月初旬の発足以来、実質的に最初のイベントでした。顔を合わせていないにも関わらず、たくさんの方にご賛同いただき、そして何よりもお忙しい師走の時期にお時間を裂いていただき、楽しい&興味深い&ハイレベルな内容のネタをご提供いただき本当にありがとうございました。心から御礼申し上げます。皆様の記事のお陰で僕自身は間違いなく毎日アドベントした毎日でしたが、僕と同じように多くの方がアドベントした毎日をお送り頂けたと信じております。今後もWeb Music Developers JPのコミュニティ活動は継続し発展をして行きたいと考えておりますので、今後ともどうぞよろしくおねがいいたします。

Web Music Developers JPのアドベントカレンダーの12月20日の記事です!

追記:Web MIDI APIの仕様は日に日に更新されています。2013年1月8日の段階で既にこの説明の説明からは変更されていますのでご注意ください。

前回は「Second Web MIDI API Working Draftのレビュー」を行いました。今回はWeb MIDI APIのWorkingDraft 第二版の末尾にあるサンプルコードのレビューを行います。とてもシンプルで分かりやすいサンプルコードになっていてとても参考になると思います。

ではさっそくレビューにはいります。

MIDI機器を取得

MIDI機器を扱う為の準備。

var midi = null;  // global MIDIAccess object

function onMIDISuccess( midiAccess ) {
 console.log( "MIDI ready!" );
 midi = midiAccess;  // store in the global 
}

function onMIDIFailure(msg) {
  console.log( "Failed to get MIDI access - " + msg );
}

navigator.getMIDIAccess( onMIDISuccess, onMIDIFailure );

getMIDIAccessメソッド成功時のcallback関数をonMIDISuccess[3-6行目]とする。onMIDISuccessでGlobal変数midi[1行目]にインターフェイスMIDIAccessを代入[5行目]。getMIDIAccessメソッドがエラーとなった場合のcallback関数としてonMIDIFailure[8-9行目]をと指定。

MIDI機器のリストアップ

MIDI入力元、出力先を指定する為にリストアップ。

function enumerateInputsAndOutputs( midiAccess ) {
 var inputs = midiAccess.enumerateInputs();
 var outputs = midiAccess.enumerateOutputs();
 var i;

 for (i=0; i<inputs.length; i++) {
  console.log(inputs[i]);
 }

 for (i=0; i<outputs.length; i++) {
  console.log(outputs[i]);
 }
}

インターフェイスMIDIAccessのメソッドenumerateInputs[2行目]/enumerateOutputs[3行目]を実行してMIDI機器のリストを取得して入力機器、出力機器を別々にconsole.logでデバッガのWebコンソールに出力[入力機器:6-8行目、出力機器:10-12行目]。

MIDIの入力信号を処理

受け取ったMIDI信号を処理。

function onMIDIMessage( event ) {
  var str = "MIDI message received at timestamp " + event.timestamp + "[" +
               event.data.length + " bytes]: ";
  for (var i=0; i<event.data.length; i++)
    str += "0x" + event.data[i].toString(16) + " ";
  console.log( str );
}

function startLoggingMIDIInput( midiAccess, indexOfPort ) {
  var input = midiAccess.getInput( indexOfPort );
  input.onmessage = onMIDIMessage;
}

インターフェイスMIDIAccessのメソッドgetInputで入力機器を指定して取得[9行目]し、MIDIメッセージを受信した場合のcallback関数(onmessage)をonMIDIMessageに指定[10行目]。 関数onMIDIessageは、MIDI入力を16進数変換してconsole.logでデバッガのWebコンソールに出力。

MIDIの出力ポートからMIDI信号を出力

MIDI信号を送信。

function sendMiddleC( midiAccess, indexOfPort ) {
  var output = midiAccess.getOutput( indexOfPort );
  output.send( [0x90, 60, 0x7f] );
   // note on, middle C, full velocity - omitting the timestamp means send immediately.
  output.send( [0x80, 60, 0x40], window.performance.now() + 1000.0 );
   // note off, middle C, release velocity = 64, 
   // timestamp = now + 1000ms.
}

インターフェイスMIDIAccessのメソッドgetOutputで出力機器を指定して取得[2行目]し、即座(timestampなし)に[90 60 7f]を実行するようMIDIメッセージを送信[3行目]、次に1000ms後に[80 60 40]が実行されるようMIDIメッセージを送信[4行目]。

  • [90 60 7f]:「MIDIポート1のC4を127の音量で発音する」というMIDIメッセージ
  • [80 60 40]:「MIDIポート1のC4を64の速度(機器によって異なる)で発音を停止する」というMIDIメッセージ

(RunningStatusの送信は許可されていません。)

MIDIの入力機器から受信したMIDIメッセージを出力機器へ送信するLoopback

var midi = null;  // global MIDIAccess object
var output = null;

function echoMIDIMessage( event ) {
  if (output)
    output.send( event.data, event.timestamp );
}

function onMIDISuccess( midiAccess ) {
  console.log( "MIDI ready!" );
  try { 
    var input = midiAccess.getInput( 0 );
    output = midiAccess.getOutput( 0 );
    input.onmessage = echoMIDIMessage;
  }
  catch (e) {
    console.log("Exception! Couldn't get i/o ports." + e );
  }
}

function onMIDIFailure(msg) {
  console.log( "Failed to get MIDI access - " + msg );
}

navigator.getMIDIAccess( onMIDISuccess, onMIDIFailure );
  • インターフェイスMIDIAccessを代入するGlobal変数midiを初期化[1行目]。
  • インターフェイスMIDIAccessのメソッドgetOutputで取得するインターフェイスMIDIOutputを代入するGlobal変数outputを初期化[2行目]。
  • getMIDIAccessメソッド成功時のcallback関数をonMIDISuccess[9-19行目]とする[25行目]。
  • MIDISuccessでは、getInputで先頭ににリストアップされた入力機器を取得[12行目]、getOutputで先頭ににリストアップされた出力機器を取得[13行目]、MIDIメッセージを受信した場合のcallback関数としてechoMIDIMessageを指定[14行目]。
  • echoMIDIMessageでは、選択した入力機器から受信したMIDIメッセージをそのまま選択した出力機器へ送信[6行目]。

というのがサンプルコードになります。 これでかなりイメージが湧くかな、と思います。

そして、Web MIDI APIの編集者の1人であるChris Wilsonさんが公開くださっているプラグインを使ったエミュレーションライブラリ(Polyfill)を実際に使って簡単なMIDI INのみのデモを作ってみましのた!!動作にはUSB-MIDIキーボードとJazz SoftのJazz-Pluginのインストールが必須となります。こんなに簡単にUSB-MIDI機器がブラウザにつながってしまう世の中になるのか〜、って思うとワクワクしちゃいます!

デモはこちらです!

それでは次回Web Music Developers JPのAdventCalenderの最終日は、MIDI OUTなデモが作成できたらな〜、と考えています!(作成できなかった場合、すみません。。。)

Web Music Developers JPのアドベントカレンダーの12月15日の記事です!

追記:Web MIDI APIの仕様は日に日に更新されています。2013年1月8日の段階で既にこの説明の説明からは変更されていますのでご注意ください。

2012年12月11日にWeb MIDI APIのWorkingDraft 第二版になりました。サンプルコードも追加され、また編集者の一人であるChris Wilsonさんがプラグインを使ったエミュレーションライブラリ(Polyfill)を公開してくださいました。仕様とサンプルを同時にレビューすると長くなりそうなので「仕様のレビュー」、「サンプルコードのレビュー」の2部構成で進めさせていただこうと思います。初回の今回は「仕様のレビュー」を行います。

さて、まずは「MIDI」と「Web MIDI API」についての簡単な説明です。 MIDIは「Musical Instrument Digital Interface」の略で、日本語にすると「電子楽器デジタルインターフェイス」、電子楽器の演奏データを機器間でデジタル転送するための世界共通規格です。そしてWeb MIDI APIです。HTML5のデバイスアクセスの仕様の1つとしてW3Cで策定が進められているウェブブラウザから”プラグインを使わずに”電子楽器へ直接接続を可能にする為のAPIです。とはいえ、最近のコンピュータでMIDIポートを搭載しているものはありませんので、基本的にはUSB-MIDIでの接続になります。Web MIDI APIの最終的な仕様は2013年の第3四半期に策定される予定になっています。

それではWeb MIDI APIの仕様のレビューをしていきます。 最初に全体的な構成です。(i)がinterface、(m)がmethodを示しています。また「->」の意味ですが、例えば「A -> return B」だとすると「Aを実行するとBがくる」という意味で使っています。

  • (i)NavigatorMIDIAccess
    - (m)getMIDIAccess -> return void
  • (i)MIDIAccess
    - (m)enumerateInputs -> return (i)MIDIPort
    - (m)enumerateOutputs -> return (i)MIDIPort
    - (m)getInput -> return (i)MIDIInput
    - (m)getOutput -> return (i)MIDIOutput
  • (i)MIDIPort
  • (i)MIDIInput
  • (i)MIDIOutput
    - (m)send -> return void
  • (i)MIDIEvent

次に(i)のついているinterfaceを説明します。

UserAgentのwindow.navigatorに属するObjectでMIDI機器へのアクセスを可能にします。

interface NavigatorMIDIAccess {
      void getMIDIAccess(successCallback, optional errorCallback)
    }

MIDIAccess

UserAgentに接続されているMIDI機器のリストアップ、またアクセスを可能にします。

interface MIDIAccess {
      sequence<MIDIPort> enumerateInputs();
      sequence<MIDIPort> enumerateOutputs();
      MIDIInput          getInput(MIDIPort or DOMString or short target);
      MIDIOutput         getOutput(MIDIPort or DOMString or short target);
}

MIDIPort

MIDIのInput/Outputポートで、名前、製造会社、MIDIポートのタイプ(input/output)、ユニークIDを提供します。

interface MIDIPort: EventTarget {
      DOMString    fingerprint;
      DOMString    manufacturer;
      DOMString    name;
      MIDIPortType type; // input or output
      DOMString    version;
}

MIDIInput

MIDIPortに組み込まれていて、さらにMIDIメッセージハンドラをデバイスへ割当てることが可能です。onmessageにMIDIメッセージを取得した時の処理を関数として書きます。

interface MIDIInput {
  attribute callback? onmessage;
}

MIDIOutput

MIDIPortに組み込まれていて、またMIDIメッセージをOutputポートへ送信するメソッドを提供します。

interface MIDIOutput {
  void send(sequence<short> data, optional DOMHighResTimeStamp? timestamp);
}

MIDIEvent

MIDIInputのonmessage handlerに渡されたEventオブジェクトで、MIDI data byteに加えてtimestampも含まれています。

interface MIDIEvent: Event {
  attribute DOMHighResTimeStamp timestamp;
  attribute Uint8Array          data;
}

最後に(m)のついているmethodの説明です。

getMIDIAccess(successCallback, optional errorCallback)

  • successCallback: MIDI機器が取得できた場合のCallback
  • -> (i)MIDIAccess を渡す
  • errorCallback: なんらかの理由でMIDI機器を取得できなった場合のCallback
  • enumerateInputs()
  • 引数なし
  • 利用可能なMIDI input port[(i)MIDIInput]のリストを配列で返す

enumerateOutputs()

  • 引数なし
  • 利用可能なMIDI output port[(i)MIDIInput]のリストを配列で返す

getInput(target)

  • target: (i)MIDIPort、または、(i)MIDIPortのfingerprint[DOMString]、
    または、 enumerateInputs()で取得したindex[short]

getOutput(target)

  • target: (i)MIDIPort、または、(i)MIDIPortのfingerprint[DOMString]、
    または、enumerateOutputs()で取得したindex[short]

send(data, optional timestamp)

  • data: 配列にしたshort
  • timestamp: DOMHighResTimeStamp(暫定?)

といった仕様になっています。 これだけではイメージするのは難しいと思いますが、「サンプルコードのレビュー」も続けて書きますので、そちらも合わせてご覧になるともっとイメージが湧くと思います。

ということで今回はここまでということで!

Web Music Developers JPのアドベントカレンダーの12月13日の記事です!

ネタは「緊急車両通りますよ〜っと!「Web Audioでドップラー効果」」です。 物理の授業で出てくる定番かな、って思います。 ドップラー効果は19世紀半ばにオーストリアの物理学者ドップラーさんが発見しました。簡単に説明すると、音は音源を中心に球状に音波の速度で伝わります。聞き手が音源に向けて一定の速度で近づくとき、音波の速度は (音波の速度)+(聞き手の速度) となりますが、音源から遠ざかる時は (音波の速度)-(聞き手の速度) となり、この音波の速度が異なることで音程が変わる、というのが原理です。

さて、ここからWeb Audioへの実装の下準備です。 今回は音は固定、聞き手(針金人間)が動くという想定で実装していきます。 変数と式はそれぞれ以下のようになります。

  • 音波の速度:340(m/s) で固定します。(14.17℃の時の音波の速度です)
  • 波周波数: F0 = V340 / Lambda
  • 初期状態において聞き手から音までの距離:d(m)
  • 聞き手の速度: v0 (m/s)
  • 聞き手の周波数:F1

(a) 音よりも右の場合:F1 = (V340 + v0) / Lambda = F0 ( V0 + U1 ) / V0

var tune = (V340+v0)/V340; // L32: js/dopplerEffect.js

(b) 音よりも左の場合:F1 = (V340 - v0) / Lambda = F0 ( V0 - U1 ) / V0

var tune = (V340+v0)/V340; // L32: js/dopplerEffect.js

(a)と(b)の分岐は、

d-v0*(i*interval)/1000 // L31: js/dopplerEffect.js

が、0より大きい場合は(a)、0より小さい場合は(b)となります。

このとき interval は JavaScriptのSetIntervalが呼ばれる間隔(ミリ秒)です。iはSetIntervalを何回通ったか、という変数にしていますので

(i*interval)/1000

は今までに聞き手が初期状態から動いた距離になります。

あとせっかくなので、PanとVolume(Gain)を変えてより臨場感を出します。 WebAudioでのPanは3次元で設定できますが、今回はその1次元だけを使います。最大値は1.0、最小値は-1.0、中央は0.0となっていますのでそのように動くように式を作ります。Volumeは最大値は1.0、最小値は0.0ですが、今回は音が大きくなり過ぎるのを避けるために最大値は0.5と設定しました。 音源は定番の救急車の「ピーポーピーポー」にしました。ヘッドホンで聞くとより臨場感のあるドップラー効果を聞けると思います。

実装したモノはこちらです。

1つもヒネリがなかった訳ですが、Web AudioってHTML5なのでテキストエディタとブラウザがあれば実装できるので、教育現場で使えたりするんじゃないかな〜、なんて密かに思っています。科学って実際に肌で触れるとより理解できると個人的には思っているので、特にWeb Audioに関してはそっちでも使われるといいな〜、なんて抱いています。