Dynamic Audio crash on any target other than Flash

It appears that attempting to call play() on a Sound instance that does not have any bytes loaded before calling the play() method crashes every target except for the Flash player. I’m unsure if this is a bug in the OpenFL implementation, or there is some other amount of setup that needs to occur before attempting start playback. I am thinking that the OpenFL implementation doesn’t handle this use case properly, as it’s counter to what the OpenFL and Flash documentation (and implementation) implies.

The use case is for dynamic audio, where there are no bytes to play on start, but will be fed data through the SampleDataEvent.SAMPLE_DATA event.

The easiest way to debug is to use the neko target. The following code causes the crash (on all platforms except Flash):

public function new () {
  var sound = new Sound();

Crashes with Neko with the backtrace

Called from ? line 1
Called from ApplicationMain.hx line 123
Called from ApplicationMain.hx line 30
Called from lime/app/Preloader.hx line 61
Called from openfl/display/Preloader.hx line 93
Called from NMEPreloader.hx line 107
Called from openfl/display/DisplayObject.hx line 790
Called from a C function
Called from openfl/events/EventDispatcher.hx line 292
Called from openfl/display/Preloader.hx line 129
Called from a C function
Called from lime/app/Preloader.hx line 234
Called from ApplicationMain.hx line 86
Called from ApplicationMain.hx line 153
Called from a C function
Called from ApplicationMain.hx line 184
Called from a C function
Called from ApplicationMain.hx line 211
Called from a C function
Called from Main.hx line 13
Called from openfl/media/Sound.hx line 430
Called from openfl/media/SoundChannel.hx line 20
Called from a C function
Called from openfl/media/SoundChannel.hx line 80
Called from lime/audio/AudioSource.hx line 163
Called from lime/audio/AudioSource.hx line 374
Uncaught exception - Invalid field access : data

Looking at AudioSource.hx:374 we see it’s clearly attempting to access the ‘data’ field of the AudioBuffer member. It looks to be the simplest fix is to initialize an AudioBuffer with 0 data bytes when attempting to call Sound#play() with no data in the buffer, but that may have unintended consequences.

I think we should add a check (probably in AudioSource?) to prevent the crash… seems like .play () with no data should just do nothing :wink:

it appears that SAMPLE_DATA is implemented in -Dlegacy but not the newer OpenFL code yet. What happens if you use openfl test neko -Dlegacy with your code?

Using -Dlegacy works fine with Neko. It’s less of an issue with listening for the SAMPLE_DATA event, that’s just a use case of why you want to play a sound object with no initial data and they shouldn’t be related. I don’t know where the best place would be to initialize an AudioBuffer with zero bytes would be; that seems like the best fix. In fact, it might be better to initialize an AudioBuffer with zero bytes always, and then reassign those bytes if there was a ByteArray present through some of the other Sound methods (loadCompressedDataFromByteArray et al) That way if you call play() it will just play a buffer of zero bytes, unless you register a callback that fills the audio buffer or through some other mechanism.

The interesting split happens on AudioSource.hx:370, where the buffer is seemingly initialized already if the platform is Flash. I don’t know where that’s happening, but the initialization of the buffer should be the same regardless of platform.

AudioBuffer holds audio data, which varies on the platform. On Flash, buffer.src is a flash.media.Sound object. Elsewhere, buffer.data holds bytes we can push to a sound subsystem like OpenAL

We probably need to check in here if the __buffer is null:

Perhaps change Sound.hx:183 to
@:noCompletion private var __buffer:AudioBuffer = new AudioBuffer(); ?

The crash is fixed now, SAMPLE_DATA still needs to be implemented in the newer code, but it won’t explode now :wink:

The new Lime was released with this fix :slight_smile:

Yes, it does not crash anymore, but also correct that the SAMPLE_DATA event is never emitted. It does work with -Dlegacy. Though there appears using legacy doesn’t call the function often enough to fill the buffer, leading to popping that isn’t present on the flash player.

At any rate, original issue is now fixed!

Any news on this?
This problem with SAMPLE_DATA is still present on native targets i think. as you say, the SampleDataEvent.SAMPLE_DATA event is never emitted on the Windows target. Only working (with popping sound) using legacy. Is really no one using this? A fix for this would be greatly appreciated.

1 Like

Same here, for me even with -Dlegacy the SampleDataEvent.SAMPLE_DATA does not work

I have opened an issue:

1 Like