SoundManager2 has an irregular delay

I play some notes at regular intervals. Each of them is delayed by a random number of milliseconds, creating a sharp irregular effect. How to fix it?

Note. I am fine with some delay until it matches.

Answers like “implement your own little SoundManager2 replacement, optimized for synchronization-sensitive playback” are fine if you know how to do this :), but I try not to rewrite my entire application in Flash at the moment.

For an example application with zero audio delay, see ToneMatrix .

TestCase ( see live here or get it in zip ):

<head> <title></title> <script type="text/javascript" src="http://www.schillmania.com/projects/soundmanager2/script/soundmanager2.js"> </script> <script type="text/javascript"> soundManager.url = '.' soundManager.flashVersion = 9 soundManager.useHighPerformance = true soundManager.useFastPolling = true soundManager.autoLoad = true function recur(func, delay) { window.setTimeout(function() { recur(func, delay); func(); }, delay) } soundManager.onload = function() { var sound = soundManager.createSound("test", "test.mp3") recur(function() { sound.play() }, 300) } </script> </head> <body> </body> </html> 
+4
source share
4 answers

I know that this is not the answer you want to hear, but there is no way to stop it, regardless of whether you wrote your own flash library to play sound or not.

For everyone who said, "this works great for me!" try resizing or moving the browser window when the demo version of the player is played. You will hear more than just a subtle delay. This is most noticeable in Firefox and IE, but even Chrome will experience it.

Worse, if you click and hold the mouse in the close window of the browser window, the sound will stop completely until you release the mouse (you can release it outside the close field and actually close the window, FYI).

What's going on here?

It turns out that when you start resizing or moving around the browser window, the browser tries to multitask to change the properties of the window, given that javascript continues to work in the window. He briefly changes the window when he needs to.

When you hold the mouse over a closing window in the browser window, the time completely stops. This is what happens in smaller increments when recalibrating or moving the window: time in the javascript world remains small, sporadic pieces (or large pieces, depending on how slow your machine is).

Now you can say: "Of course, resizing the browser or pressing the close button pauses the browser, but usually it will not." Unfortunately, you are mistaken.

It happens all the time, really. I ran the tests, and it turns out that even leaving the browser window completely motionless, without touching the mouse or touching the keyboard, the background processes on the computer can still cause hiccups, which means that for a short time (maybe up to several milliseconds) , the time "stays still" in the browser, a completely random interval out of your control.

What do I mean by standing? Let's say you have a setInterval () call (this also applies to setTimeout) that runs every 33 milliseconds (about 30 frames per second). Now you expect that after every 33 milliseconds of the real world, your function will be called. And most of the time this is true.

But when the hiccups begin, your setInterval call can happen in 43 milliseconds. What happened in 10 ms? Nothing. Time froze. Nothing was updated in the browser. If you had a sound game, it will continue to play, but no new sound calls will start to play, because no javascript is executed at all. If you had 5 setInterval () functions running, at some point they would be paused for 10 ms.

The only way to say that "time has stopped" is to poll the real time in your setInterval callbacks. You can see that the browser tries to keep up most of the time, but when you start resizing the window or doing something stressful, the intervals will be longer than usual, but all your code will remain synchronized (I make games using this technique, so you You’ll see that all updates to your game happen synchronously, but they just stutter slightly).

Usually, I have to point out that these stutters are completely invisible, and if you did not write a function to register real-time during setInterval time (as I already did in my own testing), you would not even know about it. But this becomes a problem if you try to create some kind of repeating sound (for example, an audio signal against the background of Asteriods) using repeated calls to play ().

My suggestion? If you have a sound that, as you know, will be looped, give it a long time, maybe 10 seconds, and you are less likely to notice hiccups (now the graphics on the screen may still be hiccups, but you are screwed there).

If you are writing a game and shooting from the main character with a machine gun, do not make 10 quick calls to playSound ("singleShot"), one call to playSound ("machineGunFire10Rounds") or anything else along these lines.

You will need to cheat a little to get around it, but in most cases everything will be fine.

It seems that Flash applets start in a process that somehow affects all this time “freeze time” occurring in a normal browser / javascript environment, but I can still achieve this even with your ToneMatrix link, for example, by resizing or moving the browser window.

But Flash still seems a lot better than javascript. When I stay in the browser, I bet that Flash does not freeze for a while, and these intervals always work on time.

TL; DR:

  • you screwed up what you hope to achieve.
  • try to handle this using some workarounds
  • rewrite the project in clean flash (without javascript)
  • wait until the browsers get better (Firefox 4 gets a new javascript engine called JaegerMonkey , which will be interesting to view)
  • How do I know all this? I have done many tests and logging with javascript, setInterval and sound calls soundManager / html5.
+10
source

In my commentary on your question, I mentioned that I don’t hear irregularities when I play your pattern. This means that I’m either a “dull beat” or that there may be something in your setup that interferes with good real-time performance. You do not mention any information about your environment, but other processes may be running on your computer that drain the processor cycles or an older version of Flash that may not cope with audio delays. I myself use the latest version of Flash (10.something), while your options require Flash 9. But maybe I should assume that if you are smart enough to use SoundManager2 and StackOverflow, you would fix these problems.

So, here are some troubleshooting methods and comments that come to mind:

1) There are several demos on the SoundManager website, including the JS-DOM "painting" + Sound, V2 . Do you hear irregular delays and delays there? If not, perhaps you can compare what they do there versus what you do. If so, then maybe look at your computer environment. When I run this demo, it is very responsive. ( EDIT: If you look at it more closely, you can see how the size of the brush stamps changes during a stroke. Since it depends on the time interval between mouse events (provided that you keep the mouse speed constant), you can visually see which or any irregularities in the mouse event pattern. I see a random change in the size of the stamp, which indicates that the mouse events do not appear at normal times, which leads us to Javascript events.)

2) Javascript setTimeout() and setInterval() not very reliable when it comes to time. Basically they return at some approximate interval that you requested, but there may be large variations, usually delays, which make them unreliable. I found that the same is true when using ActionScript inside Flash. You might want to print the time during which the sound.play () call is made to see if the irregularities match the violations in setTimeout/setInterval() . In this case, you can try to shorten the interval, and then poll the system time to get closer to the 300 ms interval you want. You can poll the system time using new Date().getTime() , and this seems to have ms precision. A poll is, of course, a disgusting hack that sucks loops when they can be used for something else, and I do not recommend it at all, but you can try it to see if it helps. EDIT: Here is a post by John Resig about handling input and timer events in js .

3) When the flash plays sounds, usually latency occurs, so the player can “create a steam head” and make sure that there is enough material in the buffer that will be played before the next buffer request is filled, There is an exchange between this delay and reliability of continuous playback. This may be a limitation that you can’t do anything about except “implement [your own] SoundManager2 replacement”, which I know you don’t want to do.

Hope this helps. I recently wrote an AS3 sound experiment that exposed me with some of the basics, and will be watching this space to see what other suggestions people have come up with.

+1
source

You are using a javascript interval that cannot be guaranteed to fire at a specific time. I am sure flash time is much more reliable.

But this may help, resume the replay after you turn on the sound.

 window.setTimeout(function() { func(); recur(func, delay); }, delay); 
0
source

As explained in another answer, you cannot avoid this. But...

I have done several experiments to mitigate these problems, and in the end I resorted to using:

Take a look at the source on the prototype demo and (if possible) give a lowLag shot. This worked well for me.

Good luck

0
source

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


All Articles