Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 doesn'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?

like image 947
Fabio Avatar asked May 18 '11 18:05

Fabio


1 Answers

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

}

like image 122
Arnsiou Avatar answered Oct 17 '22 00:10

Arnsiou