goldfire / howler.js

Javascript audio library for the modern web.
https://howlerjs.com
MIT License
24.03k stars 2.24k forks source link

XDK (Cordova + Crosswalk 17) Problem with Loop and Buffer #538

Closed shibekin69 closed 8 years ago

shibekin69 commented 8 years ago

Hi!

I've been doing some troubleshooting with my game that's using:

Phaser 2.4.8 XDK (Cordova + Crosswalk 17, current version) and of course, Howler.js (v. 1.1.29)

And I've encountered a bug. My target build is Android. I only have 1 3-min long OGG music file here that loads up as background music and I encountered this peculiar problem where Howler would make these scratchy echo-y noise, as if it's trying to play multiple copies of the music at once. The game would slow to a crawl like a broken loop until it hangs (in effect, it hangs almost immediately when this happens). So after a couple of hours of searching what the problem was, I nailed it down to this setting:

var testSound = new Howl({
  urls: ['audio/song.ogg'],
  autoplay: true, 
  buffer: true,
  loop: true
});

It APPEARS when...

It DOESN'T appear when...

I was hoping to get this running smoothly too... I first thought it could be this:

https://bugs.chromium.org/p/chromium/issues/detail?id=593273

As in one of the test scenarios, I saw a lot of these messages in Chrome's console window:

"Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause()."

goldfire commented 8 years ago

So, if you don't set buffer to true there is no issue? Is there a specific reason to force HTML5 Audio (which generally isn't recommended on mobile unless playing large audio files) here? You may also want to try something other than OGG to see if that is where the issue is (https://github.com/goldfire/howler.js/tree/2.0#format-recommendations).

shibekin69 commented 8 years ago

Well, I'm hoping to turn on both of these settings ON in the mobile game, as I've got a lengthy background music that I'd like to play on loop. The buffer setting is a pretty good solution to get the music playing immediately rather than having to wait 20s to a minute for the decoder to do its job, but without the loop function working...

Is there a work around I can use here just in case?

@File format - I'll see what happens if I use FAAC (m4a).

goldfire commented 8 years ago

There may be a workaround, but I still don't know what the problem is. Have you tried using 2.0? It is actually much more stable at this point and has fixed a lot of bugs, which may include this.

shibekin69 commented 8 years ago

I didn't see that one. I'll check it out and give you an update later.

shibekin69 commented 8 years ago

Hi again,

Ok, I think I have a work around. Since playing with buffer: true really just plays the audio without knowing the duration of the file (since it wasn't preloaded), the loop has to be done with a user-defined timer in his/her game, and the duration has to be set by the user. Here's what I noticed about playback with buffer: true...

  1. While the music is playing, the user can set the pos(0) to immediately restart the music with his/her own timer.
  2. However, if you call a stop() or pos() right before the actual music ends, the buffer still 'silently progresses' until the end of the music and does a stop when the actual music end is reached, so even if the music restarts when you do a pos(0), or pos(0).play(), or stop().play(), it will still stop the music, thereby interrupting loop playback by this user-made loop.

So to make this work with the fake loop, if you edit hower.js, on line 481 and comment out self.stop(data.id), this does the trick.

This work around is primarily to get this thing working on Cordova first, then desktop Chrome.

goldfire commented 8 years ago

Are you saying there is an issue in Cordova where HTML5 Audio doesn't pass a duration? In every browser it certainly passes a duration from the metadata that is downloaded first from the file before any playback can begin. However, OGG often has problems with this since it doesn't have that metadata for duration and the browser must guess.