NeoWang
NeoWang

Reputation: 18513

How to correctly pause AudioTrack and resume playing smoothly?

I am using Android's AudioTrack to play a PCM file recorded earlier. If I don't pause while playing, everything is fine; but if I pause and resume, a large chunk of audio (about 1 second) is skipped. Here is my code:

// Player thread
audioTrack = new AudioTrack(
                    AudioManager.STREAM_MUSIC,
                    RECORDER_SAMPLERATE,
                    AudioFormat.CHANNEL_OUT_MONO,
                    RECORDER_AUDIO_ENCODING,
                    bufferSize,
                    AudioTrack.MODE_STREAM);

audioTrack.play();

FileInputStream is = null;
try {
    is = new FileInputStream(filePath);
} catch (FileNotFoundException e){
    e.printStackTrace();
    return;
}

byte[] buffer = new byte[bufferSize];
int offset = 0;

while (true) {
    if(paused) { continue;}

    int cnt = 0;
    try {
       cnt = is.read(buffer, 0, bufferSize);
    } catch (IOException e){
       e.printStackTrace();
    }
    if(cnt < 0) break;
    audioTrack.write(buffer, 0, cnt);
    audioTrack.play();
}
audioTrack.release();

And here is code to pause and resume playing:

public void pause(){
    this.paused = true;
    audioTrack.pause();
}

public void resume(){
    this.paused = false;
}

What goes wrong? What is the correct way to do pause?

Upvotes: 0

Views: 1744

Answers (1)

greeble31
greeble31

Reputation: 5042

Most likely, write is returning a short transfer count. According to the documentation

...if the track is stopped or paused on entry... then the write may return a short transfer count.

Your code does not address this edge case, therefor it's likely that an entire buffer's worth of audio is simply being dropped.

A simple solution might be to attempt a second write, immediately after the play(), but only in the event the first write returns a short count. This second write would need to account for exactly those bytes that were not written during the first write.

Upvotes: 1

Related Questions