java - 在静态模式下使用 AudioTrack 的正确方法是什么?

标签 java android multithreading audio

我有一个 Android 游戏,我需要播放简短的声音。 SoundPooldual core phones 上崩溃, Mediaplayer延迟高达 200 毫秒以上,OpenSL 需要 SDK 9+(我支持 1.5)。这样就剩下AudioTrack .

这是我试过的。我这样创建 AudioTrack 对象。

protected AudioTrack createAudioTrack() {
    final int trackSize = 17408;
    return new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT, trackSize, AudioTrack.MODE_STATIC);
}

然后我为每个游戏声音创建一个可运行的(大约 8 个)。

private static class SoundRunnable implements Runnable {

    private final AudioTrack sound;
    private final byte[] rawAudio;

    public SoundRunnable(final AudioTrack sound, final byte[] rawAudio){
        this.sound = sound;
        this.rawAudio = rawAudio;
        sound.write(rawAudio, 0, rawAudio.length);
    }

    @Override
    public void run() {
        playSound();
    }

    private synchronized void playSound() {
        switch (sound.getPlayState()) {
        case AudioTrack.PLAYSTATE_PAUSED:
            sound.stop();
            sound.reloadStaticData();
            sound.play();
        break;
        case AudioTrack.PLAYSTATE_PLAYING:
            sound.stop();
            sound.reloadStaticData();
            sound.play();
        break;
        case AudioTrack.PLAYSTATE_STOPPED:
            sound.reloadStaticData();
            sound.play();
        break;
        default:
            break;
        }
    }   

    public synchronized void release() {
        sound.release();
    }

}

然后,当我需要播放声音时,我将它发送到线程池。

private void playSound(final int soundToPlay) {
    final SoundRunnable soundRunnable = mediaPlayers.get(soundToPlay);
    if(soundRunnable != null){
        threadPool.execute(soundRunnable);
    }
}

我遇到的主要问题是在我第一次执行 runnable 时声音会播放两次。之后每隔一段时间我仍然会听到双重声音,但效果很好。

我还尝试过在流模式下创建单个 AudioTrack 并从可运行文件中写入原始音频。这有点成功,但很难知道何时停止回放。如果你提前停下来,声音就会被切断,太晚了,你会得到一个 obtainBuffer 错误,应用程序会被锁定。同时播放两种声音也很困难(可以使用 AudioTracks 池)。

我很乐意看到不涉及流式音频的 AudioTrack 示例代码。

最佳答案

我在 Google 办公时间问过这个问题。他们说 AudioTrack 有和 SoundPool 一样的 bug。解决这个问题的唯一方法是编写一个本地媒体播放器。虽然,这个问题似乎只影响运行 Gingerbread 的双核手机。

关于java - 在静态模式下使用 AudioTrack 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11438671/

相关文章:

java - 在 Android 应用程序的标签中解析 HTML 中的 JSON

objective-c - 是 performSelector :onThread:withObject:waitUntilDone: ordered?

android - 在 Android 中保存同一个 Activity 的多个实例状态

android - E/SQLiteLog : (1) no such table: Cars on Android 9 Pie

C++ 持有多个线程

multithreading - Parallel.ForEach 已过时。老了,过时了?

java - 如何使用几个线程完成大量作业,并为每个线程提供相同的超时完成时间?

java - 如何在不使用强制转换的情况下选择要调用的方法的重载版本?

java - 通过 jdbc 获取 Oracle DB LONG 类型的速度非常慢

java - 将值从存储在 HashMap 中的列表添加到新列表时遇到问题 - Java