better looping

thx @LoveEevee
This commit is contained in:
Bui 2018-08-22 23:51:16 +01:00
parent d8be781774
commit 322dd9f7cb
5 changed files with 98 additions and 225 deletions

View File

@ -28,7 +28,6 @@
<script type='application/javascript' src='/src/js/lib/jquery.js'></script> <script type='application/javascript' src='/src/js/lib/jquery.js'></script>
<script type='application/javascript' src='/src/js/lib/jquery-ui.js'></script> <script type='application/javascript' src='/src/js/lib/jquery-ui.js'></script>
<script type='application/javascript' src='/src/js/lib/fontdetect.min.js'></script> <script type='application/javascript' src='/src/js/lib/fontdetect.min.js'></script>
<script type='application/javascript' src='/src/js/lib/SeamlessLoop.js'></script>
<script type='application/javascript' src='/src/js/assets.js'></script> <script type='application/javascript' src='/src/js/assets.js'></script>
<script type='application/javascript' src='/src/js/loader.js'></script> <script type='application/javascript' src='/src/js/loader.js'></script>
@ -44,6 +43,7 @@
<script type='application/javascript' src='/src/js/circle.js'></script> <script type='application/javascript' src='/src/js/circle.js'></script>
<script type='application/javascript' src='/src/js/main.js'></script> <script type='application/javascript' src='/src/js/main.js'></script>
<script type='application/javascript' src='/src/js/view.js'></script> <script type='application/javascript' src='/src/js/view.js'></script>
<script type='application/javascript' src='/src/js/bufferedloop.js'></script>
</head> </head>
<body> <body>

83
src/js/bufferedloop.js Normal file
View File

@ -0,0 +1,83 @@
// thx to @LoveEevee for this - https://github.com/LoveEevee
class BufferedLoop{
constructor(bgm1,bgm2){
this.context=new AudioContext()
this.buffers=[]
this.sources=new Set()
this.bufferedTime=0
this.iteration=0
this.bgm1=bgm1
this.bgm2=bgm2
this.loadSound(bgm1.url,0)
this.loadSound(bgm2.url,1)
}
loadSound(url,number){
var self=this
var request=new XMLHttpRequest()
request.open("GET",url)
request.responseType="arraybuffer"
request.onload=function(){
self.context.decodeAudioData(request.response,function(buffer){
self.buffers[number]=buffer
self.setLoaded()
})
}
request.send()
}
setLoaded(){
if(this.buffers[0]&&this.buffers[1]){
this.loaded=true
if(this.loadCallback){
this.loadCallback()
delete this.loadCallback
}
}
}
playSound(buffer,time,duration){
var self=this
var source=this.context.createBufferSource()
source.buffer=buffer
source.connect(this.context.destination)
source.start(time)
this.bufferedTime=time+duration
this.sources.add(source)
console.log(this.sources)
setTimeout(function(){
self.sources.delete(source)
},duration*1000)
}
addLoop(){
if(this.context.currentTime>this.bufferedTime-1){
this.playSound(
this.buffers[1],
this.start+this.bgm1.duration+this.bgm2.duration*this.iteration,
this.bgm2.duration
)
this.iteration++
}
}
play(){
var self=this
if(!this.loaded){
this.loadCallback=this.play
return
}
this.start=this.context.currentTime+0.1
this.playSound(
this.buffers[0],
this.start,
this.bgm1.duration
)
self.addLoop()
self.interval=setInterval(function(){
self.addLoop()
},100)
}
pause(){
clearInterval(this.interval)
this.sources.forEach(function(source){
source.stop(0)
})
}
}

View File

@ -1,201 +0,0 @@
/**
* SeamlessLoop.js 2.0 - Reproduces seamless loops on HTML5/Javascript
* https://github.com/Hivenfour/SeamlessLoop
*
* Copyright (c) 2012 Main Software,
* Written by Darío Tejedor Rico. Contact mail: hivenfour@gmail.com
* The source code is freely distributable under the terms of LGPL license.
* License details at http://www.gnu.org/licenses/lgpl-3.0.txt
*
* USAGE:
* - Create the Seamlessloop object
* var loop = new SeamlessLoop();
*
* - Add as many sounds as you will use, providing duration in miliseconds
* (sounds must be pre-loaded if you want to update the loop without gaps)
* loop.addUri(uri, length, "sound1");
* loop.addUri(uri, length, "sound2");
* ...
*
* - Establish your callback function that will be called when all sounds are pre-loaded
* loop.callback(soundsLoaded);
*
* - Start reproducing the seamless loop:
* function soundsLoaded() {
* var n = 1;
* loop.start("sound" + n);
* };
*
* - Update the looping sound, you can do this
* synchronously (waiting the loop to finish)
* or asynchronously (change sound immediately):
* n++;
* loop.update("sound" + n, false);
*
* - Modify the seamless loop volume:
* loop.volume(0.5);
* loop.volume(loop.volume() + 0.1);
*
* - Stop the seamless loop:
* loop.stop();
*/
function SeamlessLoop() {
this.is = {
ff: Boolean(!(window.mozInnerScreenX == null) && /firefox/.test( navigator.userAgent.toLowerCase() )),
ie: Boolean(document.all && !window.opera),
opera: Boolean(window.opera),
chrome: Boolean(window.chrome),
safari: Boolean(!window.chrome && /safari/.test( navigator.userAgent.toLowerCase() ) && window.getComputedStyle && !window.globalStorage && !window.opera)
};
console.debug("ff: " + this.is.ff);
console.debug("ie: " + this.is.ie);
console.debug("opera: " + this.is.opera);
console.debug("chrome: " + this.is.chrome);
console.debug("safari: " + this.is.safari);
this._total = 0;
this._load = 0;
this.cb_loaded;
this.cb_loaded_flag = new Boolean();
this.timeout;
this.playDelay = -30;
this.stopDelay = 30;
if(this.is.chrome) this.playDelay = -25;
if(this.is.chrome) this.stopDelay = 25;
if(this.is.ff) this.playDelay = -25;
if(this.is.ff) this.stopDelay = 85;
if(this.is.opera) this.playDelay = 5;
if(this.is.opera) this.stopDelay = 0;
console.debug(this.playDelay + ", " + this.stopDelay);
this.next = 1;
this.audios = new Array();
this.actual = new Array();
this.dropOld = new Boolean();
this.old;
this._volume = 1;
var t = this;
this._eventCanplaythrough = function(audBool) {
if(audBool == false) {
audBool = true;
t._load++;
if(t._load == t._total) {
t.loaded = true;
if(t.cb_loaded_flag == true) {
t.cb_loaded();
t.cb_loaded_flag = false;
}
}
}
};
this._eventPlaying = function(audMute) {
setTimeout(function() {
audMute.pause();
try {
audMute.currentTime = 0;
} catch (e){console.debug(e.message);};
}, t.stopDelay);
if(t.dropOld == true) {
setTimeout(function() {
if(t.old.paused == false) {
t.old.pause();
try {
t.old.currentTime = 0;
} catch (e){console.debug(e.message);};
}
}, t.stopDelay);
t.dropOld = false;
}
};
this._eventEnded = function(aud) {
aud.volume = this._volume;
};
this.doLoop = function() {
var key = (this.next == 1 ? "_1" : "_2");
var antikey = (this.next == 1 ? "_2" : "_1");
var t = this;
this.timeout = setTimeout(function() {t.doLoop();}, this.actual._length + this.playDelay);
if(this.is.opera) this.actual[antikey].pause();
this.actual[key].play();
this.next *= -1;
};
this.isLoaded = function() {
return Boolean(this._load == this._total);
};
}
SeamlessLoop.prototype.start = function(id) {
if(id != "") {
this.actual = this.audios[id];
}
this.doLoop();
};
SeamlessLoop.prototype.volume = function(vol) {
if(typeof vol != "undefined") {
this.actual._1.volume = vol;
this.actual._2.volume = vol;
this._volume = vol;
}
return vol;
};
SeamlessLoop.prototype.stop = function() {
clearTimeout(this.timeout);
this.actual._1.currentTime = 0;
this.actual._1.pause();
this.actual._2.currentTime = 0;
this.actual._2.pause();
};
SeamlessLoop.prototype.callback = function(cb_loaded) {
this.cb_loaded = cb_loaded;
if(this.isLoaded() == true) cb_loaded();
else this.cb_loaded_flag = true;
};
SeamlessLoop.prototype.update = function(id, sync) {
//var key = (this.next == 1 ? "_1" : "_2");
var antikey = (this.next == 1 ? "_2" : "_1");
this.old = this.actual[antikey];
this.actual = this.audios[id];
if(sync == false) {
if(this.old.paused == false) {
this.dropOld = true;
if(this.is.opera) this.old.pause();
}
clearTimeout(this.timeout);
this.doLoop();
}
};
SeamlessLoop.prototype.addUri = function(uri, length, id) {
this.audios[id] = new Array();
this.audios[id]._length = length;
var t = this;
this.audios[id]._1_isLoaded = new Boolean();
this.audios[id]._2_isLoaded = new Boolean();
this.audios[id]._1 = new Audio(uri);
this.audios[id]._2 = new Audio(uri);
this._total++;
this.audios[id]._1.addEventListener("canplaythrough", function() {t._eventCanplaythrough(t.audios[id]._1_isLoaded);});
this.audios[id]._2.addEventListener("canplaythrough", function() {t._eventCanplaythrough(t.audios[id]._2_isLoaded);});
this.audios[id]._1.addEventListener("playing", function() {t._eventPlaying(t.audios[id]._2);});
this.audios[id]._2.addEventListener("playing", function() {t._eventPlaying(t.audios[id]._1);});
this.audios[id]._1.addEventListener("ended", function() {t._eventEnded(t.audios[id]._1);});
this.audios[id]._2.addEventListener("ended", function() {t._eventEnded(t.audios[id]._2);});
this.audios[id]._1.load();
this.audios[id]._2.load();
this.audios[id]._1.volume = this._volume;
this.audios[id]._2.volume = this._volume;
};

View File

@ -82,13 +82,13 @@ function Scoresheet(controller, score){
$("#song-select").click(function(){ $("#song-select").click(function(){
assets.sounds["don"].play(); assets.sounds["don"].play();
bgmloop2.stop(); bgm.stop();
controller.songSelection(); controller.songSelection();
}); });
$("#replay").click(function(){ $("#replay").click(function(){
assets.sounds["don"].play(); assets.sounds["don"].play();
bgmloop2.stop(); bgm.stop();
controller.restartSong(); controller.restartSong();
}); });
@ -98,14 +98,11 @@ function Scoresheet(controller, score){
assets.sounds["results"].play(); assets.sounds["results"].play();
console.log('init scoresheet bgm'); bgm = new BufferedLoop(
bgmloop2 = new SeamlessLoop(); {url: '/assets/audio/bgm_result.ogg', duration: 0.847},
bgmloop2.addUri('/assets/audio/bgm_result.ogg', 870, "bgm_result"); {url: '/assets/audio/bgm_result_loop.ogg', duration: 16.842}
bgmloop2.addUri('/assets/audio/bgm_result_loop.ogg', 16860, "bgm_result_loop"); );
bgmloop2.callback(function(){ bgm.play();
bgmloop2.start('bgm_result');
bgmloop2.update('bgm_result_loop');
});

View File

@ -25,9 +25,8 @@ function SongSelect(){
_selectedSong.title = $(this).parent().closest('.song').find('.song-title').html(); _selectedSong.title = $(this).parent().closest('.song').find('.song-title').html();
_selectedSong.folder = songID+" "+_selectedSong.title; _selectedSong.folder = songID+" "+_selectedSong.title;
bgmloop.stop(); bgm.pause();
new loadSong(_selectedSong); new loadSong(_selectedSong);
}); });
$(".song").hover(function(){ $(".song").hover(function(){
@ -89,14 +88,11 @@ function SongSelect(){
} }
this.createCode = function(){ this.createCode = function(){
bgm = new BufferedLoop(
bgmloop = new SeamlessLoop(); {url: '/assets/audio/bgm_songsel.ogg', duration: 1.442},
bgmloop.addUri('/assets/audio/bgm_songsel.ogg', 1450, "bgm_songsel"); {url: '/assets/audio/bgm_songsel_loop.ogg', duration: 2.064}
bgmloop.addUri('/assets/audio/bgm_songsel_loop.ogg', 2085, "bgm_songsel_loop"); );
bgmloop.callback(function(){ bgm.play();
bgmloop.start('bgm_songsel');
bgmloop.update('bgm_songsel_loop')
});
setTimeout(function(){ setTimeout(function(){
assets.sounds["song-select"].play(); assets.sounds["song-select"].play();
@ -109,8 +105,6 @@ function SongSelect(){
var songID = titleSplit[0]; var songID = titleSplit[0];
var songTitle = songDir.substr(songID.length+1, songDir.length-(songID.length+1)); var songTitle = songDir.substr(songID.length+1, songDir.length-(songID.length+1));
_code += "<div id='song-"+songID+"' class='song'><div class='song-title stroke-sub' alt='"+songTitle+"'>"+songTitle+'</div>'; _code += "<div id='song-"+songID+"' class='song'><div class='song-title stroke-sub' alt='"+songTitle+"'>"+songTitle+'</div>';
_code += "<ul class='difficulties'>"; _code += "<ul class='difficulties'>";