openfl / lime

A foundational Haxe framework for cross-platform development
https://lime.openfl.org/
MIT License
749 stars 362 forks source link

Sound.loadPCMFromByteArray crashes on HTML5 #1001

Closed watabou closed 2 years ago

watabou commented 7 years ago

Code like this:

var bytes = new ByteArray();
for (i in 0...44100) {
    bytes.writeShort( Std.int( (Math.random() * 2 - 1) * 32768) );
}
bytes.position = 0;

var snd = new Sound();
snd.loadPCMFromByteArray( bytes, 44100, "short", false, 44100 );
snd.play();

crashes with a log like this:

Uncaught TypeError: Cannot read property 'volume' of null
    at lime__$backend_html5_HTML5AudioSource.setGain (Procgensnd.js:5252)
    at lime_media_AudioSource.set_gain (Procgensnd.js:22800)
    at openfl_media_Sound.play (Procgensnd.js:48436)
    ...

Apparently AudioBuffer.__srcHowl doesn't get initialized.

watabou commented 7 years ago

Hm, it looks like Howler.js doesn't support this kind of functionality at all...

zatarus commented 7 years ago

Any success with this? I also need to load ogg/m4a from ByteArray in html target, so failed using Sound.loadCompressedDataFromByteArray 🤔

jgranick commented 7 years ago

There is a risk that loading bytes directly may be a format that the current browser does not understand, but it appears the functionality for this exists internally in howler

https://github.com/goldfire/howler.js/blob/273394e7610db67c30afab9a1bf9fc8aa09b5a35/src/howler.core.js#L2116

Something sort of like: (but I don't think this would work outside of the howler.js script)

var howl = new Howl ();
Howler.ctx.decodeAudioData(arraybuffer, function(buffer) {
      if (buffer) {
        loadSound(howl, buffer);
      }
});

I think the way this would work (if Howler supported raw bytes) would be adding an alternative to the src property, like arraybuffer, which it would use instead of loading from the source, then call this sort of thing internally

zatarus commented 7 years ago

Thank you @jgranick, that is helpful. I think we can also use base64 conversion (which is immediately supported by howlerjs) as that goes through the same functionality. I will take that path first as a workaround.

zatarus commented 7 years ago

Hello, here is my trick to get ogg bytes to work with Howlerjs:

        var b64content = 'data:audio/ogg;base64,' + Base64.encode(bytes);
        var buffer = AudioBuffer.fromFile(b64content);
        var sound = Sound.fromAudioBuffer(buffer);
        buffer.src.on("load", function() {
            //sound ready
        });

That might help someone else, just beware you have to wait Howl to respond. 😊

scanline commented 6 years ago

@zatarus Did your workaround really work on HTML5? Do you have a working sample? I'm wondering because the onLoad event never fires and even if it does how do I actually start playback?

zatarus commented 6 years ago

@scanline, this is exactly how I made it work, I didn't have any issues at all. Are you sure onload never fires? That is mapped to Howler's load function, please put a trace there to see if it fires and make sure your file is in ogg format.

player-03 commented 2 years ago

Don't mind me, just cleaning up old solved issues.