Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android L SoundPool.load() regression

On Android L - the latest developer preview (Nexus 5), there seems to be a regression in the SoundPool.load() method which takes >5 seconds to load a sample (<100kb), where samples were loaded on pre-L systems instantly with the very same code.

I tried OGG or MP3, both with same results. Tried different sizes but all under 100kb. Seems as 40kb or 80kb does not make any difference, so does OGG or MP3. Loading is always around 5s delay.

This seems as yet another regression in SoundPool after looping has been broken in 4.3.

The issue is easily reproducible with:

    pool = new SoundPool(6, AudioManager.STREAM_MUSIC, 0);
    // use a listener to start playback after load
    pool.setOnLoadCompleteListener(listener);

    // R.raw.sound1 is either an OGG or MP3 sample under 100kb od size
    int id = pool.load(context, R.raw.sound1, 1);

    // onLoadComplete() method of the listener is called several seconds after the call to laod()

The same is happening for constructing the SoundPool using the Builders introduced API 21 as follows:

    AudioAttributes attr = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .build();

    pool = new SoundPool.Builder().setAudioAttributes(attr).setMaxStreams(6).build();

Is anyone else experiencing this? Did anyone find a workaround?

Many thanks!

like image 689
Petr Nalevka Avatar asked Oct 26 '14 19:10

Petr Nalevka


1 Answers

Just so you guys know, this is a known bug:

  • https://code.google.com/p/android-developer-preview/issues/detail?id=1812
  • https://code.google.com/p/android/issues/detail?id=81187

I have tried multi-threading... It works ok in a sense that it doesn't block the app! But you need to know that you can't call Soundpool.load method before all of your sounds are loaded. Even if you call load on a sound that has already been loaded, it causes the app to freeze. I guess the SoundPool class has some sort of internal synchronization of some sort. Anyways, you can make your app sort of work using this method. This is sort of an snippet that can help:

 private class loadSFXasync extends AsyncTask<String, Integer, Long> {
     protected Long doInBackground(String... str) {
         int count = str.length();
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             mSoundPool.load(str,1);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         mAllSoundsAreLoaded=true;
     }
 }

and in your code:

playSound(String str){
    if (!mAllSoundsAreLoaded)
    return;
    // otherwise: do mSoundPool.load(....)
}
like image 178
Kasra Avatar answered Oct 18 '22 22:10

Kasra