mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Scale AudioTrack buffer size for AudioTrack speed adjustment
PiperOrigin-RevId: 326642908
This commit is contained in:
parent
eabc486b58
commit
977f0d1ed0
2 changed files with 31 additions and 30 deletions
|
|
@ -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 {
|
||||||
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 {
|
||||||
*/
|
*/
|
||||||
@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 {
|
||||||
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 {
|
||||||
|
|
||||||
@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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
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 {
|
||||||
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;
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
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 {
|
||||||
* @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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue