summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java134
1 files changed, 134 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java
new file mode 100644
index 0000000000..efd8a30d61
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ResamplingAudioProcessor.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mozilla.thirdparty.com.google.android.exoplayer2.audio;
+
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.Format;
+import java.nio.ByteBuffer;
+
+/**
+ * An {@link AudioProcessor} that converts different PCM audio encodings to 16-bit integer PCM. The
+ * following encodings are supported as input:
+ *
+ * <ul>
+ * <li>{@link C#ENCODING_PCM_8BIT}
+ * <li>{@link C#ENCODING_PCM_16BIT} ({@link #isActive()} will return {@code false})
+ * <li>{@link C#ENCODING_PCM_16BIT_BIG_ENDIAN}
+ * <li>{@link C#ENCODING_PCM_24BIT}
+ * <li>{@link C#ENCODING_PCM_32BIT}
+ * <li>{@link C#ENCODING_PCM_FLOAT}
+ * </ul>
+ */
+/* package */ final class ResamplingAudioProcessor extends BaseAudioProcessor {
+
+ @Override
+ public AudioFormat onConfigure(AudioFormat inputAudioFormat)
+ throws UnhandledAudioFormatException {
+ @C.PcmEncoding int encoding = inputAudioFormat.encoding;
+ if (encoding != C.ENCODING_PCM_8BIT
+ && encoding != C.ENCODING_PCM_16BIT
+ && encoding != C.ENCODING_PCM_16BIT_BIG_ENDIAN
+ && encoding != C.ENCODING_PCM_24BIT
+ && encoding != C.ENCODING_PCM_32BIT
+ && encoding != C.ENCODING_PCM_FLOAT) {
+ throw new UnhandledAudioFormatException(inputAudioFormat);
+ }
+ return encoding != C.ENCODING_PCM_16BIT
+ ? new AudioFormat(
+ inputAudioFormat.sampleRate, inputAudioFormat.channelCount, C.ENCODING_PCM_16BIT)
+ : AudioFormat.NOT_SET;
+ }
+
+ @Override
+ public void queueInput(ByteBuffer inputBuffer) {
+ // Prepare the output buffer.
+ int position = inputBuffer.position();
+ int limit = inputBuffer.limit();
+ int size = limit - position;
+ int resampledSize;
+ switch (inputAudioFormat.encoding) {
+ case C.ENCODING_PCM_8BIT:
+ resampledSize = size * 2;
+ break;
+ case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
+ resampledSize = size;
+ break;
+ case C.ENCODING_PCM_24BIT:
+ resampledSize = (size / 3) * 2;
+ break;
+ case C.ENCODING_PCM_32BIT:
+ case C.ENCODING_PCM_FLOAT:
+ resampledSize = size / 2;
+ break;
+ case C.ENCODING_PCM_16BIT:
+ case C.ENCODING_INVALID:
+ case Format.NO_VALUE:
+ default:
+ throw new IllegalStateException();
+ }
+
+ // Resample the little endian input and update the input/output buffers.
+ ByteBuffer buffer = replaceOutputBuffer(resampledSize);
+ switch (inputAudioFormat.encoding) {
+ case C.ENCODING_PCM_8BIT:
+ // 8 -> 16 bit resampling. Shift each byte from [0, 256) to [-128, 128) and scale up.
+ for (int i = position; i < limit; i++) {
+ buffer.put((byte) 0);
+ buffer.put((byte) ((inputBuffer.get(i) & 0xFF) - 128));
+ }
+ break;
+ case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
+ // Big endian to little endian resampling. Swap the byte order.
+ for (int i = position; i < limit; i += 2) {
+ buffer.put(inputBuffer.get(i + 1));
+ buffer.put(inputBuffer.get(i));
+ }
+ break;
+ case C.ENCODING_PCM_24BIT:
+ // 24 -> 16 bit resampling. Drop the least significant byte.
+ for (int i = position; i < limit; i += 3) {
+ buffer.put(inputBuffer.get(i + 1));
+ buffer.put(inputBuffer.get(i + 2));
+ }
+ break;
+ case C.ENCODING_PCM_32BIT:
+ // 32 -> 16 bit resampling. Drop the two least significant bytes.
+ for (int i = position; i < limit; i += 4) {
+ buffer.put(inputBuffer.get(i + 2));
+ buffer.put(inputBuffer.get(i + 3));
+ }
+ break;
+ case C.ENCODING_PCM_FLOAT:
+ // 32 bit floating point -> 16 bit resampling. Floating point values are in the range
+ // [-1.0, 1.0], so need to be scaled by Short.MAX_VALUE.
+ for (int i = position; i < limit; i += 4) {
+ short value = (short) (inputBuffer.getFloat(i) * Short.MAX_VALUE);
+ buffer.put((byte) (value & 0xFF));
+ buffer.put((byte) ((value >> 8) & 0xFF));
+ }
+ break;
+ case C.ENCODING_PCM_16BIT:
+ case C.ENCODING_INVALID:
+ case Format.NO_VALUE:
+ default:
+ // Never happens.
+ throw new IllegalStateException();
+ }
+ inputBuffer.position(inputBuffer.limit());
+ buffer.flip();
+ }
+
+}