Fix handling of channel count changes with speed adjustment

When using speed adjustment it was possible for playback to get stuck at a
period transition when the channel count changed: SonicAudioProcessor would be
drained at the point of the period transition in preparation for creating a new
AudioTrack with the new channel count, but during draining the incorrect (new)
channel count was used to calculate the output buffer size for pending data from
Sonic. This meant that, for example, if the channel count changed from stereo to
mono we could have an output buffer size that stored an non-integer number of
audio frames, and in turn this would cause writing to the AudioTrack to get
stuck as the AudioTrack would prevent writing a partial audio frame.

Use Sonic's current channel count when draining output to fix the issue.

PiperOrigin-RevId: 260156541
This commit is contained in:
andrewlewis 2019-07-26 17:20:45 +01:00 committed by Oliver Woodman
parent 9c41bcfe24
commit 6f7b765a1c
2 changed files with 6 additions and 5 deletions

View file

@ -30,6 +30,7 @@ import java.util.Arrays;
private static final int MINIMUM_PITCH = 65;
private static final int MAXIMUM_PITCH = 400;
private static final int AMDF_FREQUENCY = 4000;
private static final int BYTES_PER_SAMPLE = 2;
private final int inputSampleRateHz;
private final int channelCount;
@ -157,9 +158,9 @@ import java.util.Arrays;
maxDiff = 0;
}
/** Returns the number of output frames that can be read with {@link #getOutput(ShortBuffer)}. */
public int getFramesAvailable() {
return outputFrameCount;
/** Returns the size of output that can be read with {@link #getOutput(ShortBuffer)}, in bytes. */
public int getOutputSize() {
return outputFrameCount * channelCount * BYTES_PER_SAMPLE;
}
// Internal methods.

View file

@ -210,7 +210,7 @@ public final class SonicAudioProcessor implements AudioProcessor {
sonic.queueInput(shortBuffer);
inputBuffer.position(inputBuffer.position() + inputSize);
}
int outputSize = sonic.getFramesAvailable() * channelCount * 2;
int outputSize = sonic.getOutputSize();
if (outputSize > 0) {
if (buffer.capacity() < outputSize) {
buffer = ByteBuffer.allocateDirect(outputSize).order(ByteOrder.nativeOrder());
@ -243,7 +243,7 @@ public final class SonicAudioProcessor implements AudioProcessor {
@Override
public boolean isEnded() {
return inputEnded && (sonic == null || sonic.getFramesAvailable() == 0);
return inputEnded && (sonic == null || sonic.getOutputSize() == 0);
}
@Override