More than 1 year has passed since last update.

この記事はOpal Advent Calendar 2016の12日目の投稿として書いています。

今日は、10日目の続きでWeb Audio APIのラッパーを作ろうと思います。

Web Audio APIのすべてを実装すると良いとは思うのですが、記事にするにはボリュームが大きすぎると思います。
ある程度のものを作って大体のつくりかたが分るところまでできれば本記事としてはよいでしょう。9日目に作ったサンプルが動く程度のものを作ってみましょう。

まずはAudioContextをつくりましょう。

module Audio
  class Context
    include Native

    def initialize
      super `new AudioContext()`
    end
  end
end

NativeincludeすることでJavaScriptのネイティブオブジェクトをラップしたクラスを作ることができます。
イニシャライザはネイティブオブジェクトを引数に取るので、ここではラップしたコンテキストクラスでAudioContextオブジェクトを生成してsuperに渡すことにします。

exampleのほうも更新しましょう。

examples/app/application.rb

require 'opal'
require 'opal/audio'

context = Audio::Context.new
source = context.createBufferSource

request = Native(`new XMLHttpRequest()`)
request.open('GET', 'sound.mp3', true)
request.responseType = 'arraybuffer'
request.send

request.onload = Proc.new do
  res = request.response
  context.decodeAudioData(res) do |buf|
    source.buffer = buf
  end
end
source.connect(context.destination)
source.start(0)

sound.mp3を読めるようにするためにSinatraを使うようにしましょう。
examples/config.ru等を[8日目」(http://qiita.com/youchan@github/items/735ffad1a5c406ebb30c)の記事を参考にSinatra版に変更しましょう。

このまま実行すると、createBufferSourceというメソッドがないと怒られます。
createBufferSourceメソッドを追加しましょう。
そのまえに、メソッド名はそのままでよいでしょうか?ここはRubyなのでスネークケースのメソッド名にしたいところです。
create_buffer_sourceという名前でネイティブのcreateBufferSourceを呼ぶようにしましょう。
Nativeにはこういうときに便利なalias_nativeメソッドがあります。

    alias_native :create_buffer_source, :createBufferSource

ほかにも、decode_audio_datadestinationも定義しましょう。destinationのほうは、JavaScript側ではプロパティとしてもっているのでnative_readerを使います。

    alias_native :decode_audio_data, :decodeAudioData
    native_reader :destination

examples/app/application.rbのほうも直して実行しましょう。
音が鳴りましたか?

AudioContextだけをラップしましたが、他のオブジェクトのラッパーは書いていません。たとえばcreate_buffer_sourceの戻り値はいったい何なのでしょう?
pで表示してみると、どうやらNativeクラスのオブジェクトのようです。
このようにOpalは特にラッパークラスを書かなくてもいい感じにラップしたオブジェクトを返してくれます。
今回のケースのようにスネークケースにしたいとかよりRubyishなラッパーにしたい場合にはラッパークラスを書けばよいでしょう。
OpalはRubyとJavaScriptのコードの間の橋渡しがとても良くできていると思います。JavaScriptのプロジェクトに一部Rubyを使うということも可能でしょう。これはOpalのひとつの魅力だと思います。