Android audio: Crash if USoundWave::GeneratePCMData returns 0 samples

We have a custom USoundWave-derived asset which can potentially return 0 from GeneratePCMData if it has not uncompressed the data in time. This tends to happen just the first couple of times after the asset is loaded. On Windows this does not cause any noticeable issue, but when deploying to Android it results in a crash.

Is it acceptable for this method to potentially return 0? Looking at the various implementations in the engine, it seems that it is.

Here’s what I’ve found from debugging:

FAudioDevice::StartSources calls Source->Init (AudioDevice.cpp:1943) to initialize a new source with the wave instance.

After a successful call to CreatePlayer(), FSLESSoundSource::Init sets the WaveInstance member of the source to InWaveInstance.

If the following Enqueue call fails* (see below), then DestroyPlayer() is called, which nulls out the various SL_ interfaces on the source, then Init returns false. Note that the WaveInstance member of the source remains non-null.

WaveInstance->StopWithoutNotification() is called (AudioDevice.cpp:1957).

In the next call of FAudioDevice::Update, the sources are iterated through and IsFinished() is called on each one (AudioDevice.cpp:2015).

This will call IsSourceFinished() if the WaveInstance member of the source is non-null (AndroidAudioSource.cpp:568). Even though our source failed to initialize, its WaveInstance member retained a valid pointer.

FSLESSoundSource::IsSourceFinished dereferences the SL_PlayerPlayInterface interface pointer (AndroidAudioSource:549), which had been nulled out in DestroyPlayer, resulting in a crash.


*I’m seeing the following in the log at this point:

05-16 22:27:26.784  7968  7992 W libOpenSLES: Leaving BufferQueue::Enqueue (SL_RESULT_PARAMETER_INVALID)

I suspect this is failing as a result of GeneratePCMData returning 0, which is causing AudioBuffers[0].AudioDataSize to be set to zero, and I’m guessing that is what is considered the invalid parameter. Regardless, I don’t think a failure here is intended to result in the crash that follows.

Is it acceptable for this method to
potentially return 0? Looking at the
various implementations in the engine,
it seems that it is.

Yeah, I think a similar crash was reported on and we just allowed the 0-value return and early outed.

Hi ,

We have not heard back from you in a few days, so we are marking this post as Resolved for tracking purposes. If you are still experiencing the issue you reported, please respond to this message with additional information and we will offer further assistance.

Thank you.

I just took the comment from MinusKelvin as confirmation that it probably is a bug, not as a solution. If it was intended as the latter, I don’t follow.

As far as I can see, there is a fundamental issue with the Android engine code that will inevitably lead to a crash if GeneratePCMData returns 0, as detailed in my post.

This is currently forcing us to use a blocking call as a workaround on Android for our audio plugin, resulting in an unacceptable hitch when playback begins.

Hi ,

I’m not our android platform programmer so am not completely familiar with the android API. Instead of blocking, have you tried simply writing out 0s on the GeneratePCMData() callback in the case that the sound is not ready to play yet?

I hadn’t thought of that, I’ll give it a go. Thanks.

Can I ask that this is left open and investigated though, since I’m fairly sure there is an issue with the code.

Well, I’m working on a multi-platform mixer that will theoretically replace all this duplicated code everywhere – so hopefully this problem (and many many many others like it) will be reduced to ONE implementation… :slight_smile: