在精确的时间内使用SoundPool(钢琴和弦)播放三个或更多短音频。

6
我有一个问题,我想同时启动声音。我循环播放3-5个短的声音(钢琴声),第一个声音延迟1毫秒,第二个声音延迟17毫秒,以此类推,最后一个声音延迟60-90毫秒。我正在使用SoundPool。是否有人遇到过这样的问题,或者使用过可以解决这个问题的库(同步启动多个短声音)?以下是示例测试样本(我使用RxJava进行测试,但我已经进行了测试,无论是否使用RxJava都一样)。
   Observable.timer(150, TimeUnit.MILLISECONDS, Schedulers.single())
            .repeat()
            .subscribe(aLong -> {
                for (int soundId = 55; i < 60; i++) {
                    soundPool.play(soundId , 1f, 1f, 1, 0, 1);
                }
            });
1个回答

0

看起来你需要实现监听器(OnLoadCompleteListener)。根据文档,SoundPool异步加载音频文件,我相信这就是你遇到延迟的原因。

在这里找到了一个可行的三个声音的示例here

public class SoundManager {

    public static int SOUNDPOOLSND_MENU_BTN         = 0;
    public static int SOUNDPOOLSND_WIN              = 1;
    public static int SOUNDPOOLSND_LOOSE            = 2;
    public static int SOUNDPOOLSND_DRAW             = 3;
    public static int SOUNDPOOLSND_TICK1            = 4;
    public static int SOUNDPOOLSND_TICK2            = 5;
    public static int SOUNDPOOLSND_OUT_OF_TIME      = 6;
    public static int SOUNDPOOLSND_HISCORE          = 7;
    public static int SOUNDPOOLSND_CORRECT_LETTER   = 8;

    public static boolean isSoundTurnedOff;

    private static SoundManager mSoundManager;

    private SoundPool mSoundPool; 
    private SparseArray <Integer> mSoundPoolMap; 
    private AudioManager  mAudioManager;

    public static final int maxSounds = 4;

    public static SoundManager getInstance(Context context)
    {
        if (mSoundManager == null){
            mSoundManager = new SoundManager(context);
        }

        return mSoundManager;
   }

    public SoundManager(Context mContext)
    {
        mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
        mSoundPool = new SoundPool(maxSounds, AudioManager.STREAM_MUSIC, 0);

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

        mSoundPoolMap = new SparseArray<Integer>(); 
        mSoundPoolMap.put(SOUNDPOOLSND_MENU_BTN, mSoundPool.load(mContext, R.raw.menubutton, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_WIN, mSoundPool.load(mContext, R.raw.win, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_LOOSE, mSoundPool.load(mContext, R.raw.lose, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_TICK1, mSoundPool.load(mContext, R.raw.tick_0, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_TICK2, mSoundPool.load(mContext, R.raw.tick_1, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_OUT_OF_TIME, mSoundPool.load(mContext, R.raw.out_of_time, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_HISCORE, mSoundPool.load(mContext, R.raw.personal_highscore, 1));
        mSoundPoolMap.put(SOUNDPOOLSND_CORRECT_LETTER, mSoundPool.load(mContext, R.raw.correct_letter, 1));

        // testing simultaneous playing
        int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 
        mSoundPool.play(mSoundPoolMap.get(0), streamVolume, streamVolume, 1, 20, 1f); 
        mSoundPool.play(mSoundPoolMap.get(1), streamVolume, streamVolume, 1, 2, 1f);
        mSoundPool.play(mSoundPoolMap.get(2), streamVolume, streamVolume, 1, 0, 1f);


    } 

    public void playSound(int index) { 
        if (isSoundTurnedOff)
            return;

         int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 
         mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f); 
    }

    public static void clear()
    {
        if (mSoundManager != null){
            mSoundManager.mSoundPool = null; 
            mSoundManager.mAudioManager = null;
            mSoundManager.mSoundPoolMap = null;
        }
        mSoundManager = null;
    }
}

声音已经加载,我认为可能是线程/同步问题。 - Wrobel
是的,我在网上看到过这样的解决方案,人们使用两个线程并尝试将它们同步以实现两个声音,但这看起来不太对。 - Rainmaker
另一种方法是混合声音并将其作为一个播放,这也是常见的解决方案。 - Rainmaker
我已经测试了多个解决方案,我认为我必须尝试使用NDK和OpenSL ES来开发Android应用。 - Wrobel
如果您正在使用原始的PCM-16位样本,则可以尝试使用AudioTrack。它很容易使用,只需同时对所有样本求和,并尝试通过削波或应用小于1的增益(简单乘法)来限制输出,以避免削波。这样,您可以将所有音频使用单个音频输出,否则您的系统必须为您执行此操作,即将所有音频输出混合为一个输出。 - Diljeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接