河合良哉

【Web Audio API + Web MIDI API】ブラウザで電子楽器を作ってみよう!

ブラウザ上で音を扱うというと、直接音を加工できるWeb Audio API、ブラウザから直接MIDIデバイスと接続できるWeb MIDI APIの2つがここ数年の間に利用可能になり、実際のWebサイトでも使われるようになりました。
今回は「ハンズオンだともっとよかった」というお声をいただきましたHTML5 Conference 2015での講演内容を元に、2つのAPIの説明と、実際にブラウザ上に電子楽器の1つであるシンセサイザーを作ってしまうという記事です。

記事中のサンプルはGitHubに公開していますので、そちらも合わせてご参照ください。

利用するAPIの説明

Web Audio API

短く一言で説明すると「ブラウザ上で音を直接作ったり、いじったりすることのできるAPI」です。もう少し難しく言うと「ブラウザ上で波形処理を可能にしたAPI」となります。
Web Audio APIの理解を深めるためにまず「音」とは何かを考えてみたいと思います。Wikipediaには以下のように書かれています。

  • 物の響きや人や鳥獣の声
  • (物体の振動が空気などの振動(音波)として伝わって起す)聴覚の内容
  • またはそのもととなる音波
「引用」『フリー百科事典 ウィキペディア日本語版』より。
2015年3月16日 8:30 UTC
http://ja.wikipedia.org/wiki/%E9%9F%B3

響き振動音波と出てきました。実は、音を目に見える形にするとになるのです。Web Audio APIも原理は同じで、波を与えて音として出力しています。そして、その波の形(波形)をいじる(処理)して様々な音を作り出すとご理解いただけばよいと思います。

原理の説明はここまでにして、最初に声を取得して、その声をWeb Audioでピッチシフト(音を高くしたり、低くしたりする効果)、Delay(音を遅らせる効果)の加工を行うデモをご紹介いたします。(できるだけマイクとヘッドホンをご用意ください)ピッチシフト&Delayのライブデモ

PitchShift&Delay

ノブとボタンの説明▼

(1) PitchShift ON/OFF

(2) Shiftの種類:(上:高い、下:低い)

(3) Delay ON/OFF

(4) Delayの種類:並列/直列

(5) Feedback量

(6) Delay時間


delay-parallel


ノードグラフ(Web Audioでは処理をする1つ1つをノードと呼び、それらをつなぎ合わせて1つのグラフにします)は上図のようになっています。ピッチシフト&DelayのライブデモのDelayをONにして、種類を直列にする((4)のスイッチを下にする)とこのような接続になります。直列につなげると、マイクで拾った音が(6)Delay時間だけ遅れてスピーカから出るようになります。
このノードグラフをWeb Audio APIで書くとこうなります。(ピッチシフト部分、Delay部分をObjectにしてまとめている関係上、ゼロから書くともう少し長く、複雑になります)(ライブデモ

このように、Web Audio APIを使うと、今まではプラグインを使う以外に方法がなかったWebブラウザ上でのリアルタイムな波形処理を、比較的簡単に行うことが可能です。

Web MIDI API

短く一言で説明すると「ブラウザとデバイス間でMIDIメッセージを送受信するためのAPI 」です。MIDIとは Musical Instrument Digital Interface の略で、電子楽器の演奏データをデバイス間でデジタル転送するための世界共通規格であり、物理的な送受信回路・インタフェース、通信プロトコル、ファイルフォーマットなど複数の規定からなっています。Web MIDI APIは特にこの中の通信プロトコルをWebブラウザへの実装したAPIです。

Web MIDI APIの特徴は外付けのMIDIデバイス※0とWebブラウザが直接接続できるところです。ですのでWeb Audio APIのようにそれ単体で音が鳴ったりする訳ではなく、MIDIデバイスからWebブラウザで動くアプリケーションをコントロールしたり、またWebブラウザからMIDIデバイスコントロールするために利用します。よって本記事では最初にWeb Audio APIを使った電子楽器アプリケーションを作り、それをWeb MIDI APIを使って外付けのMIDIデバイスからコントロールするというシナリオで進めさせていただきます。

※0 MIDIデバイス: 楽器関連では鍵盤をはじめ、ドラムパッド、スライダー、ノブ等があり、楽器以外ですと、ステージ上のセットを楽器等と一緒にMIDIでコントロールしてしまおうという発想で照明機器、その他噴水、爆破、炎の制御に使われていることもあります。

なお、やや長い記事になってしまいましたので、ソースコードの量の少なさを体感していただき、その解釈は後回しにしてデモを触っていただくのがよいと思います。「電子楽器を実装する」というと難しそうに聞こえるかもしれませんが、そこまで難しくもありませんので実装に挑戦していただけるとうれしいです。

Web Audio API で電子楽器を実装する

電子楽器と言ってもその種類は複数あります。今回はその中からアナログシンセサイザーとFMシンセサイザーを実装してみます。

Web Audio API でアナログ・シンセサイザー

アナログ・シンセザイザーはアナログ回路を用いて信号処理を行うことで音を出す方式のシンセサイザーです。そのアナログ回路をWeb Audio APIを使って実装していきます。まずはどんな音が出るか完成形のデモで試してみてください。

AnalogSynthApp

画面上にある2つのスライダを動かすと音色を大きく変化させることができると思います。それでは原理を見てみましょう。

このシンセサイザーは以下の3つの部品を使っています。

  • 基本の信号・波形を作り出す発振機※1 (VCO0、VCO1)
  • 波形を加工するフィルタ(VCF)
  • 低い周波数の制御信号を発振機から発生させて送ることで周期的な変化を与える(LFO)

これらを接続して下図のノードグラフを作ります。 AnalogSynthNodeGraph

※1 発振機: 波を発生させる部品で、オシレータ(Oscillator)とも呼びます。

ソースコードは以下のようになります。(ライブデモソースコード

これで発音されます。が、このままですとそのままの音が出るだけですので面白くありません。そこで、それぞれのノードのパラメータを変更してみます。コメント化していた「値を変更」の以下4行を生かしてみます。(ライブデモソースコード
先程より音色が明るくなったと思います。完成形のデモのVCFのスライダを右に動かしたのと同様な値の変更を行いました。VCFは設定値より低い周波数を通す(ローパス)フィルタになっていて、そのパラメータを大きくしてより多くの明るい部分を通して明るい音色を出しています。

さらにシンセサイザーっぽい音にするべく、音量や音高などを時間で変化させるADSR※2 と呼ばれてるエンベロープ※3 の機能実装します。ここではこのエンベロープを発振機(Oscillator)の音量(VCO0、VCO1)に適応しますので音量を調節するGainNodeを(1)、(2)へ追加します。そのソースコードは以下のようになります。(ノード作成、接続部分のみ抜粋)

※2 ADSR:下図のように波形を処理する場合のそれぞれも部分を指しています。
ADSR-DIAGRAM
  • A (Attack) :音の出始め(例えば鍵盤を押した瞬間)から最大音量に到達する時間
  • D (Decay) : Attackで到達した音量最大からSustainに到達するまでの時間
  • S (Sustain) : Decayから音が出続けている間保つ音量
  • R (Release) : 演奏終了(例えば鍵盤を離した瞬間)から音量ゼロまで到達する時間
※3 エンベロープ: ピーク(最大値)を描いた曲線。特にここでは音量のピークを描く曲線のことを指しています。

続いて、実際にエンベロープを適応していきます。Web Audioには今回のエンベロープのような時間と目標値を指定して、その間を連続的に値を変化させるオートメーションの機能も提供されており、非常に簡単に実装することが可能です。今回は「指定した値まで直線的に連続して値を変化させる」linearRampToValueAtTime()を使いオートメーションを行います。 ソースコードは以下になります。(エンベロープ部分のみ抜粋)

1つ前のライブデモにエンベロープを適応させたライブデモはこちらになります。(ソースコード

以上でアナログ・シンセサイザーの骨格が完成しました。楽器にするためには、パラメータをコントロールするスライダー、ノブ、VCOの周波数を変えて音階決める鍵盤を取り付ける作業を残すのみとなります。より個性的な音を作る場合、例えばノードグラフにVCOをもう1つ並列に追加したりすることで、更に多彩な音色を作ることが可能になりますので試してみてはいかがでしょうか。

ちなみに完成形のデモで使っているノブ、鍵盤は楽器、Audio系のアプリケーションには欠かせないカッコイイノブが簡単に取り付けられるスゴク便利なツールwebaudio-controlsというPolymerエレメント(詳しくはこちらをご覧ください)を利用して実装しています。

アナログ・シンセサイザーの実装の説明は以上になります。

Web Audio API でFMシンセサイザー

FMシンセサイザーのFMはFrequency Modulationの頭文字を取っていて、その名の通り周波数を変調して音を作り出す方法で、周波数変調と呼んでいます。(しかしながら、Web Audio APIに用意されている発振機では周波数変調ができません。よって、ここでは複数の波を掛け合わせFMシンセサイザーっぽい音を作っていることにご注意ください。本当のFMシンセサイザーを作るためには周波数変調可能な発振機の作成が必要です)
それでは、どんな音が出るか完成形のデモを試してみてください。 AnalogSynthApp

アナログ・シンセサイザーよりももう少し金属音的な音が出ていると思います。画面右上のプルダウンメニューにて音色も変更することができるようになっていますので、ぜひお試しください。

さて、実装に関してですが複数の発振機(Oscillator)を接続していきます。ここで、掛け合わせる側の発振機(Oscillator)をモジュレータ、その影響を受けて掛け合わされる側の発振機(Oscillator)をキャリアと呼びます。今回の実装はモジュレータとキャリアを1つづつ直列に接続し、更にモジュレータを自身にFeedbackしするような接続にします。ノードグラフに表すと以下のようになります。 fmsynthnodegraph 少し余談ですが、モジュレータの数が増やすと接続の組み合わせによって複数の接続方法が考えられます。その接続方法の1つ1つをアルゴリズムと呼んでいます。

ソースコードをみてみましょう。(ライブデモソースコード

これで発音されます。が、アナログ・シンセサイザーの時と同様にそのままの音が出るだけで面白くないので、ここでもパラメータを変更してみます。コメント化されている「値を変更」の以下7行を生かしてみます。(ライブデモソースコード
なんと、音がキラキラしてきました。さて、ではアナログ・シンセサイザーのときと同じようにエンベロープを適応してみます。ソースコードは以下になります。(エンベロープ部分のみ抜粋)

1つ前のライブデモにエンベロープを適応させたライブデモはこちらになります。(ソースコード

FMシンセサイザーの骨格もこれで完成しました。完成形のデモではパラメータの集合に音色名をつけて選択できるようにしていますが、アナログ・シンセサイザーのときのように、ノブやスライダでパラメータをコントロールするという方法も実現可能ですので、いろいろとお試しいただくと楽しいと思います。

アナログ・シンセサイザーとFMシンセサイザーの実装を通して「Web Audio APIで電子楽器を作ってみる」をやってきましたが、印象はどうでしょう。「Web Audio APIって簡単で楽しいな〜」と感じていただけているととても嬉しいのです!

さて、それでは次のセクションでは作成した電子楽器を本物の楽器のように鍵盤から演奏できるように、MIDIの接続を説明します。

Web MIDI APIを使う

先ほど少しだけMIDIとWeb MIDI APIについてご説明させていただきました。さらに理解したいという方はDTM界隈で著名な藤本健さんの”DTMステーション”に「今さら聞けない、「MIDIって何?」「MIDIって古いの?」」というMIDIを理解するのにドンピシャな記事が公開されましたので、詳細はそちらにお任せするとしてここでは粛々と実装を行っていきたいと思います。

ちなみに2015年3月現在でWeb MIDI APIが動作するブラウザはGoogle Chromeだけとなっています。また、その使用にはフラグの変更(Web MIDI APIを有効にする方法)が必要ですので、お試しになる前にフラグの変更を忘れないようにお願い致します。(MIDIデバイスがお手元になく、Macをお使いの場合はEasy MIDI Freeをお使いいただくと演奏できるはずです)

コンピュータに接続されているMIDIデバイスをブラウザで取得するには以下のコードを書き、MIDI InputとOutputのデバイスリストを取得します。

MIDI Inputを使う場合、例えば使いたいMIDI Inputデバイスがinputsの先頭にリストされた(index=0)とします。その場合は以下のようにイベントハンドラをつけてあげます。

こうすることで、inputsの先頭にリストされている外部MIDIデバイスからMIDIメッセージが飛んできた場合にMIDIメッセージとタイムスタンプをコンソールに出力するようになります。

MIDI Outputを使う場合、例えば使いたいMIDI Outputデバイスがoutputsの先頭にリストされた(index=0)にあったとします。

とすると、outputsの先頭にリストされたMIDIデバイスに対して0x90, 0x45, 0x3fというMIDIメッセージを今すぐ(第2引数)送信します。MIDIメッセージ0x90, 0x45, 0x3fは、A4の音(0x45)を、50%の音量(0x3f)でチャンネル1を音を鳴らしなさい(0x90)、です。

といっても、MIDIに慣れ親しんでいない場合は実装のハードルが高いと思っています。そこでWeb MIDI APIの実装を簡単にするPolymerエレメントを公開しています。それが、 x-webmidiです。x-webmidiを使うとHTMLタグを5つ追加する(そのうち1つはWeb ComponentsのPolyfill)だけで、コンピュータに接続されているMIDIデバイスを取得して、セレクトボックスを生成して表示する、までを行ってくれます。MIDI InputデバイスからのメッセージはEventハンドラを、またMIDI Outputデバイスへのメッセージの送信は.sendRawMessage()を使い生のMIDIメッセージを、.sendHRMessage()を使いMIDIに慣れていない方でも分かるようにメッセージを送信できるようになっています。コードにするとこうなります。

それでは、Web Audio APIで作ったシンセサイザーを、MIDIデバイスから操作できるように実装していきます。演奏するためには、音階を変えるのですが、そのためには発振機(Oscillator)の周波数を変更する必要があります。MIDIの鍵盤は1つ1つに連番の番号がついていてこれをMIDIノートナンバー(ノートナンバーでページ内を検索)と言いますが、そのMIDIノートナンバーから周波数に変換する必要がありますが、それをコードにすると以下のようになります。

しかし、x-webmidiを使うとEventの引数として演奏した鍵盤の番号とそれに対応する周波数が取得することができるので、MIDIノートナンバーから周波数の変更をする必要はありません。これらをアナログ・シンセサイザーとFMシンセサイザーに実装をするとこのように実装できます。

でもこのままだと単音しか出なくて楽しくないので、和音も出せるようにしちゃいます。そうするとこうなります。

自作した楽器を両手で演奏できちゃいますよね。立派な楽器のできあがりです!「Web Audio APIとWeb MIDI APIを接続するのって簡単で楽しいな~」と感じていただけているととても嬉しいのです!

番外編

2015年3月13日(金)にWeb MIDI APIはGoogle Chromeにおいて実験的APIから標準のAPIとなることが承認されました。これによって、フラグを変更することなく(これが不要になる ▶ Web MIDI APIを有効にする方法)、Web MIDI APIを利用することが可能になります。この変更がChromeに適応されるまでにはもう少し時間がかかりますが、実現するとWeb MIDI APIがChrome APPsでの利用も可能になります。(Chrome Appsとは:英語)Chrome Appsにしてしまえばオフラインでも利用可能※4になります。ですので、ユースケースとして例えばライブでWeb Audio API、Web MIDI APIを使った自作楽器でパフォーマンスを行いたい、という場合に活躍してくれることでしょう。

そこで、今回ご紹介した2つのシンセサイザーをChrome Appsにして公開してみました。(Web MIDI API部分の動作はしません:2015年3月14日現在)

細かいところですが、Chrome AppsはCSP(Contents Security Policy)によってスクリプト(JavaScript等)をHTMLファイルへインラインで書くことが禁止されていますが、これら2つのアプリにはPolymerエレメントを使っています(インラインJavaScirptが書かれたHTMLファイルです)のでちょっと困ったことになります。それを解決してくれるBuildツールにvulcanizeがあります。”csp”オプションをつけてツールを実行することでHTML部分ととスクリプトを分けてくれますので、ソースコードの変更なしにCSPに合致したソースコードを生成することが可能なのです。

$ vulcanize --csp -o build.html index.html

Google Chromeのフラグの変更なしにWeb MIDI APIの利用が可能になることで、Web Audio API、Web MIDI APIを使ったブラウザで作った電子楽器の使えるシーンがより拡大されることを期待しています。manifest.jsonとバックグランドで動作させるJavaScriptの2つのファイルを用意することで簡単に実現できますので、ぜひ試してみてください。

※4 オフラインでも利用可能:Webアプリは大きく分けて以下の2つの種類があります。
  • Hosted App: HTML、CSS、JavaScript等の全てのリソースファイルがWebサーバに保存されているWebアプリのことです。URLにアクセスしてアプリを起動する所謂従来からよく知られているWebアプリです。
  • Packaged App: Hosted Appとは違い、HTML、CSS、JavaScript等のリソースファイルがzip等で1つになっており、Webブラウザにインストールします。Webブラウザにインストールされたリソースから起動します。そのため、オフラインでも動作が可能になっています。Chrome Appsはこの方式のWebアプリです。

おわりに

いかがでしたでしょうか?Web Audio APIで用意されている発振機(Oscillator)は正弦波、ノコギリ波、矩形波、三角波の基本的な波形しかなく、それ単体では単調な音しか出なかったのが、少し波形処理をしてあげることで楽器らしい音にすることができたと思います。さらにはWebブラウザに鍵盤をつなげると、和音まで演奏できるようになってしまいました。

さて、自作で楽器が開発ができるのはWebブラウザが初めてでしょうか?いえ、そんなことはありません。Windows、Mac、Android、iOS等の所謂Nativeな環境でも開発することは可能でした。では、Webブラウザで開発できるようになった利点はなんでしょう。それは楽器を開発するということに対するハードルが一段と低くなったところです。WebアプリケーションはWeb標準言語で開発します。Web標準言語の開発はブラウザとテキストエディタで行います。ですのでコンピュータを買ってきたその日から開発が可能です。さらにご説明させていただいた通り、こんなにも簡単に楽器を開発することができるのです。

今までは難しそうなイメージがあった音楽を使ったアプリケーション。しかしWeb Audio APIを使うと音を作ることができます。またWeb MIDI APIを使うと外部のMIDIデバイスとの双方向の操作が可能です。開発するWebアプリケーションに音を鳴らす要素を追加してみる、または遊び心でMIDIデバイスからWebアプリケーションを操作してみる等、ほんの少しの遊び心があなたのWebアプリケーションをより面白くする可能性があります。これを機会にいろいろなとことで試してみてはいかがでしょうか?

セッションの資料と動画

2015年1月25日に行われたHTML5 Conference 2015の当日の資料と動画へのリンクです。こちらも合わせて御覧ください。

動画

スライド

de:code 2017
Powered byNTT Communications

tag list

アクセシビリティ イベント エンタープライズ デザイン ハイブリッド パフォーマンス ブラウザ プログラミング マークアップ モバイル 海外 高速化 Angular2 AngularJS Canvas Chrome Cordova CSS de:code ECMAScript Edge Firefox Google Google I/O 2014 HTML5 Conference 2013 html5j IoT JavaScript Microsoft Node.js PhoneGap Polymer React Safari SkyWay TypeScript UI UX W3C W3C仕様 Webアプリ Web Components WebGL WebRTC WebSocket