[Android] Audio Decoding Issues Discussion

Just loading 19 oggs (344kb): 0.091s
Loading the same 19 oggs and calling play on the first one before it actually loaded (just after calling preload): 2.143s and app is frozen in these 2 seconds.
I know I can add listener and play sound after it loaded, but in my case it requires a lot of effort to achieve. I don’t know why it’s extending loading so drastically and freezes app at the same time.

while(0) loop in AudioEngine::play2d may be responsible for this.

The do { } while(0) exits the ‘loop’ instantly as soon as it hits the while(0) statement. The only way it loops is if the condition is true, for instance, if it was while(1), which is impossible in this case since the condition is false.

The reason the do{} while(0) is there has nothing to do with looping, but as a way to stop processing the code inside the brackets if it hits any “break;” statement. You will notice a number of “break” statements inside the do { } while(0) of the play2d function.

1 Like

Replied in that thread.

@anon98020523, pitch is not supported in AudioEngine currently.
But there is some Pull Requests (https://github.com/cocos2d/cocos2d-x/pull/13662, https://github.com/cocos2d/cocos2d-x/pull/16728) which make it available probably.

It’s possible to support pitch on those platforms which use OpenAL for playing audio.
But it will take some work to make it work on AudioEngine implementation of Android since Android uses an AudioMixer in engine side rather than using which in system to get best performance.

Actually, I tested 101 ogg files loading at the same time, and it only waste a little time for loading.
2 seconds it a bit more for just loading 19 ogg files.

Keep in mind that AudioEngine::preload is called doesn’t mean that preload is finished, AudioEngine::preload is an asynchronous interface, it will be returned very fast.

If you wanna get better experience for your game, it’s better to wait the preload to finish then play audio.

I understand it and I know preload is asynchronous.
Thing is playing any sound before it loaded shoudn’t so drastically increase loading time.
Let me show you a little function:

void HelloWorld::preloadSounds(Ref* ref, ui::Widget::TouchEventType touchEventType) {
    if(touchEventType != ui::Widget::TouchEventType::ENDED) return;
    if(loaded > 0) return;
    CCLOG("Started preloading!");
    milliseconds startMiliseconds = duration_cast< milliseconds >(
            system_clock::now().time_since_epoch()
    );
    for(int i = 0; i < files.size(); i++){
        std::string filename = files.at(i) + "." + extension;
        const int j = i;
        cocos2d::experimental::AudioEngine::preload(filename, [&, filename, startMiliseconds, j](bool success){
            CCLOG("%s done loading. Result: %s", filename.c_str(), success ? "success" : "failure");
            loaded++;
            if(loaded == files.size()){
                CCLOG("All done!");
                milliseconds endMiliseconds = duration_cast< milliseconds >(
                        system_clock::now().time_since_epoch()
                );
                milliseconds diff = endMiliseconds - startMiliseconds;
                CCLOG("loading took: %lld ms", diff.count());
            }
        });
    }
}

Loading took prints about 91ms on my device.
But let’s add one more thing here:

void HelloWorld::preloadSounds(Ref* ref, ui::Widget::TouchEventType touchEventType) {
    if(touchEventType != ui::Widget::TouchEventType::ENDED) return;
    if(loaded > 0) return;
    CCLOG("Started preloading!");
    milliseconds startMiliseconds = duration_cast< milliseconds >(
            system_clock::now().time_since_epoch()
    );
    for(int i = 0; i < files.size(); i++){
        std::string filename = files.at(i) + "." + extension;
        const int j = i;
        cocos2d::experimental::AudioEngine::preload(filename, [&, filename, startMiliseconds, j](bool success){
            CCLOG("%s done loading. Result: %s", filename.c_str(), success ? "success" : "failure");
            loaded++;
            if(loaded == files.size()){
                CCLOG("All done!");
                milliseconds endMiliseconds = duration_cast< milliseconds >(
                        system_clock::now().time_since_epoch()
                );
                milliseconds diff = endMiliseconds - startMiliseconds;
                CCLOG("loading took: %lld ms", diff.count());
            }
        });
        if(i == 0){
            cocos2d::experimental::AudioEngine::play2d(filename);
        }
    }
}

First sound is played before it loaded.
And then game freezes for a while and loading took prints 2143ms!

That time shouldn’t be that long, it should be more or less the same! It should play this sound after loading.

That wasn’t working like that while using SimpleAudioEngine. It took longer to load, but game wasn’t freezing.

I play tons of sounds in tons of screens in different situations and it’s hard to find all the ones which are played on the beginning - leave one and game is freezing hard.

Sorry about that while loop, it was confusing.

Thanks for the good work @dumganhar .

Is the new patch stable enough to update my game in Google Play? I got some dudes reporting bad reviews because the game got stuck due to sound problems in Android 7. Cocos version is 3.7, let’s see if the new patch can be introduced in this version

We have merged the patch to Cocos Creator yet, and no complain of audio any more. Probably, you could have a try and do some tests.

Sorry about that it could be used without easy modification in v3.7. You could check the different between v3.12 and v3.13 to find out what have been changed in audio module. Then, it will be easier for you to apply the patch into v3.7. Otherwise, you probably need to upgrade your engine to v3.14 (latest version).

@piotrros, yes, if your test code is all right, I guess there is something wrong inside AudioEngine.
Could you send me a demo for reproducing the issue you reported? Thanks.

Of course I can. Here it is:
PreloadBug.zip (9.0 MB)

Got to modify JNIHelper class introducing new methods, but it’s building fine for now (builds take about 15 mins to compile). I will post here my results

Ahh, that’s bad… But what about just to wrap and use some cross-platform audio engine? Like superpowered or fmod?

Should we use SimpleAudioEngine or AudioEngine? Seems a bit laggy for me in HTC Desire 820 and Sony Xperia Z

Those audio engine aren’t open source. Therefore, we will not use them.
About pitch functionality, it could be a feature request. If you need it eagerly, you could try to wrap those engine by yourself.

It’s better to use AudioEngine since SimpleAudioEngine has worse performance and it will be deprecated sooner or later, probably in v4.0.

I can confirm then a lag playing sounds with the new audio source for a HTC Desire 820 and Sony Xperia Z. Playing sounds with the current Google Play version of the game is fine for these devices and no lag is appreciated.

I will wait for testing the new audio source in an Android 7 device and see if the sound plays fine. I will not update the game in Google Play by the moment, too risky movement.

BTW I’m using AudioEngine.

@piotrros, it was fixed, please test.

https://github.com/cocos2d/cocos2d-x/pull/17233/commits/9a2b927acffa72dcc18f7561780e9292eb003930

Sorry, but it didn’t resolve the problem. It’s still the same long loading. Have you tried my example?

I tried it and confirmed it was fixed.
Did you recompile the prebuilt library?
If you make sure, please upload the logcat output. Thanks.