【问题标题】:Android implementing simultaneous sound effectsAndroid 实现同步音效
【发布时间】:2012-08-28 11:30:56
【问题描述】:

我正在制作一个 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;   
        }
    }
}

总而言之,问题在于,假设要在 1 秒内播放 5 个“流行”声音。我听到爆裂声播放了 5 次,但它们被延迟并且与游戏中实际发生的情况不同步。这可能是对硬件的限制吗?如果不是,那么我是否错误地实现了我的代码?这个问题有哪些解决方法?

【问题讨论】:

    标签: java android


    【解决方案1】:

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

    【讨论】:

    • 这并没有完全解决我的问题。可杀队列没有做任何有意义的事情,因为我的音效很短。我对 SoundPool 对象的担忧是它是否允许同时播放音轨,即每个音效是否在单独的线程上播放?
    【解决方案2】:

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

    【讨论】:

      最近更新 更多