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

Posted

技术标签:

【中文标题】在静态模式下使用 AudioTrack 的正确方法是啥?【英文标题】:What is the proper way to use AudioTrack in static mode?在静态模式下使用 AudioTrack 的正确方法是什么? 【发布时间】:2012-07-11 18:02:43 【问题描述】:

我有一个需要播放短声音的 android 游戏。 SoundPool 在dual 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();
    


然后,当我需要播放声音时,我将其发送到 ThreadPool。

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

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

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

我希望看到不涉及流式音频的 AudioTrack 示例代码。

【问题讨论】:

【参考方案1】:

我在 Google 办公时间问了这个问题。他们说 AudioTrack 与 SoundPool 有相同的错误。这个问题的唯一解决方案是编写一个原生媒体播放器。虽然,这个问题似乎只影响运行 Gingerbread 的双核手机。

【讨论】:

以上是关于在静态模式下使用 AudioTrack 的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Android音频系统AudioTrack使用方法详解

Android音视频使用opensles和audiotrack进行播放pcm

Android音视频使用opensles和audiotrack进行播放pcm

在 Heroku 上部署 Django/静态文件的正确方法

AudioTrack 采样率不一致

Python 如何正确使用静态方法和类方法?