Wednesday, May 14, 2008

Adobe Is Making Some Noise Part 1

If you have been following the community there has been quite a stir around lack of sound features in the Flash Player. Not only lack of sound features, but the last two dot releases have injected serious bugs in the sound support. This is unfortunate and some of these are squarely my fault, but some of them are design choices for which there are no workarounds.

The big controversy has been around the SOUND_COMPLETE event which has become less predictable. There is a change I had to make for Windows Vista to fix an audio-video synchronization issue. Windows Vista uses a new audio stack and does support the older but still viable WaveOut API through an emulation layer. This emulation layer does not behave exactly like previous iterations of Windows and exposed some bad assumptions the Flash Player made to drive audio-video synchronization and the famous the SOUND_COMPLETE event.

To be clear: the accuracy of SOUND_COMPLETE will get even worse in Flash Player 10. Here, I said it. Why? Because the world moves on and power consumption of devices becomes more important than ever, even for desktops. One of the stumbling blocks of improving power consumption on Windows was the Flash Player and we've gotten an earful from Microsoft and Intel because of it. The key part here was a Win32 API we used which is timeBeginPeriod()/timeEndPeriod(). We were setting the period to 1ms so that events like SOUND_COMPLETE would be more accurate, dispatched at the right time. This worked on Win98 through WinXP but is essentially useless on Windows Vista since the sound stack works in a different way as I mentioned above. So apart from being useless on Vista using this API is deadly for power consumption and a show case of bad engineering. We can not continue to rely on it.

So what does that mean? You should have never relied on SOUND_COMPLETE in the first place to do sound processing. Easy for me to say, but Macromedia did miss putting a big warning into the documentation. Or maybe the real problem was that no one really paid attention to the sound stack for such a long time. I am trying to change this, unfortunately in the process causing havoc for some clients and breaking backwards compatibility.

Continue to read Part 2 to see how we will address the requests from the community in Flash Player 10.

7 Comments:

Blogger tomsamson said...

boo

Thursday, May 15, 2008 12:09:00 PM  
Blogger p.stolp said...

Hello,
I am in this issue for quite some time. I think Macromedia, but ALSO Adobe, should have been open about the minimal audio sync/sequence possibilities of Flash and the fact that onSoundComplete should not be used as a solution for this. Please also look at http://www.actionscript.org/forums/showthread.php3?t=146032

Saturday, May 17, 2008 3:12:00 PM  
Blogger p.stolp said...

Hello,
I am in this issue for quite some time. I think Macromedia, but ALSO Adobe, should have been open about the minimal audio sync/sequence possibilities of Flash and the fact that onSoundComplete should not be used as a solution for this. Please also look at http://www.actionscript.org/forums/showthread.php3?t=146032

Saturday, May 17, 2008 3:12:00 PM  
Blogger Ric said...

I'm sorry, but the choice to break the audio playback and blame the users for not knowing better than to use documented class events is pure hubris.
It is not just the SOUND_COMPLETE event that broke when this change was made, you have introduced serious errors into the playback of audio files that are not 44.1kHz (see the public bugbase).
And to tell us that it's only going to get worse is just rubbing salt in our wounds. At least try to be helpful. Tell us how to get needed functionality back if you're going to take away some of the features that we've relied on for more than 5 years.
This is extremely painful for those of us doing Flash development. You should understand that the decision you've made is costing us dearly with our clients.

Friday, June 20, 2008 8:01:00 AM  
OpenID rdmartell said...

Okay, so I'm not sure how we're supposed to solve this. It appears to me, that you're basically pushing your bad engineering off on us.

It would seem to me, that as you were populating the audio ring buffer, you would be aware of how many bytes of sound data you have left. Once you put in the last chunk of sound, and start padding out silence, you could calculate how long until the playhead hits the silence, and setup a high priority thread (or event, or what have you) to fire at that point, which then would cause the SOUND_COMPLETE event to fire.

Instead, by getting rid of a valid and useful event, I'm going to have to poll the SoundChannel for it's position, and compare it to the duration of the Sound, since there is not a way I can do this based on an event, essentially causing all the same power drain issues that you were talking about avoiding in this post.

Perhaps I'm missing something. Is there a better way to know when a sound has completed playing?

Tuesday, October 28, 2008 1:41:00 PM  
OpenID rdmartell said...

Quick followup to the above:

It doesn't work. I have a SoundChannel that is playing, and I'm checking it's status every 1000ms with a timer.

The audio is complete, but the SoundChannel is no longer updating it's position, and it didn't reach the end of the Sound:

Position: 53908.93424036281 Length: 53928.00453514739
Position: 53908.93424036281 Length: 53928.00453514739

So I can't even solve this through polling.

Sigh...

Tuesday, October 28, 2008 1:55:00 PM  
Blogger Tinic Uro said...

rdmartell,

if you want get to get a sound complete event do not pad the callback with silence, instead just pass the remaining data. A sound complete event will then be dispatched. That might still not be accurate enough for your purpose though.

For calculating exactly when a sound will finish playing, the Flash Player 10 documentation explains how to calculate the exact latency of sound playback:

http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/events/SampleDataEvent.html

Add the latency to the current time + the remaining sound to the played and you will know the time the sound will finish playing.

Something like this:

function onSampleData(SampleDataEvent:event):void {
// calc remaining samples
var remainingSamples:Number = ...;
...
// calc sample data and fill event.data
...
// at the end calculate when the sound will stop playing
endTime = ( ( even.position / 44.1 ) - sound.position ) + remainingSamples/44.1 + getTimer();
}

Tuesday, October 28, 2008 2:10:00 PM  

Post a Comment

<< Home