How do I know when audio is ready to be played in HTML5?

Hi,
this can be considered a twin-topic of discussion

sound-not-playing-on-html5-target-ios

We all know that in iOS sound must be unmuted before we can hear it, but before this there is another problem: when I load a game I have to download sounds, and in HTML5 sounds are not loaded completely before game starts, they are “streamed”, I can just say “start downloading sound files”, and I will hear them only when they are ready.
So, how do I know when a sound file is ready to be played? More in detail, how do I know when a music can be played? When coding in AS3 I use Greensock libraries that tell me when enough data has been downloaded to allow me to play a music… how can I do it in Openfl?
Maybe I have to periodically try to play it, or check if it is not null?

You can use the Sound’s “complete” event. It works perfectly on HTML5 on desktop browsers. Would this work on iOS browser as well?

// assuming _sound is an openfl.media.Sound instance
this._sound.addEventListener(Event.COMPLETE, completeHandler);

I already use this event for loading sounds, and in HTML5 target (on iOS and Android) loading is instantaneous, that means it just starts the download: if i try to play sounds immediately after the COMPLETE event I can’t hear them.

If you are using openfl.media.Sound, you can just treat it like AS3.

var snd = new Sound();
snd.addEventListener( Event.COMPLETE, onLoaded );
snd.load( new URLRequest( "some/url.mp3" );

Then for playback complete:

var sndChannel = snd.play();
sndChannel.addEventListener( Event.SOUND_COMPLETE, onSoundFinished );

This works on iOS/Safari (and the rest of the browsers on mobile/PC), so long as you are using a supported sound type. If you try to load an OGG on iOS for example (even if it’s just a fallback you know isn’t supported) sound will not play at all for some reason. It seems maybe Safari doesn’t follow through when it encounters a file type it doesn’t know what to do with.

I need to use loadSound of Assets.hx because I want to use its caching feature. Anyway I am pretty sure that sound download in JS works the same using snd.load(“urlRequest”) too: I think it simply launches a “GET url” like loadSound and returns a COMPLETE event immediately, but I should test this.

So… do you think I can detect when download is complete?

I know with Assets, there is a second param for an onComplete function for every load method. It is commented as deprecated, but as far as I know still works. @singmajesty would know if events or other methods are advised here to catch load completion through Assets.

I am trying to see if it works.
Alternatively is it possible to know if a sound is being played? I could try to play music repeatedly until it effectively starts.

There are a few more sound properties that could help you out here.

Loading related:

  • isBuffering
  • bytesLoaded / bytesTotal

Playing related:

  • sound.play() returns a SoundChannel. I believe null is returned if it failed to play.
  • I don’t think there’s any simple way to find if a sound is currently playing. For that, you may just need to write a wrapper class where you can track a bool yourself.

isBuffering returns false
bytesLoaded returns 0
playing the file the resulting soundChannel is not null

Even if the file has not been downloaded yet I am not able to understand when it effectively is complete or is playing, I have no clue on how to play this sound file at the right time.

If I play it every 1sec I have to wait about 10 seconds for download and then it starts playing, restarting every second.
It is like I am blind and can’t see what’s doing/downloading.