I wanna make a beat machine to play sounds at a given time. I need to pass in a bpm number. My first attempt was just to use a setInterval function to get a constant beat, but Im not sure if thats the way to go.
let beat = (bpm) => {
setInterval(()=> {
// Run update beat machine
}, (60 * 1000) / bpm)
}
I didnt find anything on the web. I appreciate articles as well.
thanks
No, that's not what you want. setInterval is not precise.
The Web Audio API has an AudioBufferSourceNode which keeps the sample in memory. It can be scheduled to start at a certain time.
bufferNode.start(0.5, startOffset);
In this example, we start playing 0.5 seconds from the offset.
Related
I'm making a simple game which generates random numbers and user has to enter a value, if users value matches the random value generated, the user wins basically this is a beginner project. I want to make a small counter so that user has a limited time to put in the value and I want that limited time to show on the screen in a label. Lets say that you have to put the value under 30 secs and the timer will count from 1 to 30 every second. The counting from 1 to 30 will update in the label every second. This is the logic I'm trying to work on right now and I can't figure out any other way... If I've done some mistake in code please comment or if you have much more simpler way please post it down below. (pls dont vote down im at threat of account suspension)
Heres the part of my timer code:
if(timer <= 30)
{
for(var i = 0;i >= 30;i++)
{
setInterval(null,1000);
timer++;
document.getElementById("counter").innerHTML = timer+" seconds wasted";
}
alert("Time is over, you lost by "+s);
}
You could create a recursive function.
Say var countDown function(){ time = time--;
setTimeout(countDown, 1000);}
Then you need a variable time that is accessible for the countDown function.
var time = 30;
In the countDown function you could create an updateTimeElement.
Try it out.
The setInterval function has 2 parameters, a callback (an anomynous function in javascript thats triggered) and the milliseconds between each trigger of the interval.
What you are doing in your script is making an interval with nothing to do each second (this runs indefinately), then increment the timer integer and updating the DOM. However, this all executes within seconds.
I'd suggest (before you use a function) you look at the documentation to see how you can improve your script to work as you intent to ;-) Here are a few links that might help you get started:
http://www.w3schools.com/js/js_timing.asp
https://www.sitepoint.com/build-javascript-countdown-timer-no-dependencies/
I wont be doing the work for you, since this is a good exercise for a beginner programmer ;-)
If you can't figure it out, leave a comment below this answer and I'll get back to you to help you if you need further assistance.
Why this is important to me
I have a site where I need to have a countdown timer running to show people how much time they have left to complete an action.
This timer will run for days and probably just use MomentJS to say something like "in 4 days" from MomentJS's to() function.
However when we have an hour left to go I'm going to switch over to a countdown by minutes timer, eventually when the minutes get low enough, I'm going to have a seconds timer involved. When we're getting down to the very last few minutes I'm going to even display milliseconds.
The problem
Pretty much there are two main techniques to animate the countdown timer.
setInterval()
requestAnimationFrame()
Well, right away I noticed that the requestAnimationFrame() method was much more smooth to the eye, it works great - especially when I'm displaying milliseconds. However it wasn't long when I noticed that my poor computer started to get a little warm. All of this "animation" is causing quite a load on my CPU. I tried to use CPU monitors, and looked around at ways to see how much load this puts on my CPU but, overall I can't really find a tool that gives me a clear graph of what kind of CPU load my little countdown timer is using.
So, I decided to find a way to limit the FPS and see if that would reduce my problem. And yes, it does. If you use setTimeout() in tandem with requestAnimationFrame() you can set a waiting time before you call your next function.
Which raises the question, if you're using setTimeout() - Why don't you just use setInterval() and forget about the extra optimization that requestAnimationFrame() gives you?
I did some looking around and found another method which simply checks to see if the right amount of interval time has passed since the last time requestAnimationFrame() called your function. I made some optimizations to how this code works and ended up with one of the two functions I'm trying to measure below.
In the end, I'd really like to have a more clear way to measure this - because the activity monitor on my mac is hardly reliable tool to give an accurate reading - and I can't find a way to measure just the code I'm running.
Chrome has some more tools, the profiler, and the timeline - which are both very helpful, but they don't give me the metric I'm looking for - CPU load.
The Code:
Here are four code snippets, which do exactly the same thing - all of them use:
MomentJS
CountdownJS
jQuery
The code is 100% identical, the only difference is how I am limiting the FPS of the animation.
I'd like to find a way to measure (as precisely as possible) the difference between the four functions in how much CPU load they are taking. And then I'd like to then change the FPS around to see if I can find an acceptable load for my application and then I can find the sweet spot - the right amount of FPS, during the different timer stages.
Technique 1 - setTimeout()
var now = moment(); // new Date().getTime();
var then = moment().add(60, 'seconds'); // new Date(now + 60 * 1000);
$(".now").text(moment(now).format('h:mm:ss a'));
$(".then").text(moment(then).format('h:mm:ss a'));
$(".duration").text(moment(now).to(then));
(function timerLoop() {
setTimeout(function(){
$(".difference").text(moment().to(then));
$(".countdown").text(countdown(then, null, countdown.YEARS | countdown.MONTHS | countdown.DAYS | countdown.HOURS | countdown.MINUTES | countdown.SECONDS | countdown.MILLISECONDS).toString());
requestAnimationFrame(timerLoop);
}, 1000/30);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdn.rawgit.com/mckamey/countdownjs/master/countdown.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" type="text/javascript"></script>
<div>
The time is now: <span class="now"></span>, a timer will go off <span class="duration"></span> at <span class="then"></span>
</div>
<div>The timer is set to go off <span class="difference"></span></div>
<div class="countdown"></div>
Technique 2 - Delta between intervals
var now = moment(); // new Date().getTime();
var then = moment().add(60, 'seconds'); // new Date(now + 60 * 1000);
$(".now").text(moment(now).format('h:mm:ss a'));
$(".then").text(moment(then).format('h:mm:ss a'));
$(".duration").text(moment(now).to(then));
var fps = 30;
var interval = 1000/fps;
var performanceTime = performance.now();
var performanceDelta;
(function updateCountdown(time) {
performanceDelta = time - performanceTime;
if (performanceDelta > interval) {
performanceTime = time - (performanceDelta % interval);
$(".difference").text(moment().to(then));
$(".countdown").text(countdown(then, null, countdown.YEARS | countdown.MONTHS | countdown.DAYS | countdown.HOURS | countdown.MINUTES | countdown.SECONDS | countdown.MILLISECONDS).toString());
}
requestAnimationFrame(updateCountdown);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdn.rawgit.com/mckamey/countdownjs/master/countdown.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" type="text/javascript"></script>
<div>
The time is now: <span class="now"></span>, a timer will go off <span class="duration"></span> at <span class="then"></span>
</div>
<div>The timer is set to go off <span class="difference"></span></div>
<div class="countdown"></div>
Technique 3 - setInterval()
var now = moment(); // new Date().getTime();
var then = moment().add(60, 'seconds'); // new Date(now + 60 * 1000);
$(".now").text(moment(now).format('h:mm:ss a'));
$(".then").text(moment(then).format('h:mm:ss a'));
$(".duration").text(moment(now).to(then));
var fps = 30;
var interval = 1000/fps;
setInterval(function updateCountdown() {
$(".difference").text(moment().to(then));
$(".countdown").text(countdown(then, null, countdown.YEARS | countdown.MONTHS | countdown.DAYS | countdown.HOURS | countdown.MINUTES | countdown.SECONDS | countdown.MILLISECONDS).toString());
}, interval);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdn.rawgit.com/mckamey/countdownjs/master/countdown.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" type="text/javascript"></script>
<div>
The time is now: <span class="now"></span>, a timer will go off <span class="duration"></span> at <span class="then"></span>
</div>
<div>The timer is set to go off <span class="difference"></span></div>
<div class="countdown"></div>
It would also be interesting to see a completely un-throttled version like so:
Technique 4 - No throttle
var now = moment(); // new Date().getTime();
var then = moment().add(60, 'seconds'); // new Date(now + 60 * 1000);
$(".now").text(moment(now).format('h:mm:ss a'));
$(".then").text(moment(then).format('h:mm:ss a'));
$(".duration").text(moment(now).to(then));
(function timerLoop() {
$(".difference").text(moment().to(then));
$(".countdown").text(countdown(then, null, countdown.YEARS | countdown.MONTHS | countdown.DAYS | countdown.HOURS | countdown.MINUTES | countdown.SECONDS | countdown.MILLISECONDS).toString());
requestAnimationFrame(timerLoop);
})();
// CountdownJS: http://countdownjs.org/
// MomentJS: http://momentjs.com/
// jQuery: https://jquery.com/
// Rawgit: http://rawgit.com/
// Light reading about the requestAnimationFrame pattern:
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
// https://css-tricks.com/using-requestanimationframe/
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdn.rawgit.com/mckamey/countdownjs/master/countdown.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" type="text/javascript"></script>
<div>
The time is now: <span class="now"></span>, a timer will go off <span class="duration"></span> at <span class="then"></span>
</div>
<div>The timer is set to go off <span class="difference"></span></div>
<div class="countdown"></div>
Simply Put: How does one measure the CPU load difference between four similar javascript functions?
Does anyone already know which of these is going to be more performant? (I know that is not really a word)
Answering my own question:
The Short Answer:
Worst Performance
Clearly setInterval() is the worst solution. Because setInterval() still runs while you are not on the tab, wasting CPU and therefor battery life.
Best Animation (Microseconds)
Clearly the Delta Interval Math calculation method is the most smooth and most accurate way to calculate interval time. When you combined this algorithm with the accuracy of calculating frames times using performance.now() you can achieve results accurate to the microsecond with your animation frames.
(and yes, even requestAnimationFrame() uses performance.now() time as the first argument it passes to the callback function).
And yes folks, I really mean microseconds. That's 1s/1000ms/1000µs.
Go ahead, test it now. Open up your console and type: performance.now() And you'll get a number that looks like 2132438.165 - those are milliseconds since the browser rendered the first frame.
(Which is extra cool because µ is a greek character +10 nerd points)
Best CPU Performance (Milliseconds)
Combine requestAnimationFrame() (which allows your animation to sleep when you switch tabs) with setTimeout() which can throttle the FPS of your animation to any desired millisecond interval.
Keep in mind however, that the difference between this method and the Delta Interval Math method is very VERY slightly different. I don't even have a way to quantify how small of a difference it is. From what I can tell it might be one fourth to one eighth more efficient. But you lose a lot of smoothness for it. your choice.
The Long Answer:
I'm still looking forward to a better way to do this, perhaps in a way that allows me to compare data between different functions.
Until then, I was able to generate these images using Google's Javascript CPU Profiler
Listing in the order in which I believe they are performant, but with titles that match the original question:
Technique 3 - setInterval()
Technique 1 - setTimeout()
Technique 2 - Delta between intervals
Technique 4 - No throttle
Visual Analysis
Well, from the looks of it, I'd rank the different functions in this order of performance:
setInterval() function.
setTimeout() wrapping therequestAnimationFrame()` call.
Delta Interval Math inside the recursive function called by requestAnimationFrame()
No FPS Throttle simply looping with requestAnimationFrame()
Conclusion: [Edited: 06/25/2016]
The setInterval() function is better than any requestAnimationFrame() pattern that I have found at least for CPU usage reasons ONLY WHILE YOU ARE ON THE TAB.
So if CPU cost or longer battery life are the larger concern for your application, than go with requestAnimationFrame() and throttle the FPS using either:
The setTimeout() method which seams to be a little less work for the CPU (best of both worlds) - but admittedly less smooth than the method below.
or
The Delta Interval Math which seams to be a little bit more smooth of an animation (And using the technique outlines in this Question/Answer with the time from performance.now() and the time reported from the requestAnimationFrame() (which is just the current performance.now() provided in the first argument to the callback function). Because we're using the most accurate algorithm I've seen to calculate the animation frame (You're actually calculating down to the millionth of a second, or a microsecond 1s/1000ms/1000µs). There is not a HUGE difference in the CPU load from this technique and setTimeout() - but there IS a difference (reference the attached images)
Why is requestAnimationFrame() is the bomb-digity?" - Because: when you're not on that tab, it gets turned off by the browser, so your animations are "waiting" for you to come back. AND using performance.now() you're getting microsecond (µs) accuracy on your animation.
It is said that requestAnimationFrame() is an "optimized" way to make sure your animation works along side other browser redrawing so that your animation "fits" with what the browser is doing, it also comes at a 60FPS callback cost.
Steps I took to generate these photos:
Created individual blank HTML files with nothing but absolutely what I needed for the tests.
Rebooted my computer, opened only my chrome browser to an about:blank tab.
Opened each "test benchmark" HTML file I previously created individually and one at a time.
At precisely 50 seconds into the countdown timer I clicked start on Google's Javascript CPU Profiler and precisely 10 seconds later I clicked stop (I used a special clicking macro built into my gamer-mouse's special driver software that works pretty well - Once I click the button it clicks start and 10 seconds later another click on stop - good enough for these photos)
Saved the profile to my computer
Loaded each of the profiles into the profiler tool on the about:blank tab.
Resized the window to frame the data well
Screenshot [shift] + [cmd] + [4] and then you press space on the keyboard to frame the screenshot exactly around the window.
Unresolved Problem:
I still don't have a way to see what the CPU % usage is. This graph leave me wanting for something more detailed. The other Google Javascript CPU Profiler screens are also a little vague in this sense. Maybe I just don't know how to use the tool.
If anyone knows of a better benchmark for testing this, please send an answer over and I'll review it. I hope it's better than this mess. And thanks in advance.
The main issue here is having a way to quantify hard data from one CPU profile to another and compare them. This is what I'm missing the most.
I am developing a stopwatch application using Javascript/jQuery. The problem is that the milliseconds value is out of sync with REAL milliseconds. I am using function setInterval() with the interval of 1 millisecond, still it is causing this problem.
jsFiddle: http://jsfiddle.net/FLv3s/
Please help!
Use setInterval to trigger updates, but use the system time (via new Date()) for the actual time calculations.
To be honest, I tried nearly the same thing as you do now (Creating an accurate Metronome in Javascript only) - to make a long story short: To be absolutely accurate in terms of milliseconds (or lower) is sadly not (yet) possible with javascript only.
For more insight i recommend this question: Does JavaScript provide a high resolution timer?
or to be more precise this blog article: http://ejohn.org/blog/how-javascript-timers-work/
Best regards,
Dominik
Program execution in any language, not just JavaScript, is not realtime. It will take a tiny amount of time to actually run the code to increment your counter and update the view, and that throws the "timing" off.
Additionally, many browsers have a "minimum timeout" length, which varies between 4 and about 16 (the latter being the computer's own clock timer), which will really mess with your code.
Instead, you should use delta timing.
var startTime = new Date().getTime();
setInterval(function() {
var elapsed = new Date().getTime()-startTime;
// update view according to elapsed time
},25);
If you're worried about it looking choppy, consider using requestAnimationFrame instead, to update the timer exactly once per frame - this has the added benefit of not updating when the user switches tabs (but it will still be timing them) because if the tab is not active then there's no need to redraw stuff.
You can use the new performance object to get a more accurate time. Combine this with requestAnimationFrame instead of setInterval:
var startTime = performance.now(),
currentTime,
isRunning = true;
loop();
function loop(timeElapsed) {
currentTime = performance.now();
if (isRunning) requestAnimationFrame(loop);
}
Just subtract startTime from currentTime.
I left timeElapsed which contains time elapsed handed by rAF which you can may use also for something (or just ignore it).
One note though: not all browsers support this yet (and some may use prefix) so for mobile you need to use the standard system time object.
The task is to emulate the MIDI player work in js, but just for emulate delays between beats. There is an array with beat starting times in beat clock format, for example [960, 1280, 2200, ...], and the formula I'm using for calculate millisecond time for each beat tick:
var beatTickTime = 60000 / (tempo * 96);
The problem is in very slow tick real time generation. Even if I use 1 second delay, it is still very slow. Here is how it was implemented:
var tickTimer = setInterval(function() {
...
tickCount += 1;
}, beatTickTime); // or just 1 ms
Should I pass some beat ticks doing tickCount += someNumber? Or there is more common way to solve this problem? Also I'm not sure about 96 (PPQ * 4 time) in my formula.
P. S. beat ticks comes from parsed guitar pro file
There's no guarantee that setInterval() will run as fast as you ask it to. Even if the timeout is set to 1, you can't count on the function being called 1,000 times each second.
You'll most likely need to do something like the following:
var startTime = (new Date()).getTime();
setInterval(function() {
var relTime = (new Date()).getTime() - startTime;
// relTime is now the number of ms since the script started
/*
In here, you'll need to see if relTime is large enough to indicate the next
beat has been reached. So that means keeping some sort of external marker
to indicate the most recent beat that has occurred -- when relTime is big
enough to move that marker to the next beat, also run any code that is
necessary to handle that beat.
*/
}, 1);
The loop runs "as fast as it can" but still much more slowly than desired. It measures the current time relative to the start of the script, and determines the difference at each iteration. You could divide that time by the tempo of the song, and you'll have an indicator of where in the song you currently are.
Right now i have a text-based game that deals with turns, but i want to upgrade it to a timer system so that when the timer hits 0 then you gain 1 or 2 of whatever action you were doing. Also if you know how to make it randomly pick whether u get 1 item or 2 items could you please elaborate on how to do that? Thank you to all responses.
You can use setTimeout() for delaying actions for a set period of time, or setInterval() if you wish to run it periodically on a given interval.
For getting a random number either 1 or 2 you can use random():
var randomOneOrTwo = Math.floor(Math.random() * 2) + 1;
Hope you will get from here.
http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/
Happy Coding.....