メニューを閉じる

テクノデジタルグループ

メニューを開く

2017.09.05

プログラミング

Web Audio APIを使って簡単なプレイヤーを作ってみる(1)

こんにちは、新卒のshiroです。
実は入社前にほとんどプログラミングをしたことがないため、記事を書きながら勉強している最中です。

では、本題です。
今回から数回に分けてweb audio apiを利用して、ブラウザ上で動く簡単なミュージックプレイヤー(上記画像)を作成します。
HTMLファイルからjsファイルを分離して開発を行うため、以下に各種ファイルが入ったzipを添付します。
playerフォルダを任意の場所に展開してください。
主にjsフォルダ内のplayer.jsを編集して作成していきます。
なお、今回使用しているアイコンは素材サイト様からお借りしており、再配布はできないため入っていません。下記URLからのダウンロードをお願いします。
また、音声ファイルも同様の理由で配布できませんので、こちらも各自用意をお願いします。

各種ファイル:player.zip
素材サイト様:ICOON MONO

なお、今回はfirefox55.0.2での動作を前提としています。

具体的に以下の機能を実装します。

再生/停止
音量の変更
再生中音楽のタイトル表示
再生時間の表示
ファイルの取り込み
一時停止/再開
リピート

再生/停止

今回はその中の「再生/停止」と「音量の変更」の実装を行いたいと思います。

player.jsの中に既に変数が記載されていますので、listの[]内に”音声ファイルの相対パス(拡張子まで)”を、audioNameの[]に”音声ファイル名”を記述しておいてください。
これらは後に「フォルダを指定したファイル取り込み」を作成する際、自動で入力されるようにします。

では、web audio apiの要であるaudioContextやデコードの処理を作成します。
古いwebkit系ブラウザでは、プレフィックスが必要です。

// AudioContextの作成
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
context.createGain = context.createGain || context.createGainNode;

// Bufferへのデコード
var getAudioBuffer = function(url,fn) {
  let request = new XMLHttpRequest();
  request.responseType = "arraybuffer";
  request.onreadystatechange = function() {
    // XMLHttpRequestの処理が完了しているか
    if (request.readyState === 4) {
      // レスポンスのステータスを確認
      // 200はリクエストに成功
      if (request.status === 0 || request.status === 200) {
        context.decodeAudioData(request.response, function(buffer) {
          fn(buffer);
        });
      }
    }
  };
  req.open("GET", url, true);
  req.send("");
};

XMLHttpRequest.readyStateはMDN web docsによると

Value State Description
0 UNSENT Client has been created. open() not called yet.
1 OPENED open() has been called.
2 HEADERS_RECEIVED send() has been called, and headers and status are available.
3 LOADING Downloading; responseText holds partial data.
4 DONE The operation is complete.

となっており、ロードが完了している4を条件としています。

また、XMLHttpRequest.statusに関して、
・正常なレスポンスが返ってきている200
に加えて、
・file://等を読み込んだ時に返ってくる0
である場合、今回は正常と判断しています。

次に実際の再生処理の実装です。

var sound = function(buffer) {
  if (volumeControl == null) {
    volumeControl = context.createGain();
  }
  let source = context.createBufferSource();
  volumeControl.connect(context.destination);
  source.buffer = buffer;
  source.connect(volumeControl);
  // 外部の関数からはsoundFileで処理を行うことにする
  soundFile = source;
  playing = true;
  changeVolume();
  // 音の再生
  source.start();
}

既にvolumeControlが出てきていますが、字面の通り音量関係で使用しています。
createGainが音量のノードを生成する処理になります。
実際の音量変更は後ほど別に処理を追加します。

createBufferSourceは再生に必要なsourceを作成しています。

source.connect(volumeControl)でvolumeControlをsourceに接続しています。
こうすることで、volumeContorol.gain.valueの値を変更した際に音量を変更することができます。

source.start()で音声の再生を開始します。
ただし、ワンショットのように短い音声ではなく4~5分ある曲のような場合、実際の再生まで数秒の遅延が生じます。
sourceはグローバルではないので、最終的にsoundFileに入れています。

次いで、プレイヤーの設定をしていきます。

// プレイヤーの処理
// 再生
var player_play = function() {
  let bgm = list[0];
  getAudioBuffer(bgm,function(buffer) {
    sound(buffer);
  });
}
// 停止
var player_stop = function() {
  if (soundFile != null) {
    soundFile.stop(0);
  }
}

getAudioBufferの第1引数に音声ファイルのパスが渡されることによって、最初に作ったデコードを通して最終的にsoundを呼び出す形になります。
止める際は、soundFile.stop()と簡単です。

これで再生と停止ができます。

音量の変更

// 音量の変更
var changeVolume = function() {
  if (volumeControl != null) {
    volumeControl.gain.value = volume.value;
  }
}

これだけです。

先ほど、sound()内にvolumeControlを作成しました。
これにのgain.valueにrangeの値を代入しています。
HTMLを見てもらうとわかりますが、onchangeの度にこの関数を呼び出しており、これにより音量の変更を行っています。

ここで注意するべき点は、gain.valueは通常0から1の値を取るということです。
「通常」と書いているのは、0~1の外の値を取ってもエラーになることはないためです。
ただ実際どのように変わるのかは、-1にしてみてもよくわかりませんでした。
今回はただのボリュームコントローラーとして使用しているので、0から1の値を取るようにしています。

volumeControlが生成されていない状態で値を代入しようとすれば、当然エラーが返ってくるため、if文で囲っています。

また、再生開始時に音量が設定されるようsound()内でchangeVolume()を呼んでいます。
ここで直接値を指定してもいいのですが、音量の変更時に呼び出す必要があり、やることは結局同じなので、こちらに集約しています。

今回は以上となります。
次回は「再生中音楽のタイトル表示」と「再生時間の表示」を作成していこうと思います。

第2回はこちら
第3回はこちら

EOF.


【記事への感想募集中!】

記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!
  • こんな記事が読んでみたい、こんなことが知りたい、調べてほしい!という意見も募集中!
  • いただいた感想は今後の記事に活かしたいと思います!

感想フォームはこちら


【テクノデジタルではエンジニア/デザイナーを積極採用中です!】

下記項目に1つでも当てはまる方は是非、詳細ページへ!
  • 自分でアプリを作ってみたい
  • ITで世の中にワクワクを生み出したい
  • 使いやすさ、デザインにこだわったWebサイトを開発したい

採用情報の詳細はこちら


Qangaroo(カンガルー)

  • 徹底した見やすさと優れた操作性で、テストの「見える化」を実現。
  • テストの進捗が見える。開発がスマートに進む。
  • クラウド型テスト管理ツール『Qangaroo(カンガルー)』

【テクノデジタルのインフラサービス】

当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。

https://www.tcdigital.jp/infrastructure/

最近の記事