24

I have a .wav file that I'd like to use across my game, currently I am loading the sound in onCreate() of each activity in the game.

 soundCount = soundpool.load(this,R.raw.count, 1);

The sound will be played once the activity starts.

  soundpool.play(soundCount, 0.9f, 0.9f, 1, -1, 1f);

Problem is at times I will hit the error "sample x not ready". Is it possible to load the .wav file once upon starting the game and keep it in memory and use it later across the game? Or is it possible to wait for 1-2 seconds for the sound to load finish?

4

8 回答 8

37

You'll need to wait for it to finish by adding a listener via SoundPool.setOnLoadCompleteListener.

于 2011-03-05T08:03:09.640 回答
5

Since my project is compatible with Android 1.5 and I couldn't use setOnLoadCompleteListener, I resolved making the play of sound delayed. My source code follows:

    playSound_Delayed(soundId, 100);

// (..)

private void playSound_Delayed (final int soundId, final long millisec) {
    // TIMER
    final Handler mHandler = new Handler();
    final Runnable mDelayedTimeTask = new Runnable() {
    int counter = 0;
    public void run() {
        counter++;

        if (counter == 1) {
            boolean ret = mHandler.postDelayed(this, millisec); 
            if (ret==false) Log.w("playSound_Delayed", "mHandler.postAtTime FAILED!");
       } else {
           playSound(soundId);
       }
    }
    };
    mDelayedTimeTask.run();
}
于 2011-06-05T18:14:32.620 回答
4

you should use setOnLoadCompleteListener if possible ... if not, wrap a while loop around your call to 'play'. something like:

int waitLimit = 1000;
int waitCounter = 0;
int throttle = 10;
while(soundPool.play(soundId, 1.f, 1.f, 1, 0, 1.f) == 0 && waitCounter < waitLimit)
 {waitCounter++; SystemClock.sleep(throttle);}

this will retry 'play' 1000 times on a 10ms interval. this should be run on a non-ui thread of course, and is still not ideal. but maybe a little stronger than waiting an arbitrary time and expecting the pool to be ready.

于 2011-09-13T08:21:25.310 回答
2

The SoundPool library uses the MediaPlayer service to decode the audio into a raw 16-bit PCM mono or stereo stream which we simply can call preparation of Stream, that takes some times depending on size of sound file. And if we try to play the sound before that process is over, we get "sample x not ready" error.

There are two solutions for this

  1. implement setOnLoadCompleteListener or
  2. wait arbitrary amount of time so that preparation is over

and then play it Note that there is no exception for this condition or application is not crashing without any try-catch

于 2011-08-05T10:23:37.920 回答
2
private SoundPool soundPool;
private int my_sound;
boolean loaded = false;

// In the constructor

soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
my_sound = soundPool.load(this, R.raw.blast_sound, 1);

soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
    public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
       loaded = true;
    }
});

// then where ever you want to play the sound, type

if (loaded) {
soundPool.play(my_sound,  0.9f, 0.9f, 1, 0, 1f);
}
于 2012-08-13T08:22:21.173 回答
2

I solved with problem with simple do-while cicle. The method play() return non-zero streamID if successful, zero if failed. So, it's sufficient to check the return value.

int streamID = -1;
do {
    streamID = soundPool.play(soundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
} while(streamID==0);
于 2012-09-23T08:37:26.203 回答
2

This would work for you definitely !

public void playWavFile() {

    Thread streamThread = new Thread(new Runnable() {           

        @Override
        public void run() {                 
            SoundPool soundPool;
            final int wav;
            String path = "/mnt/sdcard/AudioRecorder/record.wav";
            soundPool = new SoundPool(5,AudioManager.STREAM_MUSIC, 0);
            wav = soundPool.load(path, 1);
            soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
                @Override
                public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                    // TODO Auto-generated method stub
                    soundPool.play(wav,100, 100, 0, 0, 1f);
                }
            });

        }        
    });

    streamThread.start();
}   
于 2013-10-31T16:48:22.757 回答
1

This sounds crazy, but don't play sounds right away. Give your app a couple of seconds to initialize the SoundPool. In my app, this was exactly the issue; I added a fake "loading" screen of ~3 seconds, and then everything worked. (I didn't even need to preload the sounds.)

于 2012-03-24T11:26:03.413 回答