How do you sync javascript animations with the tempo of a song without creating an “audio visualizer”?

In my basic understanding, JavaScript audiovisualists reflect music based on real sound waves. I would like to build something like a metronome (http://bl.ocks.org/1399233), where I animate some DOM element every x beats.

As I do now, I manually determine the tempo of the song, say 120bpm, then I convert it to milliseconds to trigger the setInterval callback. But this does not work, because the performance of the browser causes its inaccuracy. Is there a better way to make sure that the callback is being executed at exactly the same pace as the song?

If not, what other strategies are there to synchronize JavaScript animations with the tempo of a song that is not an audio visualizer?

Update: does something like this look like? https://github.com/bestiejs/benchmark.js/blob/master/benchmark.js#L1606

+4
source share
2 answers

I had a similar problem, since in setInterval it was impossible to rely on "keeping time" for a long period. My solution was the snippet below: (in a coffee script, compiled js is at the end of the link)

This provides a replacement for setInetrval, which will remain very close to saving time. With it, you can do this:

 accurateInterval(1000 * 60 / bpm, callbackFunc); 

See my usage example and an example that synchronizes visual effects with the provided BPM for YouTube videos: http://squeegy.github.com/MandalaTron/?bpm=64&vid=EaAzRm5MfY8&vidt=0.5&fullscreen=1

exactInterval code:

 # Accurate Interval, guaranteed not to drift! # (Though each call can still be a few milliseconds late) window.accurateInterval = (time, fn) -> # This value is the next time the the timer should fire. nextAt = new Date().getTime() + time # Allow arguments to be passed in in either order. if typeof time is 'function' [fn, time] = [time, fn] # Create a function that wraps our function to run. This is responsible for # scheduling the next call and aborting when canceled. wrapper = -> nextAt += time wrapper.timeout = setTimeout wrapper, nextAt - new Date().getTime() fn() # Clear the next call when canceled. wrapper.cancel = -> clearTimeout wrapper.timeout # Schedule the first call. setTimeout wrapper, nextAt - new Date().getTime() # Return the wrapper function so cancel() can later be called on it. return wrapper 

get the coffee script and js here: https://gist.github.com/1d99b3cd81d610ac7351

+6
source

This message may be relevant:

The bottom line is that you run the function in setInterval() little faster than your pace, for example, every 100 ms. A short, long example, you can track if the time to play is beat by checking the value of (new Date()).getMilliseconds() and seeing if the equivalent of one bit has passed in milliseconds instead of relying on the inaccurate accuracy of setTimeout or setInterval .

Even so, the music itself, if it is not computer-generated, may not have an ideal or consistent tempo, so accounting for erroneous beats may be an obstacle for you, and this may be the reason for using audio analysis to find where the actual bits may happen, which is the best way .

+2
source

Source: https://habr.com/ru/post/1383998/


All Articles