Android - ofSoundPlayer doesn't work on worker threads

Hi,

I tried searching for this, but it doesn’t seem to be a known issue, whether in OF or generally in Android’s sound pool.

The problem: when I load and play a sample using ofSoundPlayer, in android, from a worker thread, the sample doesn’t play. I get a log message that the sample is not loaded. Doing the same action in the UI thread fixes this.

I can also fix this by specifying stream=true, but by sifting the code, I see that in this case it uses MediaPlayer and not SoundPool.

I wonder if this work around is good enough (as I do need small samples and do not require streaming), or should I work it so it will work on the sound pool.

Did anyone here ran into this problem? I’m not sure, but I think it’s related to the fact that SoundPool loads the sample asynchronously, and OFAndroidSoundPlayer doesn’t listen with OnLoadCompleteListener. Even if it did, I’m not sure how to make it so it won’t break compatibility with the existing interface of ofSoundPlayer. It seems that the load() method expects the loading to be synchronous.

I would love to get some feedback on this.

Thanks,

Tal

1 Like

I am not sure how much this helps, but soundpool is only for short samples (notification sounds etc) if you are working with short sounds then soundpool could be good. Otherwise Mediaplayer is a better option, in native android you need to create an Audiotrack and then add threaded media players. Media player will load the sample asynchronously if you specify it using something like this

mediaPlayer = new MediaPlayer();
 mediaPlayer.setOnPreparedListener(this);
 try {
      mediaPlayer.setDataSource(audioRoot + fileName);
      
 } catch (IllegalArgumentException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
 } catch (SecurityException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
 } catch (IllegalStateException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
 } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
 }
 mediaPlayer.prepareAsync();
   
}

But, I have no idea how to integrate this with OF- this was one of the reasons I switched to native android.

Alternately I know there is an implementation of FMOD for android. I had much more luck with this getting multiple long audio files to play on Android.

Fred

Thanks for replying @fresla!

I do actually play short samples, so I understand that soundpool is the solution with less overhead. If only it worked.

I cannot just use any native android solution I want. I’m making a cross platform iOS/Android app with as much cpp code as I can, so every platform specific code needs to be hidden behind some abstraction.

Regarding fmod, I’ll definitely give ofFmodSoundPlayer a try tomorrow!

Thanks for the tip (I didn’t know there’s such a thing until now).

Here’s hoping it works seamlessly on iOS AND Android, even on worker threads!

UPDATE: I see there’s also openAL sound player present in the same folder. Choices choices… Anyone have an opinion regarding which fits betters to my scenario (recap: iOS AND Android, playing short samples from worker threads)?

P.S. I see I can set the sound player in use by ofSoundPlayer, so I don’t have to rewrite everything to use a different class. Very clever.

there might be a bug in the java side of the sound player that avoids starting a soundpool from a non gui thread. perhaps a simple fix is to just change the load method to always load from the gui thread if using a soundpool.

didn’t knew either that there’s an FMOD version for android, but be aware that FMOD is a commercial library that you need to pay for if you use it in commercial projects

ok, I didn’t know that. So openAL perhaps?

openSL is the preferred way of doing it in android native but it can’t for example open mp3 or any other format for that matter, you need some library to decode the files. i have an implementation i started some time ago with a custom WAV decoder but it’s still a bit buggy, i’ll upload it later somewhere if you are interested

Ok, that opened up some questions:

  1. When you say OpenSL, do you mean using ofOpenALSoundPlayer? does it use OpenSL when targeting the mobile platform?
  2. Will this method work correctly on iOS also?
  3. I don’t have a limitation on the file format I’m using. What does OpenSL take? Uncompressed wav only?

Regarding your suggestion for on-the-fly-decoding, I don’t think that’s right for me. If I will need to use uncompressed sounds, so be it. And if I really need the space, I can bundle it as mp3 and uncompress them to cache once on first load.

I wanted to try openAL sound player, so I defined a pre-processor macro “OF_SOUND_PLAYER_OPENAL”, but then it complained that it can’t find kiss header files. I went to the libs folder and found out it’s a linux only lib? So OpenAL is not an option for iOS/Android? Is there any other option other then the default one for these OS’s?

Thanks,

Tal

openSL is different to openAL. openAL doesn’t exist on android so it won’t work. this is a soundplayer based on opensl for android but as i said it’s still buggy, there’s some bad memory access and crashes on some devices from time to time. there’s also a class to be able to read wav files, the opensl player depends on it to be able to read wavs and it’s the only format it’s able to read openslplayer.tar.bz2 (5.2 KB)