简体   繁体   English

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

[英]What is the proper way to use AudioTrack in static mode?

I have an Android game that I need to play short sounds. 我有一个Android游戏,我需要播放短音。 SoundPool crashes on dual core phones , Mediaplayer has up to 200ms+ delays, OpenSL requires SDK 9+ (I support 1.5). SoundPool双核手机上崩溃, Mediaplayer200毫秒+延迟,OpenSL需要SDK 9+(我支持1.5)。 So that leaves AudioTrack . 这就离开了AudioTrack

This is what I have tried. 这就是我尝试过的。 I create the AudioTrack objects like this. 我像这样创建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);
}

I then create a runnable for each in game sound (about 8). 然后我在游戏声音(约8)中为每个创建一个runnable。

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

}

Then when I need to play the sound I send it to a ThreadPool. 然后,当我需要播放声音时,我将它发送到ThreadPool。

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

The main issue I have is that sounds play twice the first time I execute the runnable. 我遇到的主要问题是,第一次执行runnable时声音会播放两次。 After that every once in a while I still might get a double sound but it works pretty well. 在那之后每隔一段时间我仍然会得到一个双重声音,但它的效果非常好。

I have also experimented with creating a single AudioTrack in streaming mode and writing raw audio from the runnables. 我还尝试在流模式下创建单个AudioTrack并从runnables编写原始音频。 This was somewhat successfull but was difficult to know when to stop the play back. 这有点成功,但很难知道何时停止播放。 I you stop to early the sound is cut short, too late and you get an obtainBuffer error and the app locks up. 我你早点停止声音被缩短,太晚了,你得到一个gainBuffer错误,应用程序锁定。 Also playing two sounds at the same time is difficult (could possiblly use a pool of AudioTracks). 同时播放两个声音也很困难(可能会使用AudioTracks池)。

I would love to see sample code for AudioTrack that doesn't involve streaming audio. 我很想看到AudioTrack的示例代码,它不涉及流式音频。

I asked this question during Google office hours. 我在谷歌办公时间问了这个问题。 They said that AudioTrack has the same bug as SoundPool. 他们说AudioTrack与SoundPool有同样的错误。 The only solution to this problem is to write a native media player. 解决此问题的唯一方法是编写本机媒体播放器。 Although, this issue does only seem to effect Dual Core phones running Gingerbread. 虽然,这个问题似乎只影响运行Gingerbread的双核手机。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM