6

I have a problem, I want to start sound in the same time.

I play 3-5 short sound in loop (piano sounds), and I have delay on first 1ms, on second 17ms, and so on, up to 60-90ms on last sound.

I am using SoundPool.

Anyone have a problem like this or had used library which can solve this problem (start multiple short sounds in sync)?

Below is example test sample (I use RxJava but I have tested it with and without 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);
                }
            });
Wrobel
  • 1,042
  • 12
  • 21

1 Answers1

0

It seems like you need to implement listener (OnLoadCompleteListener). SoundPool loads audio files asynchronously as it is stated in the docs so I believe this is why you get your delay.

Found this working example for 3 sounds 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;
    }
}
Rainmaker
  • 10,294
  • 9
  • 54
  • 89
  • Sounds are already loaded, I think it's maybe a threading/syncing problem – Wrobel Dec 13 '17 at 07:37
  • Yah, I saw such a solution on the net that people use two threads and try to sync them for two sounds , but it doesn't looke right – Rainmaker Dec 13 '17 at 07:50
  • The other way round it is to mix the sounds and play it as one, it is also a common solution – Rainmaker Dec 13 '17 at 07:51
  • I,ve testing multiple solution and I think i must try NDK with OpenSL ES for Android – Wrobel Dec 13 '17 at 08:05
  • if you are using raw PCM-16 bit samples, you can try AudioTrack its simple to use, just sum all samples playing simultaneously and try to limit the output by clipping or applying gain less than 1(by multiplying simply) to avoid clipping. This way you can use a single audio output for all audio, otherwise your system has to do that for you, i.e. mixing all audio output to one. – Diljeet Dec 13 '17 at 21:02