【问题标题】:Soundpool sample not readySoundpool 样品未准备好
【发布时间】:2011-07-09 07:40:09
【问题描述】:

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

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

活动开始后将播放声音。

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

问题是有时我会遇到错误"sample x not ready"。 是否可以在开始游戏时加载 .wav 文件并将其保存在内存中并稍后在整个游戏中使用?或者是否可以等待 1-2 秒让声音加载完成?

【问题讨论】:

    标签: android soundpool


    【解决方案1】:

    您需要通过SoundPool.setOnLoadCompleteListener 添加侦听器来等待它完成。

    【讨论】:

    • 不幸的是,在 API 8 之前 setOnLoadCompleteListener 不可用 :( 除了使用 setOnLoadCompleteListener 之外,还有其他众所周知的解决方案吗?/谢谢
    【解决方案2】:

    由于我的项目与 Android 1.5 兼容并且我无法使用 setOnLoadCompleteListener,因此我解决了延迟播放声音的问题。 我的源代码如下:

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

    【讨论】:

    • 不完全是主题,但您可能想用 Log.w 替换 System.err.println 以便在 LogCat 上显示它
    • System.err.println 确实出现在 logcat 中,带有 System.err 标签,实际上。但我同意 Log.w 更干净
    【解决方案3】:

    如果可能,您应该使用 setOnLoadCompleteListener ... 如果没有,请在您对“播放”的调用周围环绕一个 while 循环。类似:

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

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

    【讨论】:

      【解决方案4】:

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

      有两种解决方案

      1. 实现 setOnLoadCompleteListener 或
      2. 等待任意时间以便准备结束

      然后播放 请注意,这种情况也不例外,或者应用程序在没有任何 try-catch 的情况下不会崩溃

      【讨论】:

        【解决方案5】:
        private SoundPool soundPool;
        private int my_sound;
        boolean loaded = false;
        

        //在构造函数中

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

        【讨论】:

          【解决方案6】:

          我用简单的 do-while cicle 解决了问题。如果成功,方法 play() 返回非零流 ID,如果失败则返回零。所以,检查返回值就足够了。

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

          【讨论】:

            【解决方案7】:

            这绝对适合你!

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

            【讨论】:

              【解决方案8】:

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

              【讨论】:

              • 这就是我正在做的,但我觉得它真的很烦人。游戏在一秒钟内加载。加载屏幕只是为了声音。
              • @W.K.S 我也是。我有一个想法,将加载屏幕制作成一个小游戏,或者在其中添加一些交互性作为“复活节彩蛋”之类的东西,即使它只显示几秒钟。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多