Merge "Change the heuristics for waiting for audiotracks to finish."

This commit is contained in:
Narayan Kamath
2011-08-31 03:53:03 -07:00
committed by Android (Google) Code Review
2 changed files with 42 additions and 3 deletions

View File

@@ -415,6 +415,9 @@ class AudioPlaybackHandler {
}
if (params.mBytesWritten < params.mAudioBufferSize) {
if (DBG) Log.d(TAG, "Stopping audio track to flush audio, state was : " +
audioTrack.getPlayState());
params.mIsShortUtterance = true;
audioTrack.stop();
}
@@ -452,10 +455,40 @@ class AudioPlaybackHandler {
return;
}
if (params.mIsShortUtterance) {
// In this case we would have called AudioTrack#stop() to flush
// buffers to the mixer. This makes the playback head position
// unobservable and notification markers do not work reliably. We
// have no option but to wait until we think the track would finish
// playing and release it after.
//
// This isn't as bad as it looks because (a) We won't end up waiting
// for much longer than we should because even at 4khz mono, a short
// utterance weighs in at about 2 seconds, and (b) such short utterances
// are expected to be relatively infrequent and in a stream of utterances
// this shows up as a slightly longer pause.
blockUntilEstimatedCompletion(params);
} else {
blockUntilCompletion(params);
}
}
private static void blockUntilEstimatedCompletion(SynthesisMessageParams params) {
final int lengthInFrames = params.mBytesWritten / params.mBytesPerFrame;
final long estimatedTimeMs = (lengthInFrames * 1000 / params.mSampleRateInHz);
if (DBG) Log.d(TAG, "About to sleep for: " + estimatedTimeMs + "ms for a short utterance");
try {
Thread.sleep(estimatedTimeMs);
} catch (InterruptedException ie) {
// Do nothing.
}
}
private static void blockUntilCompletion(SynthesisMessageParams params) {
final AudioTrack audioTrack = params.mAudioTrack;
final int bytesPerFrame = params.mBytesPerFrame;
final int lengthInBytes = params.mBytesWritten;
final int lengthInFrames = lengthInBytes / bytesPerFrame;
final int lengthInFrames = params.mBytesWritten / params.mBytesPerFrame;
int currentPosition = 0;
while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) {

View File

@@ -41,7 +41,13 @@ final class SynthesisMessageParams extends MessageParams {
// Written by the synthesis thread, but read on the audio playback
// thread.
volatile int mBytesWritten;
// A "short utterance" is one that uses less bytes than the audio
// track buffer size (mAudioBufferSize). In this case, we need to call
// AudioTrack#stop() to send pending buffers to the mixer, and slightly
// different logic is required to wait for the track to finish.
//
// Not volatile, accessed only from the audio playback thread.
boolean mIsShortUtterance;
int mAudioBufferSize;
// Always synchronized on "this".
int mUnconsumedBytes;