Commit 977f0d1e by andrewlewis Committed by kim-vde

Scale AudioTrack buffer size for AudioTrack speed adjustment

PiperOrigin-RevId: 326642908
parent eabc486b
...@@ -191,6 +191,16 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -191,6 +191,16 @@ public final class DefaultAudioSink implements AudioSink {
} }
} }
/** The default playback speed. */
public static final float DEFAULT_PLAYBACK_SPEED = 1f;
/** The minimum allowed playback speed. Lower values will be constrained to fall in range. */
public static final float MIN_PLAYBACK_SPEED = 0.1f;
/** The maximum allowed playback speed. Higher values will be constrained to fall in range. */
public static final float MAX_PLAYBACK_SPEED = 8f;
/** The default skip silence flag. */
private static final boolean DEFAULT_SKIP_SILENCE = false;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({OUTPUT_MODE_PCM, OUTPUT_MODE_OFFLOAD, OUTPUT_MODE_PASSTHROUGH}) @IntDef({OUTPUT_MODE_PCM, OUTPUT_MODE_OFFLOAD, OUTPUT_MODE_PASSTHROUGH})
...@@ -210,11 +220,10 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -210,11 +220,10 @@ public final class DefaultAudioSink implements AudioSink {
private static final long OFFLOAD_BUFFER_DURATION_US = 50_000_000; private static final long OFFLOAD_BUFFER_DURATION_US = 50_000_000;
/** /**
* A multiplication factor to apply to the minimum buffer size requested by the underlying * A multiplication factor to apply to the minimum buffer size requested by the underlying {@link
* {@link AudioTrack}. * AudioTrack}.
*/ */
private static final int BUFFER_MULTIPLICATION_FACTOR = 4; private static final int BUFFER_MULTIPLICATION_FACTOR = 4;
/** To avoid underruns on some devices (e.g., Broadcom 7271), scale up the AC3 buffer duration. */ /** To avoid underruns on some devices (e.g., Broadcom 7271), scale up the AC3 buffer duration. */
private static final int AC3_BUFFER_MULTIPLICATION_FACTOR = 2; private static final int AC3_BUFFER_MULTIPLICATION_FACTOR = 2;
...@@ -239,10 +248,6 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -239,10 +248,6 @@ public final class DefaultAudioSink implements AudioSink {
*/ */
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
private static final int WRITE_NON_BLOCKING = AudioTrack.WRITE_NON_BLOCKING; private static final int WRITE_NON_BLOCKING = AudioTrack.WRITE_NON_BLOCKING;
/** The default playback speed. */
private static final float DEFAULT_PLAYBACK_SPEED = 1f;
/** The default skip silence flag. */
private static final boolean DEFAULT_SKIP_SILENCE = false;
private static final String TAG = "AudioTrack"; private static final String TAG = "AudioTrack";
...@@ -582,6 +587,7 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -582,6 +587,7 @@ public final class DefaultAudioSink implements AudioSink {
outputChannelConfig, outputChannelConfig,
outputEncoding, outputEncoding,
specifiedBufferSize, specifiedBufferSize,
enableAudioTrackPlaybackParams,
canApplyPlaybackParameters, canApplyPlaybackParameters,
availableAudioProcessors); availableAudioProcessors);
if (isAudioTrackInitialized()) { if (isAudioTrackInitialized()) {
...@@ -1007,6 +1013,7 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1007,6 +1013,7 @@ public final class DefaultAudioSink implements AudioSink {
@Override @Override
public void setPlaybackSpeed(float playbackSpeed) { public void setPlaybackSpeed(float playbackSpeed) {
playbackSpeed = Util.constrainValue(playbackSpeed, MIN_PLAYBACK_SPEED, MAX_PLAYBACK_SPEED);
if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) { if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) {
setAudioTrackPlaybackSpeedV23(playbackSpeed); setAudioTrackPlaybackSpeedV23(playbackSpeed);
} else { } else {
...@@ -1802,6 +1809,7 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1802,6 +1809,7 @@ public final class DefaultAudioSink implements AudioSink {
int outputChannelConfig, int outputChannelConfig,
int outputEncoding, int outputEncoding,
int specifiedBufferSize, int specifiedBufferSize,
boolean enableAudioTrackPlaybackParams,
boolean canApplyPlaybackParameters, boolean canApplyPlaybackParameters,
AudioProcessor[] availableAudioProcessors) { AudioProcessor[] availableAudioProcessors) {
this.inputFormat = inputFormat; this.inputFormat = inputFormat;
...@@ -1815,7 +1823,7 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1815,7 +1823,7 @@ public final class DefaultAudioSink implements AudioSink {
this.availableAudioProcessors = availableAudioProcessors; this.availableAudioProcessors = availableAudioProcessors;
// Call computeBufferSize() last as it depends on the other configuration values. // Call computeBufferSize() last as it depends on the other configuration values.
this.bufferSize = computeBufferSize(specifiedBufferSize); this.bufferSize = computeBufferSize(specifiedBufferSize, enableAudioTrackPlaybackParams);
} }
/** Returns if the configurations are sufficiently compatible to reuse the audio track. */ /** Returns if the configurations are sufficiently compatible to reuse the audio track. */
...@@ -1925,13 +1933,15 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1925,13 +1933,15 @@ public final class DefaultAudioSink implements AudioSink {
} }
} }
private int computeBufferSize(int specifiedBufferSize) { private int computeBufferSize(
int specifiedBufferSize, boolean enableAudioTrackPlaybackParameters) {
if (specifiedBufferSize != 0) { if (specifiedBufferSize != 0) {
return specifiedBufferSize; return specifiedBufferSize;
} }
switch (outputMode) { switch (outputMode) {
case OUTPUT_MODE_PCM: case OUTPUT_MODE_PCM:
return getPcmDefaultBufferSize(); return getPcmDefaultBufferSize(
enableAudioTrackPlaybackParameters ? MAX_PLAYBACK_SPEED : DEFAULT_PLAYBACK_SPEED);
case OUTPUT_MODE_OFFLOAD: case OUTPUT_MODE_OFFLOAD:
return getEncodedDefaultBufferSize(OFFLOAD_BUFFER_DURATION_US); return getEncodedDefaultBufferSize(OFFLOAD_BUFFER_DURATION_US);
case OUTPUT_MODE_PASSTHROUGH: case OUTPUT_MODE_PASSTHROUGH:
...@@ -1949,7 +1959,7 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1949,7 +1959,7 @@ public final class DefaultAudioSink implements AudioSink {
return (int) (bufferDurationUs * rate / C.MICROS_PER_SECOND); return (int) (bufferDurationUs * rate / C.MICROS_PER_SECOND);
} }
private int getPcmDefaultBufferSize() { private int getPcmDefaultBufferSize(float maxAudioTrackPlaybackSpeed) {
int minBufferSize = int minBufferSize =
AudioTrack.getMinBufferSize(outputSampleRate, outputChannelConfig, outputEncoding); AudioTrack.getMinBufferSize(outputSampleRate, outputChannelConfig, outputEncoding);
Assertions.checkState(minBufferSize != ERROR_BAD_VALUE); Assertions.checkState(minBufferSize != ERROR_BAD_VALUE);
...@@ -1957,7 +1967,13 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1957,7 +1967,13 @@ public final class DefaultAudioSink implements AudioSink {
int minAppBufferSize = (int) durationUsToFrames(MIN_BUFFER_DURATION_US) * outputPcmFrameSize; int minAppBufferSize = (int) durationUsToFrames(MIN_BUFFER_DURATION_US) * outputPcmFrameSize;
int maxAppBufferSize = int maxAppBufferSize =
max(minBufferSize, (int) durationUsToFrames(MAX_BUFFER_DURATION_US) * outputPcmFrameSize); max(minBufferSize, (int) durationUsToFrames(MAX_BUFFER_DURATION_US) * outputPcmFrameSize);
return Util.constrainValue(multipliedBufferSize, minAppBufferSize, maxAppBufferSize); int bufferSize =
Util.constrainValue(multipliedBufferSize, minAppBufferSize, maxAppBufferSize);
if (maxAudioTrackPlaybackSpeed != 1f) {
// Maintain the buffer duration by scaling the size accordingly.
bufferSize = Math.round(bufferSize * maxAudioTrackPlaybackSpeed);
}
return bufferSize;
} }
@RequiresApi(21) @RequiresApi(21)
......
...@@ -29,22 +29,10 @@ import java.nio.ShortBuffer; ...@@ -29,22 +29,10 @@ import java.nio.ShortBuffer;
*/ */
public final class SonicAudioProcessor implements AudioProcessor { public final class SonicAudioProcessor implements AudioProcessor {
/** /** Indicates that the output sample rate should be the same as the input. */
* The maximum allowed playback speed in {@link #setSpeed(float)}.
*/
public static final float MAXIMUM_SPEED = 8.0f;
/**
* The minimum allowed playback speed in {@link #setSpeed(float)}.
*/
public static final float MINIMUM_SPEED = 0.1f;
/**
* Indicates that the output sample rate should be the same as the input.
*/
public static final int SAMPLE_RATE_NO_CHANGE = -1; public static final int SAMPLE_RATE_NO_CHANGE = -1;
/** /** The threshold below which the difference between two pitch/speed factors is negligible. */
* The threshold below which the difference between two pitch/speed factors is negligible.
*/
private static final float CLOSE_THRESHOLD = 0.01f; private static final float CLOSE_THRESHOLD = 0.01f;
/** /**
...@@ -70,9 +58,7 @@ public final class SonicAudioProcessor implements AudioProcessor { ...@@ -70,9 +58,7 @@ public final class SonicAudioProcessor implements AudioProcessor {
private long outputBytes; private long outputBytes;
private boolean inputEnded; private boolean inputEnded;
/** /** Creates a new Sonic audio processor. */
* Creates a new Sonic audio processor.
*/
public SonicAudioProcessor() { public SonicAudioProcessor() {
speed = 1f; speed = 1f;
pendingInputAudioFormat = AudioFormat.NOT_SET; pendingInputAudioFormat = AudioFormat.NOT_SET;
...@@ -94,7 +80,6 @@ public final class SonicAudioProcessor implements AudioProcessor { ...@@ -94,7 +80,6 @@ public final class SonicAudioProcessor implements AudioProcessor {
* @return The actual new playback speed. * @return The actual new playback speed.
*/ */
public float setSpeed(float speed) { public float setSpeed(float speed) {
speed = Util.constrainValue(speed, MINIMUM_SPEED, MAXIMUM_SPEED);
if (this.speed != speed) { if (this.speed != speed) {
this.speed = speed; this.speed = speed;
pendingSonicRecreation = true; pendingSonicRecreation = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment