Android 声音池样本未准备好

Android 声音池样本未准备好,android,soundpool,Android,Soundpool,我有一个.wav文件,我想在我的游戏中使用,目前我正在游戏中每个活动的onCreate()中加载声音 soundCount = soundpool.load(this,R.raw.count, 1); 活动开始后将播放声音 soundpool.play(soundCount, 0.9f, 0.9f, 1, -1, 1f); 问题是有时我会遇到错误“示例x未就绪”。 是否可以在游戏开始时加载一次.wav文件并将其保存在内存中,然后在整个游戏中使用它?或者可以等待1-2秒声音加载完成吗?您

我有一个.wav文件,我想在我的游戏中使用,目前我正在游戏中每个活动的
onCreate()
中加载声音

 soundCount = soundpool.load(this,R.raw.count, 1);
活动开始后将播放声音

  soundpool.play(soundCount, 0.9f, 0.9f, 1, -1, 1f);
问题是有时我会遇到错误
“示例x未就绪”

是否可以在游戏开始时加载一次.wav文件并将其保存在内存中,然后在整个游戏中使用它?或者可以等待1-2秒声音加载完成吗?

您需要通过
声音池添加一个监听器来等待声音加载完成。setOnLoadCompleteListener

由于我的项目与Android 1.5兼容,而且我不能使用setOnLoadCompleteListener,所以我决定延迟播放声音。 我的源代码如下:

    playSound_Delayed(soundId, 100);
//(……)


SoundPool库使用MediaPlayer服务将音频解码为原始的16位PCM单声道或立体声流,我们可以简单地称之为流的准备,这需要一些时间,具体取决于声音文件的大小。如果我们试图在这个过程结束之前播放声音,我们会得到“样本x未准备好”错误

有两种解决方案

  • 实现setOnLoadCompleteListener或
  • 等待任意时间,以便准备工作结束
  • 然后播放它
    请注意,这种情况没有例外,或者应用程序在没有任何try-catch的情况下不会崩溃

    如果可能,您应该使用setOnLoadCompleteListener。。。如果没有,请围绕“播放”调用循环一段时间。比如:

    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);}
    
    int waitLimit=1000;
    int waitCounter=0;
    int节流阀=10;
    while(soundPool.play(soundId,1.f,1.f,1,0,1.f)==0&&waitCounter

    这将以10毫秒的间隔重试“播放”1000次。当然,这应该在非ui线程上运行,但仍然不理想。但也许比等待一个任意的时间,期待游泳池准备好要强烈一点

    这听起来很疯狂,但不要马上播放声音。给你的应用几秒钟来初始化声音池。在我的应用程序中,这正是问题所在;我添加了一个约3秒的假“加载”屏幕,然后一切正常。(我甚至不需要预先加载声音。)

    //在构造函数中

    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;
        }
    });
    
    //然后,无论你想在哪里播放声音,键入

    if (loaded) {
    soundPool.play(my_sound,  0.9f, 0.9f, 1, 0, 1f);
    }
    

    我用简单的方法解决了这个问题。方法play()如果成功,则返回非零的streamID,如果失败,则返回零。因此,检查返回值就足够了

    int streamID = -1;
    do {
        streamID = soundPool.play(soundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
    } while(streamID==0);
    

    这绝对适合你

    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();
    }   
    

    不幸的是,setOnLoadCompleteListener在API 8之前不可用:(除了使用setOnLoadCompleteListener之外,还有其他众所周知的解决方案吗?/Thanks不完全在主题中,但您可能想用Log.w替换System.err.println,以便在LogCatSystem上显示它。实际上,err.println会在logcat中显示System.err标记。但我同意Log.w是干净的,这就是我正在做的但我觉得它真的很烦人。游戏在一秒钟内加载。加载屏幕只是为了声音的缘故才在那里。@W.K.S我也是。我有一个想法,把加载屏幕变成一个迷你游戏,或者在其中加入一点互动性作为“复活节彩蛋”之类的东西,即使它只在几秒钟内可见。
    int streamID = -1;
    do {
        streamID = soundPool.play(soundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
    } while(streamID==0);
    
    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();
    }