Soundpool LoadComplete

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
I am trying to use the Soundpool. This seems to be better for my purposes since there does not seem to be a delay (or hickup) between wav repetitions when repeating indefinitely.

There seems to be a delay after loading a wav before it is ready to play. if I set a breakpoint after calling Load, creating a pause of several seconds before I execute Play, it works. If I don't introduce this delay, I receive a Play ID of 0 signifying it failed.

I see in the Android documentation there is a "Load Complete" callback. There does not seem to be the equivalent event in the B4A Soundpool library. This is an important feature.

Is there any way to add that event? I am wondering, as a registered user, if the source code for the library functions is available? If so, I would be willing to add that functionality.

Thanks,
Barry.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The reason that this event is missing is that it was only added in Android 2.2 (API level 8). Adding this event will make this library incompatible with older versions of Android.

Here is the source code, if you like to roll your own library (change the class name and ShortName value):
B4X:
package anywheresoftware.b4a.audio;

import java.io.IOException;

import android.media.AudioManager;
import android.media.SoundPool;
import anywheresoftware.b4a.AbsObjectWrapper;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ShortName;

/**
 * SoundPool holds a collection of short sounds which can be played with low latency.
 *Each sound has two Id values which you should work with. The first is the LoadId which is returned when loading the sound with Load.
 *The second is the PlayId which is returned when you call Play.
 *When working with SoundPool it is useful to watch the unfiltered LogCat for messages (for example when the sound is too long).
 */
@ShortName("SoundPool")
public class SoundPoolWrapper extends AbsObjectWrapper<SoundPool>{
   /**
    * Initializes the SoundPool and sets the maximum number of simultaneous streams.
    */
   public void Initialize(int MaxStreams) {
      setObject(new SoundPool(MaxStreams, AudioManager.STREAM_MUSIC, 0));
   }
   /**
    * Loads a sound file and returns the sound LoadId.
    *Example:<code>
    *Dim LoadId As Int
    *LoadId = SP.Load(File.DirAssets, "sound.wav")</code>
    */
   public int Load(String Dir, String File) throws IOException {
      if (Dir.equals(anywheresoftware.b4a.objects.streams.File.getDirAssets())) {
         return getObject().load(BA.applicationContext.getAssets().openFd(File.toLowerCase(BA.cul)), 1);
      }
      else {
         return getObject().load(anywheresoftware.b4a.objects.streams.File.Combine(Dir, File), 1);
      }
   }
   /**
    * Plays the sound with the matching LoadId and returns the PlayId. Returns 0 if there was an error.
    *LoadId - The value returned when loading the file.
    *LeftVolume / RightVolume - The volume value (0 - 1)
    *Priority - A priority value which you assign to this sound. The higher the value the higher the priority.
    *When the number of simultaneous streams is higher than the value set in Initialize the lowest priority stream will be stopped.
    *Loop - Number of times to repeat. Pass -1 to repeat indefinitely.
    *Rate - Playback rate (0 - 2).
    */
   public int Play(int LoadId, float LeftVolume, float RightVolume, int Priority, int Loop, float Rate) {
      return getObject().play(LoadId, LeftVolume, RightVolume, Priority, Loop, Rate);
   }
   /**
    * Pauses the stream with the given PlayId.
    */
   public void Pause(int PlayId) {
      getObject().pause(PlayId);
   }
   /**
    * Resumes the stream with the given PlayId.
    */
   public void Resume(int PlayId) {
      getObject().resume(PlayId);
   }
   /**
    * Stops the stream with the given PlayId.
    */
   public void Stop(int PlayId) {
      getObject().stop(PlayId);
   }
   /**
    * Sets the volume of the stream with the given PlayId. Values are between 0 to 1.
    */
   public void SetVolume(int PlayId, float Left, float Right) {
      getObject().setVolume(PlayId, Left, Right);
   }
   /**
    * Unloads the stream with the given LoadId.
    */
   public void Unload(int LoadId) {
      getObject().unload(LoadId);
   }
   /**
    * Sets the rate of the stream with the given PlayId. Value is between 0 to 2. 
    */
   public void SetRate(int PlayId, float Rate) {
      getObject().setRate(PlayId, Rate);
   }
   /**
    * Releases all resources allocated to this object.
    */
   public void Release() {
      getObject().release();
   }
}
 
Upvote 0

canalrun

Well-Known Member
Licensed User
Longtime User
The reason that this event is missing is that it was only added in Android 2.2 (API level 8). Adding this event will make this library incompatible with older versions of Android.

Here is the source code, if you like to roll your own library

Thanks.

I did not notice it was a new function – backward compatibility is also very important.

I found a solution, which I am not proud of, but seems to work:

B4X:
        For i=1 To 1000
          pid = SP.Play(lid, f, f, pri, lp, rt)
          If (pid > 0) Then Exit
        Next
I find it takes about 100 iterations of the loop before pid is returned as a positive number. I am fairly certain that the number of loops will be dependent on the wave file size. I will try sticking a DoEvents in the loop to insert a little more delay.

Thanks,
Barry.
 
Upvote 0
Top