Merge "Change the heuristics for waiting for audiotracks to finish."
This commit is contained in:
committed by
Android (Google) Code Review
commit
5b8f29d077
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user