views:

3133

answers:

11

I've got a few very short audio clips (less than a second long) to be played on various events (button hover, click, etc). However, there is usually a significant lag between the action and the actual playing of the sound. I have tried both embedding the sound in the .swf, and loading it externally at the start, but both lead to the same results. Likewise, I've tried with compressed and uncompressed audio.

What it seems like is that the audio buffers are just a lot longer than I need them to be, like perhaps Flash is optimized more towards playing longer sounds without any stutter at the expense of a little more latency in starting sounds. Could this be it? Is there any way to change them? Since what I'm working on will never need to play sounds more than a second or so long and will always be loaded completely at the start, it wouldn't hurt it at all to have really short buffers.

One other possible thing that might be the cause: if I use .wav files when using loadSound()... I can't get it to actually play the sounds. There's no errors, and everything returns as it should, but no actual sound is played, which is why I have them as .mp3 currently. Perhaps when using .mp3 audio (or any compressed audio), there just will be lag in decoding it? The reason I still have doubts about this, though, is that when embedding them in the .swf as .wav files (by importing them into the library), they still have the same latency on playback.

Just for a sanity check, I'll include the code I've got, minus irrelevant parts and error checking. First, loading them at runtime:

var soundArray:Array = new Array();
loadSound( "click", "sounds/buttondroop4.mp3" );
loadSound( "hover", "sounds/Dink-Public_D-146.mp3" );

function loadSound( name:String, url:String ):void
{
   var req:URLRequest = new URLRequest( url );
   soundArray[ name ] = new Sound( req );
   soundArray[ name ].addEventListener( Event.COMPLETE, soundLoaded );
}
function soundLoaded( event:Event ):void
{
   for( var name:String in soundArray )
   {
      if( event.target == soundArray[name] )
      {
         trace( "Loaded sound [" + name + "]" );
         return;
      }
   }
}
function playSound( name:String ):void
{
   for( var nameSrc:String in soundArray )
   {
      if( name == nameSrc )
      {
         var channel:SoundChannel = soundArray[ name ].play();
         return;
      }
   }
}

// Sometime later, well after soundLoaded() callback is triggered...
playSound( "click" );
playSound( "hover" );

And an alternate way, embedding them in the library as classes and going from there:

var sClick:soundClick = new soundClick();
var sHover:soundHover = new soundHover();
sClick.play();
sHover.play();

The sound files are tiny, less than 10kb generally. The lag is apparent enough that one of the first complaints someone had when looking at it was that the sound effects on button hovers seemed delayed, so it wasn't just me being picky. I feel like I must just be doing something wrong; there's too many flash things out there that have snappy sound effects without anywhere near this kind of lag.

edit: In response to the first response about sound files themselves, I've already checked, and the sound starts immediately at the start of the file (even clipping out everything but the very first millisecond of sound, I can still hear the start of the 'tick' noise it makes).

+4  A: 

Well, my first-blush answer is that when I've done things like this, normally I find that sound files have a certain amount of lead time built in. You could check in a sound editor, but What I've done in the past is to import the sound into the Flash IDE, make an empty movie clip, and put the sound on frame 1 of the clip. Then, but editing the frame sound you get a nice little interface to drag the start/end points of the sound playback. Then I used to either attach/remove the clip to play the sound, or leave it somewhere and use frame commands.

If you're already sure that the lead time is in flash and not the audio then I have no tips or tricks, beyond reasonably obvious things like playing click sounds on key down instead of up...

fenomas
+6  A: 

It's a little thing but:

function playSound( name:String ):void
{
   for( var nameSrc:String in soundArray )
   {
      if( name == nameSrc )
      {
         var channel:SoundChannel = soundArray[ name ].play();
         return;
      }
   }
}

Should be:

function playSound(name:String):void
{
    if(soundArray[name])
    {
        soundArray[name].play();
    }
}

There is no need for a loop look up since that is what the hash table is for. Also, you shouldn't use an Array at all for that since an Array is an ordered set which is indexed using integers. You want to use an Object (or Dictionary) in this case and name it soundMap (since it maps sound names to sound objects).

As for sound latency -- there should be none. I've done quite a bit of sound in Flash (including tons of one off rollover and rollout sounds) and it has never been an issue. However Flash Player 10 has a new low-level sound API which is described by one of the Adobe engineers in that article. A solution involving that is a bit of a sledge hammer but perhaps you are looking for millisecond accuracy.

The advice fenomas gives is wise: check the mp3 file for deadspace at the start and end and trim it as close as possible. Also - what is the path from the event handler to your play statement? Are there any possible blocks there? What is the format of the mp3? Flash works best with specific encodings (44.1 hHz and 128 bit I believe).

James Fassett
+1  A: 

Hi,

did you find a solution to this problem yet? I am currently in the development of an as3 project and running into the exact same problem. When hovering different buttons in a short time, it sometimes even doesn't play any sound and after some random time (miliseconds to seconds) plays all of them one by one as if they were stacked.

+2  A: 

I had the exact same problem... until I noticed that the problem was only occurring only while previewing within Flash. Try running the complied swf (it worked for me).

+1  A: 

I've having the same problem. I tried your suggestion Tom about working it in release, it is a bit better, but it's still noticeably latent in Flash Player 10.

There has to be a way to do this...

+1  A: 

Thank you very much for that piece of advice, Tom! Was having the same problem- my sounds were playing multiple whole seconds after they were called and I was completely clueless to what could be causing it. Running the compile swf completely cleared this up for me.

+1  A: 

My own experimentation matches what people have been saying here -- there's much more latency when testing the swf versus viewing the published swf in a browser, but it's still bad enough to be very distracting in the rhythm-based game I'm working on. I'm going to try using the low-level sound APIs James mentioned; I'll report back if that works better. Still, it seems strange -- for a while now I've seen Flash games that play sounds in response to player input without noticeable lag.

zole
A: 

I was having bad sound lancency (about 1 full second) with Flash Player 10.0.2.x. The lantency was the same when stopping the sound channel.

I just upgraded to 10.0.22.x and the problem is gone.

A: 

I'm having the same problem. Came across this. Apparently if you keep the sound player "going" silently in the background, it doesn't need to "restart" for small sounds. Haven't tried it yet...

http://www.ghostwire.com/blog/archives/as3-fixing-the-lag-that-arises-when-playing-a-short-sound-effect/

A: 

Hi, Just came across this issue. Strangely, in Linux, I didn't have this problem. It was Flash Player 10 in Linux too.

A: 

Hi I have the same problem I tried playing published swf in standalone player and the delay is gone. When playing from Flash program after compiling, the delay is present.

AlexG