LoginSignup
9
10

More than 5 years have passed since last update.

DartでWeb Audio APIを使って音を鳴らす

Last updated at Posted at 2014-06-22

DartでWeb Audio APIを使って音を鳴らしてみます。

以下のページを参考にします。

Getting Started with Web Audio API - HTML5 Rocks

Getting Started with the Web Audio API | Dart: Structured web apps

上のページではJavaScriptでの説明になっていますが、Web Audio APIはWeb標準のAPIですので、言語が変わってもAPI仕様は変わりません。(変わりません、というかWeb標準API自体が、API仕様を統一させましょう、というものなので、仕様を変えてしまっては非難を浴びるだけです)

下のページは、上の解説を元にしたDartでのサンプルです。

下ごしらえ

pubspec.yamlには特別な記述は行いません。

pubspec.yaml
name: dartwebaudio
dependencies:
  browser: any

pub getして依存パッケージを取得しておきます。

$ pub get

以下の様なディレクトリ構成でファイルを作成していきます。

├── pubspec.yaml
└── web
    ├── dartwebaudio.dart
    ├── index.html
    └── sample.ogg

HTML側には、音再生用のボタンを用意しておきます。

index.html
<title>Web Audio on Dart</title>
<input type="button" value="loading..."></input>
<script type="application/dart" src="dartwebaudio.dart"></script>
<script src="packages/browser/dart.js"></script>

ボタンに表示する文言を"loading..."にして、音素材の読み込みが完了したら"play"に切り替えて再生できる状態になったことがわかるようにする工夫をしてみます。

下ごしらえが済みましたので、Web Audio APIを使っていきます。

Dartのコードを書く

まずはdart:htmldart:web_audioimportしておきます。

dartwebaudio.dart
import 'dart:html';
import 'dart:web_audio';

Web Audioで用いる各種変数を用意しておきます。

dartwebaudio.dart
AudioContext context;
AudioBuffer sampleBuffer;

AudioContextを作っておきます。

dartwebaudio.dart
main() {
  context = new AudioContext();
}

次に音素材を読み込みます。

音素材の対応フォーマットはWebブラウザごとに異なりますので注意が必要です。

主要Webブラウザごとの対応フォーマットについては以下のページが詳しいです。

Media formats supported by the HTML audio and video elements - HTML | MDN

今回は素直に(?)OGGで行きましょう。sample.oggを適当に作成しましょう。Audacityを使うと簡単に作成できます。

では、このsample.oggを読み込ませる処理を書きます。

dartwebaudio.dart
// main関数を省略
HttpRequest request = new HttpRequest()
  ..requestType = 'arraybuffer'
  ..open('GET', 'sample.ogg');

request.onLoad.listen((e) => _onLoad(request));

request.onError.listen((e) {
  throw 'File load error';
});

request.send();

HttpRequestrequestType'arraybuffer'とし、'GET''sample.ogg'を読み込みます。

データ読み込まれた時に_onLoad関数が呼ばれるように、HttpRequest.onLoad_onLoadlistenさせておきます。

最後に、request.send()で読み込みを開始させます。

_onLoad関数を用意します。

dartwebaudio.dart
_onLoad(HttpRequest request) {
  context
    .decodeAudioData(request.response)
    .then((AudioBuffer buffer) {
      sampleBuffer = buffer;

      InputElement playButton = document.query('#playbutton');
      playButton
        ..value = 'play'
        ..onClick.listen((e) => _play());
    });
}

AudioContext.decodeAudioData()HttpRequestで得たバッファデータを渡すことで、音源データをデコードさせます。

decodeAudioData()Futureのオブジェクトを返しますので、then()でデコード完了後の処理を渡します。

decodeAudioData()が返すFutureFuture<AudioBuffer>となっており、then()AudioBufferのオブジェクトを受け取ることができます。このバッファをsampleBufferに入れておきます。

このthen()が呼ばれた時点で音素材の読み込みとデコードが完了しているので、音再生用のボタンの文字を"loading..."から"play"に差し替えます。

そして、このボタンが押された時に呼ばれる処理を設定します。再生時に読んでいる_play()の処理は以下のようになります。

dartwebaudio.dart
_play() {
  AudioBufferSourceNode source = context.createBufferSource()
    ..buffer = sampleBuffer
    ..connectNode(context.destination)
    ..start(0);
}

AudioContext.createBufferSource()AudioBufferSourceNodeのオブジェクトを作成し、これのbufferプロパティに先ほど用意したsampleBufferを設定します。

AudioSourceNode.connectNode()AudioContext.destinationへノードを接続します。Web Audioにおけるノード接続の仕組みは音の様々な操作加工のために使用でき、ノードの接続を操作することによってそれを行うことができます。今回は、単にバッファの音源をそのまま再生するだけで良いので、AudioBufferSourceNodeを最終的な音出力のノードとなるAudioContext.destinationへ接続しています。

その後、AudioBufferSourceNode.start()を呼び、音の再生を行います。引数の0は、再生されるタイミングを指示するもので、今回は即時再生されてほしいので0を指定します。

以上で、音の再生が可能になります。

dartwebaudio.dartの全体像は以下のようになります。

dartwebaudio.dart
import 'dart:html';
import 'dart:web_audio';

AudioContext context;
AudioBuffer sampleBuffer;

main() {
  context = new AudioContext();

  HttpRequest request = new HttpRequest()
    ..responseType = 'arraybuffer'
    ..open('GET', 'sample.ogg');

  request.onLoad.listen((e) => _onLoad(request));

  request.onError.listen((e) {
    throw 'File load error';
  });

  request.send();
}

_onLoad(HttpRequest request) {
  context
    .decodeAudioData(request.response)
    .then((AudioBuffer buffer) {
      sampleBuffer = buffer;

      InputElement playButton = document.query('#playbutton');
      playButton
        ..value = 'play'
        ..onClick.listen((e) => _play());
  });
}

_play() {
  AudioBufferSourceNode source = context.createBufferSource()
    ..buffer = sampleBuffer
    ..connectNode(context.destination)
    ..start(0);
}

DEMO

DEMOとして以下のページを用意しました。今回のサンプルを動かすことができます。

Web Audio on Dart

動作環境

dart2jsにてJavaScriptへコンパイルされていますので、Web Audio APIに対応したブラウザであれば、動かすことが可能だという想定でしたが、FirefoxとSafariではエラーを確認しており、今のところChromeでしか動作を確認できていません。

型指定

Dartの型指定はオプショナルで、varとしてJavaScriptのように変数が型を持たない記述方法も可能ですが、今回はなるべく変数の型を指定する書き方にしました。これにより、Dartの型チェックの恩恵を受けることができます。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10