HTML5/jQuery metronome - performance problems
javascript, jquery, performance, setinterval
Solution
setInterval is not accurate. what you can try doing is something like:
var timestamp = (new Date()).getTime();
function run() {
var now = (new Date()).getTime();
if( now - timestamp >= 1000 ) {
console.log( 'tick' );
timestamp = now;
}
setTimeout(run, 10);
}
run();
This will (every hundredth of a second) compare the 'timestamp' with the current time to see if the diff is a second or more (deviation is 0.01 seconds) and if it is logs 'tick' and resets the current timestamp.
http://jsfiddle.net/rlemon/UqbwT/
This is the best approach to something that needs to be time accurate (imo).
Update: if you change the setTimeout time setting... you get less deviation. http://jsfiddle.net/rlemon/UqbwT/1/
Second update: After reviewing this post I thought there must be a more accurate way to use timers in javascript.. so with a bit of research I came acrossed this article. I do suggest you read it.
Problem
As mentioned in the title I'm trying to create a jQuery/JavaScript based metronome along with the HTML `<audio />` tag to play the sound. It works "okay", but it seems to me the `setInterval` method is not working accurately enough. I searched some threads here, but for I am new to both jQuery and JavaScript and I haven't found a working solution. Same for the "open new tab and setInterval stops or lags" - problem. I tried to prevent that with `stop(true,true)` but it didn't work as I expected. I want the metronome to run "in background" without changing tempo when opening a new tab and doing something there. Also I want an exact metronome for sure ;) Here's my testing environment located: http://nie-wieder.net/metronom/test.html At the moment, JS-Code and HTML-markup are all in the test.html source, so you can look there. Also, here's the concerned (as I think) js-code I use: ``` $(document).ready(function() { //vars var intervalReference = 0; var currentCount = 1; var countIncrement = .5; var smin = 10; var smax =240; var svalue = 120; //soundchkbox $(".sndchck").attr("disabled", true); //preload sound $.ajax({ url: "snd/tick.ogg", success: function() { $(".sndchck").removeAttr("disabled"); } }); // tick event var met = $("#bpm").slider({ value: 120, min: smin, max: smax, step: 1, change: function( event, ui ) { var delay = (1000*60/ui.value)/2 clearInterval(intervalReference); //seems to be the Problem for me intervalReference = setInterval(function(){ var $cur_sd = $('#sub_div_'+currentCount); $cur_sd .stop(true,true) .animate({opacity: 1},15, function() { //Play HTML5 Sound if($('#sound_check:checked').val()){ $('#tick') .stop(true,true) .trigger("play"); } $(this). stop(true,true). animate({opacity:0}); } ); currentCount += countIncrement; if(currentCount > 4.5) currentCount = 1 }, delay); createMusicTag(ui); } }); }); ``` Any help would be great, I'm out of ideas for now.