mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add clipFloatOutput parameter to AudioMixer
PiperOrigin-RevId: 615720340
This commit is contained in:
parent
ca6031deab
commit
3248b7962a
@ -70,6 +70,8 @@ public final class AudioMixingUtil {
|
|||||||
* @param matrix Scaled channel mapping from input to output.
|
* @param matrix Scaled channel mapping from input to output.
|
||||||
* @param framesToMix Number of audio frames to mix. Must be within the bounds of both buffers.
|
* @param framesToMix Number of audio frames to mix. Must be within the bounds of both buffers.
|
||||||
* @param accumulate Whether to accumulate with the existing samples in the mixing buffer.
|
* @param accumulate Whether to accumulate with the existing samples in the mixing buffer.
|
||||||
|
* @param clipFloatOutput Whether to clip the output signal to be in the [-1.0, 1.0] range if the
|
||||||
|
* output encoding is {@link C#ENCODING_PCM_FLOAT}.
|
||||||
* @return The {@code mixingBuffer}, for convenience.
|
* @return The {@code mixingBuffer}, for convenience.
|
||||||
*/
|
*/
|
||||||
public static ByteBuffer mix(
|
public static ByteBuffer mix(
|
||||||
@ -79,7 +81,8 @@ public final class AudioMixingUtil {
|
|||||||
AudioFormat mixingAudioFormat,
|
AudioFormat mixingAudioFormat,
|
||||||
ChannelMixingMatrix matrix,
|
ChannelMixingMatrix matrix,
|
||||||
int framesToMix,
|
int framesToMix,
|
||||||
boolean accumulate) {
|
boolean accumulate,
|
||||||
|
boolean clipFloatOutput) {
|
||||||
|
|
||||||
boolean int16Input = inputAudioFormat.encoding == C.ENCODING_PCM_16BIT;
|
boolean int16Input = inputAudioFormat.encoding == C.ENCODING_PCM_16BIT;
|
||||||
boolean int16Output = mixingAudioFormat.encoding == C.ENCODING_PCM_16BIT;
|
boolean int16Output = mixingAudioFormat.encoding == C.ENCODING_PCM_16BIT;
|
||||||
@ -114,7 +117,10 @@ public final class AudioMixingUtil {
|
|||||||
(short) constrainValue(outputFrame[outputChannel], Short.MIN_VALUE, Short.MAX_VALUE));
|
(short) constrainValue(outputFrame[outputChannel], Short.MIN_VALUE, Short.MAX_VALUE));
|
||||||
} else {
|
} else {
|
||||||
mixingBuffer.putFloat(
|
mixingBuffer.putFloat(
|
||||||
constrainValue(outputFrame[outputChannel], FLOAT_PCM_MIN_VALUE, FLOAT_PCM_MAX_VALUE));
|
clipFloatOutput
|
||||||
|
? constrainValue(
|
||||||
|
outputFrame[outputChannel], FLOAT_PCM_MIN_VALUE, FLOAT_PCM_MAX_VALUE)
|
||||||
|
: outputFrame[outputChannel]);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputFrame[outputChannel] = 0;
|
outputFrame[outputChannel] = 0;
|
||||||
|
@ -85,7 +85,8 @@ public final class ChannelMixingAudioProcessor extends BaseAudioProcessor {
|
|||||||
outputAudioFormat,
|
outputAudioFormat,
|
||||||
channelMixingMatrix,
|
channelMixingMatrix,
|
||||||
framesToMix,
|
framesToMix,
|
||||||
/* accumulate= */ false);
|
/* accumulate= */ false,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
outputBuffer.flip();
|
outputBuffer.flip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_FLOAT,
|
STEREO_44100_PCM_FLOAT,
|
||||||
STEREO_TO_STEREO.scaleBy(0.5f),
|
STEREO_TO_STEREO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -81,7 +82,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_FLOAT,
|
STEREO_44100_PCM_FLOAT,
|
||||||
MONO_TO_STEREO.scaleBy(0.5f),
|
MONO_TO_STEREO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -108,7 +110,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_FLOAT,
|
STEREO_44100_PCM_FLOAT,
|
||||||
STEREO_TO_STEREO.scaleBy(0.5f),
|
STEREO_TO_STEREO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -132,7 +135,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_FLOAT,
|
STEREO_44100_PCM_FLOAT,
|
||||||
MONO_TO_STEREO.scaleBy(0.5f),
|
MONO_TO_STEREO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -155,7 +159,8 @@ public final class AudioMixingUtilTest {
|
|||||||
MONO_44100_PCM_FLOAT,
|
MONO_44100_PCM_FLOAT,
|
||||||
STEREO_TO_MONO.scaleBy(0.5f),
|
STEREO_TO_MONO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -175,7 +180,8 @@ public final class AudioMixingUtilTest {
|
|||||||
MONO_44100_PCM_FLOAT,
|
MONO_44100_PCM_FLOAT,
|
||||||
MONO_TO_MONO.scaleBy(0.5f),
|
MONO_TO_MONO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -202,7 +208,8 @@ public final class AudioMixingUtilTest {
|
|||||||
MONO_44100_PCM_FLOAT,
|
MONO_44100_PCM_FLOAT,
|
||||||
STEREO_TO_MONO.scaleBy(0.5f),
|
STEREO_TO_MONO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -226,7 +233,8 @@ public final class AudioMixingUtilTest {
|
|||||||
MONO_44100_PCM_FLOAT,
|
MONO_44100_PCM_FLOAT,
|
||||||
MONO_TO_MONO.scaleBy(0.5f),
|
MONO_TO_MONO.scaleBy(0.5f),
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -250,7 +258,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_16BIT,
|
STEREO_44100_PCM_16BIT,
|
||||||
MONO_TO_STEREO,
|
MONO_TO_STEREO,
|
||||||
/* framesToMix= */ 3,
|
/* framesToMix= */ 3,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -272,7 +281,8 @@ public final class AudioMixingUtilTest {
|
|||||||
MONO_44100_PCM_16BIT,
|
MONO_44100_PCM_16BIT,
|
||||||
MONO_TO_MONO,
|
MONO_TO_MONO,
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer")
|
assertWithMessage("Mixing buffer")
|
||||||
@ -304,7 +314,8 @@ public final class AudioMixingUtilTest {
|
|||||||
MONO_44100_PCM_16BIT,
|
MONO_44100_PCM_16BIT,
|
||||||
MONO_TO_MONO,
|
MONO_TO_MONO,
|
||||||
/* framesToMix= */ 4,
|
/* framesToMix= */ 4,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -328,7 +339,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_16BIT,
|
STEREO_44100_PCM_16BIT,
|
||||||
STEREO_TO_STEREO,
|
STEREO_TO_STEREO,
|
||||||
/* framesToMix= */ 3,
|
/* framesToMix= */ 3,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
@ -350,7 +362,8 @@ public final class AudioMixingUtilTest {
|
|||||||
STEREO_44100_PCM_16BIT,
|
STEREO_44100_PCM_16BIT,
|
||||||
STEREO_TO_STEREO,
|
STEREO_TO_STEREO,
|
||||||
/* framesToMix= */ 2,
|
/* framesToMix= */ 2,
|
||||||
/* accumulate= */ false);
|
/* accumulate= */ false,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
assertWithMessage("Source buffer")
|
assertWithMessage("Source buffer")
|
||||||
.that(sourceBuffer.remaining())
|
.that(sourceBuffer.remaining())
|
||||||
@ -362,4 +375,46 @@ public final class AudioMixingUtilTest {
|
|||||||
mixingBuffer.rewind();
|
mixingBuffer.rewind();
|
||||||
assertThat(mixingBuffer).isEqualTo(expectedBuffer);
|
assertThat(mixingBuffer).isEqualTo(expectedBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mixToMonoFloat_withMonoFloatInput_withClipping() {
|
||||||
|
ByteBuffer mixingBuffer = createByteBuffer(new float[] {0.9f, -0.9f});
|
||||||
|
ByteBuffer sourceBuffer = createByteBuffer(new float[] {0.5f, -0.2f});
|
||||||
|
|
||||||
|
AudioMixingUtil.mix(
|
||||||
|
sourceBuffer,
|
||||||
|
MONO_44100_PCM_FLOAT,
|
||||||
|
mixingBuffer,
|
||||||
|
MONO_44100_PCM_FLOAT,
|
||||||
|
MONO_TO_MONO,
|
||||||
|
/* framesToMix= */ 2,
|
||||||
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
|
|
||||||
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
|
mixingBuffer.rewind();
|
||||||
|
assertThat(createFloatArray(mixingBuffer)).isEqualTo(new float[] {1f, -1f});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mixToMonoFloat_withMonoFloatInput_noClipping() {
|
||||||
|
ByteBuffer mixingBuffer = createByteBuffer(new float[] {0.9f, -0.9f});
|
||||||
|
ByteBuffer sourceBuffer = createByteBuffer(new float[] {0.5f, -0.2f});
|
||||||
|
|
||||||
|
AudioMixingUtil.mix(
|
||||||
|
sourceBuffer,
|
||||||
|
MONO_44100_PCM_FLOAT,
|
||||||
|
mixingBuffer,
|
||||||
|
MONO_44100_PCM_FLOAT,
|
||||||
|
MONO_TO_MONO,
|
||||||
|
/* framesToMix= */ 2,
|
||||||
|
/* accumulate= */ true,
|
||||||
|
/* clipFloatOutput= */ false);
|
||||||
|
|
||||||
|
assertWithMessage("Source buffer").that(sourceBuffer.remaining()).isEqualTo(0);
|
||||||
|
assertWithMessage("Mixing buffer").that(mixingBuffer.remaining()).isEqualTo(0);
|
||||||
|
mixingBuffer.rewind();
|
||||||
|
assertThat(createFloatArray(mixingBuffer)).isEqualTo(new float[] {1.4f, -1.1f});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,8 @@ public class WaveformAudioBufferSink implements TeeAudioProcessor.AudioBufferSin
|
|||||||
mixingAudioFormat,
|
mixingAudioFormat,
|
||||||
channelMixingMatrix,
|
channelMixingMatrix,
|
||||||
/* framesToMix= */ 1,
|
/* framesToMix= */ 1,
|
||||||
/* accumulate= */ false);
|
/* accumulate= */ false,
|
||||||
|
/* clipFloatOutput= */ true);
|
||||||
mixingBuffer.rewind();
|
mixingBuffer.rewind();
|
||||||
for (int i = 0; i < outputChannels.size(); i++) {
|
for (int i = 0; i < outputChannels.size(); i++) {
|
||||||
WaveformBar bar = outputChannels.get(i);
|
WaveformBar bar = outputChannels.get(i);
|
||||||
|
@ -64,7 +64,9 @@ public interface AudioMixer {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
static AudioMixer create() {
|
static AudioMixer create() {
|
||||||
return new DefaultAudioMixer.Factory(/* outputSilenceWithNoSources= */ true).create();
|
return new DefaultAudioMixer.Factory(
|
||||||
|
/* outputSilenceWithNoSources= */ true, /* clipFloatOutput= */ true)
|
||||||
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,20 +33,30 @@ import androidx.media3.common.util.Util;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
/** An {@link AudioMixer} that incrementally mixes source audio into a fixed size mixing buffer. */
|
/**
|
||||||
|
* An {@link AudioMixer} that incrementally mixes source audio into a fixed size mixing buffer.
|
||||||
|
*
|
||||||
|
* <p>By default, the output signal is guaranteed to be in the range corresponding to its encoding.
|
||||||
|
* This range is [{@link Short#MIN_VALUE}, {@link Short#MAX_VALUE}] for {@link
|
||||||
|
* C#ENCODING_PCM_16BIT}, and [-1.0, 1.0] for {@link C#ENCODING_PCM_FLOAT}. Before adding a value to
|
||||||
|
* the output buffer, it is first converted to the output encoding (in the corresponding range). It
|
||||||
|
* is then added to the output buffer value, and the result is clipped by moving it to the closest
|
||||||
|
* value in this range.
|
||||||
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final class DefaultAudioMixer implements AudioMixer {
|
public final class DefaultAudioMixer implements AudioMixer {
|
||||||
|
|
||||||
/** An {@link AudioMixer.Factory} implementation for {@link DefaultAudioMixer} instances. */
|
/** An {@link AudioMixer.Factory} implementation for {@link DefaultAudioMixer} instances. */
|
||||||
public static final class Factory implements AudioMixer.Factory {
|
public static final class Factory implements AudioMixer.Factory {
|
||||||
private final boolean outputSilenceWithNoSources;
|
private final boolean outputSilenceWithNoSources;
|
||||||
|
private final boolean clipFloatOutput;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance that does not {@linkplain #getOutput() output} silence when there are no
|
* Creates an instance. This is equivalent to {@link #Factory(boolean, boolean) new
|
||||||
* {@linkplain #addSource sources}.
|
* Factory(false, true)}.
|
||||||
*/
|
*/
|
||||||
public Factory() {
|
public Factory() {
|
||||||
this(/* outputSilenceWithNoSources= */ false);
|
this(/* outputSilenceWithNoSources= */ false, /* clipFloatOutput= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,20 +64,27 @@ public final class DefaultAudioMixer implements AudioMixer {
|
|||||||
*
|
*
|
||||||
* @param outputSilenceWithNoSources Whether to {@linkplain #getOutput() output} silence when
|
* @param outputSilenceWithNoSources Whether to {@linkplain #getOutput() output} silence when
|
||||||
* there are no {@linkplain #addSource sources}.
|
* there are no {@linkplain #addSource sources}.
|
||||||
|
* @param clipFloatOutput Whether to clip the output signal to be in the [-1.0, 1.0] range if
|
||||||
|
* the output encoding is {@link C#ENCODING_PCM_FLOAT}. This parameter is ignored for
|
||||||
|
* non-float output signals. For float output signals, non-float input signals are converted
|
||||||
|
* to float signals in the [-1.0, 1.0] range. All input signals (float or non-float) are
|
||||||
|
* then added and the result is clipped if and only if {@code clipFloatOutput} is true.
|
||||||
*/
|
*/
|
||||||
public Factory(boolean outputSilenceWithNoSources) {
|
public Factory(boolean outputSilenceWithNoSources, boolean clipFloatOutput) {
|
||||||
this.outputSilenceWithNoSources = outputSilenceWithNoSources;
|
this.outputSilenceWithNoSources = outputSilenceWithNoSources;
|
||||||
|
this.clipFloatOutput = clipFloatOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DefaultAudioMixer create() {
|
public DefaultAudioMixer create() {
|
||||||
return new DefaultAudioMixer(outputSilenceWithNoSources);
|
return new DefaultAudioMixer(outputSilenceWithNoSources, clipFloatOutput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/290002438, b/276734854): Improve buffer management & determine best default size.
|
// TODO(b/290002438, b/276734854): Improve buffer management & determine best default size.
|
||||||
private static final int DEFAULT_BUFFER_SIZE_MS = 500;
|
private static final int DEFAULT_BUFFER_SIZE_MS = 500;
|
||||||
|
|
||||||
|
private final boolean clipFloatOutput;
|
||||||
private final SparseArray<SourceInfo> sources;
|
private final SparseArray<SourceInfo> sources;
|
||||||
private int nextSourceId;
|
private int nextSourceId;
|
||||||
private AudioFormat outputAudioFormat;
|
private AudioFormat outputAudioFormat;
|
||||||
@ -90,7 +107,8 @@ public final class DefaultAudioMixer implements AudioMixer {
|
|||||||
*/
|
*/
|
||||||
private long maxPositionOfRemovedSources;
|
private long maxPositionOfRemovedSources;
|
||||||
|
|
||||||
private DefaultAudioMixer(boolean outputSilenceWithNoSources) {
|
private DefaultAudioMixer(boolean outputSilenceWithNoSources, boolean clipFloatOutput) {
|
||||||
|
this.clipFloatOutput = clipFloatOutput;
|
||||||
sources = new SparseArray<>();
|
sources = new SparseArray<>();
|
||||||
outputAudioFormat = AudioFormat.NOT_SET;
|
outputAudioFormat = AudioFormat.NOT_SET;
|
||||||
bufferSizeFrames = C.LENGTH_UNSET;
|
bufferSizeFrames = C.LENGTH_UNSET;
|
||||||
@ -338,7 +356,7 @@ public final class DefaultAudioMixer implements AudioMixer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Per-source information. */
|
/** Per-source information. */
|
||||||
private static class SourceInfo {
|
private final class SourceInfo {
|
||||||
/**
|
/**
|
||||||
* Position (in frames) of the next source audio frame to be input by the source, relative to
|
* Position (in frames) of the next source audio frame to be input by the source, relative to
|
||||||
* the mixer start.
|
* the mixer start.
|
||||||
@ -399,7 +417,8 @@ public final class DefaultAudioMixer implements AudioMixer {
|
|||||||
mixingAudioFormat,
|
mixingAudioFormat,
|
||||||
channelMixingMatrix,
|
channelMixingMatrix,
|
||||||
framesToMix,
|
framesToMix,
|
||||||
/* accumulate= */ true);
|
/* accumulate= */ true,
|
||||||
|
clipFloatOutput);
|
||||||
position = newPosition;
|
position = newPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,9 @@ public final class DefaultAudioMixerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
mixer = new DefaultAudioMixer.Factory(outputSilenceWithNoSources).create();
|
mixer =
|
||||||
|
new DefaultAudioMixer.Factory(outputSilenceWithNoSources, /* clipFloatOutput= */ true)
|
||||||
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user