Android's AudioTrack MODE_STATIC replay issues
I have an issue with AudioTrack, this Android API is killing me. I come from no previous Android or Java experience, but I'm a very experienced coder (asm, C++, etc.. on a lot of platforms) and I never thought I was particularly dumb, like Android is certainly making me feel now.
What am I doing wrong? Apparently nothing:
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();
Actually sampleRate=8000 and minbufsizbytes=742, which (742*64 = 47488) is considerably bigger than the Buffer I'm writing (16000 16bit samples).
The audio plays just fine the first time. But... how do I play it more than once? (e.g. in response to an event, like e.g. a piano key pressed). If I invoke play() again, no new sound will be produced. So after days of frustration, here's what I came up:
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();
}
So it plays the sound a second OR(!) third time.. then NO AUDIO!! And the Log gets flooded by this error message:
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
I then must reboot the phone (emulated or real) else the Log flood do开发者_Go百科esn't stop..
(mis)Behaves on my Galaxy 2.2.1, on my IDEOS 2.1 and on the emulator (various versions).. so it's not a phone bug issue.
If I make the internal buffer bigger (5th parameter in AudioTrack), it will play more times before it stops emitting sounds and starts flooding the Log, so I think it's like if an internal buffer was overran
P.S.: do you know if getMinBufferSize returns samples or bytes (even for PCM_16BIT), as some have reported?
Here is a sample of code that had run several times!! 'super' is an 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;
}
}
精彩评论