Simplify buffer resizing in Sonic

This is in preparation for making it possible to flush a Sonic instance so that
it's not necessary to create new ones every time the processor is flushed.

There should be no behavior changes here.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=191410326
This commit is contained in:
andrewlewis 2018-04-03 01:35:01 -07:00 committed by Oliver Woodman
parent 8b5a34769f
commit 53eae50c0c

View File

@ -41,17 +41,14 @@ import java.util.Arrays;
private final int maxRequiredFrameCount; private final int maxRequiredFrameCount;
private final short[] downSampleBuffer; private final short[] downSampleBuffer;
private int inputBufferSizeFrames;
private short[] inputBuffer; private short[] inputBuffer;
private int outputBufferSize; private int inputFrameCount;
private short[] outputBuffer; private short[] outputBuffer;
private int pitchBufferSize; private int outputFrameCount;
private short[] pitchBuffer; private short[] pitchBuffer;
private int pitchFrameCount;
private int oldRatePosition; private int oldRatePosition;
private int newRatePosition; private int newRatePosition;
private int inputFrameCount;
private int outputFrameCount;
private int pitchFrameCount;
private int remainingInputToCopyFrameCount; private int remainingInputToCopyFrameCount;
private int prevPeriod; private int prevPeriod;
private int prevMinDiff; private int prevMinDiff;
@ -71,22 +68,16 @@ import java.util.Arrays;
int inputSampleRateHz, int channelCount, float speed, float pitch, int outputSampleRateHz) { int inputSampleRateHz, int channelCount, float speed, float pitch, int outputSampleRateHz) {
this.inputSampleRateHz = inputSampleRateHz; this.inputSampleRateHz = inputSampleRateHz;
this.channelCount = channelCount; this.channelCount = channelCount;
this.speed = speed;
this.pitch = pitch;
rate = (float) inputSampleRateHz / outputSampleRateHz;
minPeriod = inputSampleRateHz / MAXIMUM_PITCH; minPeriod = inputSampleRateHz / MAXIMUM_PITCH;
maxPeriod = inputSampleRateHz / MINIMUM_PITCH; maxPeriod = inputSampleRateHz / MINIMUM_PITCH;
maxRequiredFrameCount = 2 * maxPeriod; maxRequiredFrameCount = 2 * maxPeriod;
downSampleBuffer = new short[maxRequiredFrameCount]; downSampleBuffer = new short[maxRequiredFrameCount];
inputBufferSizeFrames = maxRequiredFrameCount;
inputBuffer = new short[maxRequiredFrameCount * channelCount]; inputBuffer = new short[maxRequiredFrameCount * channelCount];
outputBufferSize = maxRequiredFrameCount;
outputBuffer = new short[maxRequiredFrameCount * channelCount]; outputBuffer = new short[maxRequiredFrameCount * channelCount];
pitchBufferSize = maxRequiredFrameCount;
pitchBuffer = new short[maxRequiredFrameCount * channelCount]; pitchBuffer = new short[maxRequiredFrameCount * channelCount];
oldRatePosition = 0;
newRatePosition = 0;
prevPeriod = 0;
this.speed = speed;
this.pitch = pitch;
this.rate = (float) inputSampleRateHz / outputSampleRateHz;
} }
/** /**
@ -98,7 +89,7 @@ import java.util.Arrays;
public void queueInput(ShortBuffer buffer) { public void queueInput(ShortBuffer buffer) {
int framesToWrite = buffer.remaining() / channelCount; int framesToWrite = buffer.remaining() / channelCount;
int bytesToWrite = framesToWrite * channelCount * 2; int bytesToWrite = framesToWrite * channelCount * 2;
enlargeInputBufferIfNeeded(framesToWrite); inputBuffer = ensureSpaceForAdditionalFrames(inputBuffer, inputFrameCount, framesToWrite);
buffer.get(inputBuffer, inputFrameCount * channelCount, bytesToWrite / 2); buffer.get(inputBuffer, inputFrameCount * channelCount, bytesToWrite / 2);
inputFrameCount += framesToWrite; inputFrameCount += framesToWrite;
processStreamInput(); processStreamInput();
@ -134,7 +125,9 @@ import java.util.Arrays;
outputFrameCount + (int) ((remainingFrameCount / s + pitchFrameCount) / r + 0.5f); outputFrameCount + (int) ((remainingFrameCount / s + pitchFrameCount) / r + 0.5f);
// Add enough silence to flush both input and pitch buffers. // Add enough silence to flush both input and pitch buffers.
enlargeInputBufferIfNeeded(remainingFrameCount + 2 * maxRequiredFrameCount); inputBuffer =
ensureSpaceForAdditionalFrames(
inputBuffer, inputFrameCount, remainingFrameCount + 2 * maxRequiredFrameCount);
for (int xSample = 0; xSample < 2 * maxRequiredFrameCount * channelCount; xSample++) { for (int xSample = 0; xSample < 2 * maxRequiredFrameCount * channelCount; xSample++) {
inputBuffer[remainingFrameCount * channelCount + xSample] = 0; inputBuffer[remainingFrameCount * channelCount + xSample] = 0;
} }
@ -157,17 +150,24 @@ import java.util.Arrays;
// Internal methods. // Internal methods.
private void enlargeOutputBufferIfNeeded(int frameCount) { /**
if (outputFrameCount + frameCount > outputBufferSize) { * Returns {@code buffer} or a copy of it, such that there is enough space in the returned buffer
outputBufferSize += (outputBufferSize / 2) + frameCount; * to store {@code newFrameCount} additional frames.
outputBuffer = Arrays.copyOf(outputBuffer, outputBufferSize * channelCount); *
} * @param buffer The buffer.
} * @param frameCount The number of frames already in the buffer.
* @param additionalFrameCount The number of additional frames that need to be stored in the
private void enlargeInputBufferIfNeeded(int frameCount) { * buffer.
if (inputFrameCount + frameCount > inputBufferSizeFrames) { * @return A buffer with enough space for the additional frames.
inputBufferSizeFrames += (inputBufferSizeFrames / 2) + frameCount; */
inputBuffer = Arrays.copyOf(inputBuffer, inputBufferSizeFrames * channelCount); private short[] ensureSpaceForAdditionalFrames(
short[] buffer, int frameCount, int additionalFrameCount) {
int currentCapacityFrames = buffer.length / channelCount;
if (frameCount + additionalFrameCount <= currentCapacityFrames) {
return buffer;
} else {
int newCapacityFrames = 3 * currentCapacityFrames / 2 + additionalFrameCount;
return Arrays.copyOf(buffer, newCapacityFrames * channelCount);
} }
} }
@ -179,7 +179,7 @@ import java.util.Arrays;
} }
private void copyToOutput(short[] samples, int positionFrames, int frameCount) { private void copyToOutput(short[] samples, int positionFrames, int frameCount) {
enlargeOutputBufferIfNeeded(frameCount); outputBuffer = ensureSpaceForAdditionalFrames(outputBuffer, outputFrameCount, frameCount);
System.arraycopy( System.arraycopy(
samples, samples,
positionFrames * channelCount, positionFrames * channelCount,
@ -306,10 +306,7 @@ import java.util.Arrays;
private void moveNewSamplesToPitchBuffer(int originalOutputFrameCount) { private void moveNewSamplesToPitchBuffer(int originalOutputFrameCount) {
int frameCount = outputFrameCount - originalOutputFrameCount; int frameCount = outputFrameCount - originalOutputFrameCount;
if (pitchFrameCount + frameCount > pitchBufferSize) { pitchBuffer = ensureSpaceForAdditionalFrames(pitchBuffer, pitchFrameCount, frameCount);
pitchBufferSize += (pitchBufferSize / 2) + frameCount;
pitchBuffer = Arrays.copyOf(pitchBuffer, pitchBufferSize * channelCount);
}
System.arraycopy( System.arraycopy(
outputBuffer, outputBuffer,
originalOutputFrameCount * channelCount, originalOutputFrameCount * channelCount,
@ -359,7 +356,9 @@ import java.util.Arrays;
// Leave at least one pitch sample in the buffer. // Leave at least one pitch sample in the buffer.
for (int position = 0; position < pitchFrameCount - 1; position++) { for (int position = 0; position < pitchFrameCount - 1; position++) {
while ((oldRatePosition + 1) * newSampleRate > newRatePosition * oldSampleRate) { while ((oldRatePosition + 1) * newSampleRate > newRatePosition * oldSampleRate) {
enlargeOutputBufferIfNeeded(1); outputBuffer =
ensureSpaceForAdditionalFrames(
outputBuffer, outputFrameCount, /* additionalFrameCount= */ 1);
for (int i = 0; i < channelCount; i++) { for (int i = 0; i < channelCount; i++) {
outputBuffer[outputFrameCount * channelCount + i] = outputBuffer[outputFrameCount * channelCount + i] =
interpolate(pitchBuffer, position * channelCount + i, oldSampleRate, newSampleRate); interpolate(pitchBuffer, position * channelCount + i, oldSampleRate, newSampleRate);
@ -386,7 +385,7 @@ import java.util.Arrays;
newFrameCount = period; newFrameCount = period;
remainingInputToCopyFrameCount = (int) (period * (2.0f - speed) / (speed - 1.0f)); remainingInputToCopyFrameCount = (int) (period * (2.0f - speed) / (speed - 1.0f));
} }
enlargeOutputBufferIfNeeded(newFrameCount); outputBuffer = ensureSpaceForAdditionalFrames(outputBuffer, outputFrameCount, newFrameCount);
overlapAdd( overlapAdd(
newFrameCount, newFrameCount,
channelCount, channelCount,
@ -409,7 +408,8 @@ import java.util.Arrays;
newFrameCount = period; newFrameCount = period;
remainingInputToCopyFrameCount = (int) (period * (2.0f * speed - 1.0f) / (1.0f - speed)); remainingInputToCopyFrameCount = (int) (period * (2.0f * speed - 1.0f) / (1.0f - speed));
} }
enlargeOutputBufferIfNeeded(period + newFrameCount); outputBuffer =
ensureSpaceForAdditionalFrames(outputBuffer, outputFrameCount, period + newFrameCount);
System.arraycopy( System.arraycopy(
samples, samples,
position * channelCount, position * channelCount,