ティラノスクリプトで音声のループ再生をシームレスにやりたい!!!
ティラノスクリプトの[playbgm]タグおよび[playse]タグでのオーディオ再生ではループ再生ができるわけですが、これはhtmlの限界的な意味で完全なシームレス再生(継ぎ目のない再生)ができません。
せっかくちまちまAudacityでループ再生対応のoggファイルを作っても、そのままではループのタイミングで謎の空白が入ってしまいます。
より完璧でより幸福なシームレス再生をやりたいならWeb Audio APIを使えばいいんですが、こっちはこっちで闇が深いしティラノスクリプトの標準機能からも外れてしまいます。
ということで、標準の[playbgm]、[playse]を使いつつ、よりシームレスなループ再生を目指してみた結果がこちらです。
code:kag.tag_audio.js
tyrano.plugin.kag.tag.playbgm = {
... 中略 ...
play: function (pm) {
... 中略 ...
if (pm.loop == "true") {
audio_obj.loop = true;
/* ここから削除
audio_obj.onended = function () {
this.play()
}
ここまで削除 */
//ここから追加
var update = function(){
if(audio_obj.currentTime >= audio_obj.duration - 0.3){
audio_obj.currentTime = 0
}
requestAnimationFrame(update)
}
update()
//ここまで追加
} else if (pm.loop == "smooth") {
... 中略 ...
//削除
//audio_obj.play();
//ここから追加
$(audio_obj).on("canplaythrough", function(){
if(audio_obj.currentTime == 0){
audio_obj.play();
}
})
//ここまで追加
if (pm.fadein == "true") {
... 後略 ...
解説
追加しているupdate関数でループ時の処理を行っています。
audio_obj.currentTimeが現在の再生時間で、audio_obj.durationが音声ファイルの総再生時間です。
if(audio_obj.currentTime >= audio_obj.duration - 0.3)とすることで、現在の再生時間が総再生時間-0.3秒を超えたら、現在の再生時間を0に戻す(=ループさせる)という処理になります。
0.3秒の理由は後述するのでまずはその先の処理の説明。
requestAnimationFrame()というのは、本来は画面の描画処理に使う関数です。
これは、ブラウザが次のフレームを描画する準備ができたタイミングで実行されるもので、PCの性能とかにもよりますが、おおよそ60fpsで動きます。
オーディオ再生のタイミング取得をするなら、timeupdateというイベントハンドラがあるんですが、これは1秒間に数回程度の頻度でしか呼び出されません。
それならrequestAnimationFrame()の方がましかな…とおもって今回はrequestAnimationFrame()の方を使っています。
で、0.3秒の理由。
およそ60fpsで実行されるrequestAnimationFrame()ですが、60fpsごとにいちいち処理を呼び出して実行しているので、その都度処理の時間がかかります。
なので、処理にかかる時間を見越して0.3秒をバッファとして指定しています。
正直おま環要素がモリモリなので、他の環境でもちゃんとシームレス再生されているかはわからない…
ひとまずこれでループ時の継ぎ目が多少ましになったかな~~~~
なってほしいな~~~~~