2024.11.14
いまさらNode.jsを知ろう~環境構築も~
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()を呼んでいます。
ここで直接値を指定してもいいのですが、音量の変更時に呼び出す必要があり、やることは結局同じなので、こちらに集約しています。
今回は以上となります。
次回は「再生中音楽のタイトル表示」と「再生時間の表示」を作成していこうと思います。
EOF.
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
タグ検索