Android实现同步音效

时间:2011-11-16 04:29:00

标签: java android

我正在制作一款Android游戏,当玩家与游戏对象互动时,我需要实现无滞后音效。为了简单起见,对象在屏幕上移动,播放器必须点击它们才能触发声音效果。我遇到的问题是当玩家在很短的时间内点击很多物体时,每个声音效果之间会有明显的延迟。因此,例如,玩家点击对象1,声音播放,点击对象2,声音播放,并继续前进,直到玩家点击对象n,声音播放但听起来比先前播放的声音效果有点延迟。

我尝试将我的SoundPool对象设置为从同一资源加载不同的声音,但似乎没有做太多。那么,是否有一种方法可以使声音效果的每次迭代重叠甚至停止声音效果的前一次迭代,以便在不经历明显的声音延迟的情况下被新声音效果替换?以下是我的代码:

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

总结一下,问题在于,假设5秒钟内将播放5个“pop”声音。我听到弹出的声音播放了5次但是它们被延迟并且与游戏中实际发生的事情不同步。这可能是对硬件的限制吗?如果没有,那么我是否错误地实现了我的代码?这个问题有哪些解决方法?

2 个答案:

答案 0 :(得分:0)

This answer对类似的问题可能有所帮助。该问题的OP是他们的应用程序崩溃,如果他们试图用SoundPool播放多个声音,但它可能是同一问题的不同症状。

答案 1 :(得分:0)

您可以使用AudioTrack而不是SoundPool获得更好的结果,代价是您需要更多代码。