I am making an Android game where I need to implement lag-free sound effects when the player interacts with a game object. To keep it simple, the objects are moving around on the screen and the player must tap them in order to trigger a sound effect. The issue I am having is that when the player taps many objects in a short amount of time, there is a noticeable delay between each sound effect. So for example, the player taps object 1, sound plays, taps object 2, sound plays, and keeps going until the player taps object n, the sound plays but sounds a bit delayed from previous sound effects that played.
I tried to set my SoundPool objects to load different sounds from the same resource but it didn't seem to do much. So is there a way for each iterations of the sound effect to overlap or even stop the previous iteration of the sound effect to be replaced by the new one without experiencing a noticeable delay in sound? Below is my code:
protected SoundPool mSoundPool;
protected boolean mLoaded;
protected int mBalloonPopStreams = 5;
protected int[] mSoundIds;
protected int mSoundIdx = 0;
protected void initializeMedia() {
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
mSoundPool = new SoundPool(mBalloonPopStreams, AudioManager.STREAM_MUSIC, 0);
mSoundIds = new int[mBalloonPopStreams];
for (int i = 0; i < mBalloonPopStreams; i++) {
mSoundIds[i] = mSoundPool.load(this, R.raw.sound_effect, 1);
}
mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
mLoaded = true;
}
});
}
protected OnTouchListener mTouchEvent = new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
int action = arg1.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
int pointerId = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int x;
int y;
x = (int)arg1.getX(pointerId);
y = (int)arg1.getY(pointerId);
if (actionCode == MotionEvent.ACTION_DOWN || actionCode == MotionEvent.ACTION_POINTER_DOWN) {
// Check if the player tapped a game object
playSound();
}
return true;
}
};
public void playSound() {
if (mLoaded) {
synchronized(mSoundPool) {
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
float actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = actualVolume / maxVolume;
mSoundPool.play(mSoundIds[mSoundIdx], volume, volume, 1, 0, 1f);
mSoundIdx = ++mSoundIdx % mBalloonPopStreams;
}
}
}
To sum it up, the problem is that, let's say 5 "pop" sounds are to be played within 1 second. I hear the popping sounds play 5 times but they are delayed and out of sync with what's actually going on in the game. Could this be a limitation on hardware? If not, then have I implemented my code incorrectly? What are some workarounds to this problem?