Android AudioTrack MODE_STATIC重播问题

时间:2011-05-18 18:16:50

标签: java android audio

我有一个AudioTrack的问题,这个Android API正在扼杀我。我来自没有以前的Android或Java经验,但我是一个非常有经验的编码器(asm,C ++等在许多平台上),我从未想过我特别愚蠢,就像Android现在肯定让我感觉到的那样。

我做错了什么?显然没有:

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minbufsizbytes*64, AudioTrack.MODE_STATIC);
audioTrack.write(Buffer, 0, numSamples);
audioTrack.play();

实际上sampleRate = 8000和minbufsizbytes = 742,其中(742 * 64 = 47488)比我写的Buffer(16000 16bit样本)大得多。

第一次音频播放得很好。但是......我如何不止一次地玩它? (例如,响应于诸如按下的钢琴键之类的事件)。如果我再次调用play(),则不会产生新的声音。经过几天的挫折之后,这就是我的想法:

for (i=0;;i++) {
   SystemClock.sleep(3000L); // so the problem is NOT "fast, repeated attempts to replay sound", but looks like internal buffer overrun related (please see the Log'ed error below)
   audioTrack.stop();
   audioTrack.reloadStaticData();
   audioTrack.setPlaybackHeadPosition(0);
   audioTrack.play();
}

所以它第三次播放声音(!)然后是NO AUDIO !!并且日志被这个错误消息所淹没:

05-18 13:03:16.785: ERROR/AudioFlinger(345): TrackBase::getBuffer buffer out of range:
05-18 13:03:16.785: ERROR/AudioFlinger(345):     start: 0x404fb680, end 0x404fb7f2 , mBuffer 0x40507000 mBufferEnd 0x40512980
05-18 13:03:16.785: ERROR/AudioFlinger(345):                     server 0, serverBase 23744, user 47488, userBase 47488, channels 1

然后我必须重新启动手机(模拟或真实),否则日志洪水不会停止..

(mis)在我的Galaxy 2.2.1,我的IDEOS 2.1和模拟器(各种版本)上行为......所以这不是手机错误问题。

如果我将内部缓冲区放大(AudioTrack中的第5个参数),它会在停止发出声音并开始充斥日志之前播放更多次,所以我认为这就像是内部缓冲区是否超过

P.S。:你知道getMinBufferSize是否会返回样本或字节(即使是PCM_16BIT),正如有些人报道的那样?

1 个答案:

答案 0 :(得分:5)

这是一个已运行多次的代码示例! 'super'是一个AudioTrack

public void play(){

    switch (super.getPlayState()) {
    case AudioTrack.PLAYSTATE_PAUSED:
    super.stop();
        super.reloadStaticData();
        super.play();
        break;
    case AudioTrack.PLAYSTATE_PLAYING:
    super.stop();
        super.reloadStaticData();
        super.play();
        break;
    case AudioTrack.PLAYSTATE_STOPPED:
        super.reloadStaticData();
        super.play();
        break;
    }

}