aboutsummaryrefslogtreecommitdiffstats
path: root/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/AudioRemixer.java
diff options
context:
space:
mode:
Diffstat (limited to 'libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/AudioRemixer.java')
-rw-r--r--libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/AudioRemixer.java66
1 files changed, 66 insertions, 0 deletions
diff --git a/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/AudioRemixer.java b/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/AudioRemixer.java
new file mode 100644
index 000000000..5255a2219
--- /dev/null
+++ b/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/AudioRemixer.java
@@ -0,0 +1,66 @@
+package net.ypresto.androidtranscoder.engine;
+
+import java.nio.ShortBuffer;
+
+public interface AudioRemixer {
+ void remix(final ShortBuffer inSBuff, final ShortBuffer outSBuff);
+
+ AudioRemixer DOWNMIX = new AudioRemixer() {
+ private static final int SIGNED_SHORT_LIMIT = 32768;
+ private static final int UNSIGNED_SHORT_MAX = 65535;
+
+ @Override
+ public void remix(final ShortBuffer inSBuff, final ShortBuffer outSBuff) {
+ // Down-mix stereo to mono
+ // Viktor Toth's algorithm -
+ // See: http://www.vttoth.com/CMS/index.php/technical-notes/68
+ // http://stackoverflow.com/a/25102339
+ final int inRemaining = inSBuff.remaining() / 2;
+ final int outSpace = outSBuff.remaining();
+
+ final int samplesToBeProcessed = Math.min(inRemaining, outSpace);
+ for (int i = 0; i < samplesToBeProcessed; ++i) {
+ // Convert to unsigned
+ final int a = inSBuff.get() + SIGNED_SHORT_LIMIT;
+ final int b = inSBuff.get() + SIGNED_SHORT_LIMIT;
+ int m;
+ // Pick the equation
+ if ((a < SIGNED_SHORT_LIMIT) || (b < SIGNED_SHORT_LIMIT)) {
+ // Viktor's first equation when both sources are "quiet"
+ // (i.e. less than middle of the dynamic range)
+ m = a * b / SIGNED_SHORT_LIMIT;
+ } else {
+ // Viktor's second equation when one or both sources are loud
+ m = 2 * (a + b) - (a * b) / SIGNED_SHORT_LIMIT - UNSIGNED_SHORT_MAX;
+ }
+ // Convert output back to signed short
+ if (m == UNSIGNED_SHORT_MAX + 1) m = UNSIGNED_SHORT_MAX;
+ outSBuff.put((short) (m - SIGNED_SHORT_LIMIT));
+ }
+ }
+ };
+
+ AudioRemixer UPMIX = new AudioRemixer() {
+ @Override
+ public void remix(final ShortBuffer inSBuff, final ShortBuffer outSBuff) {
+ // Up-mix mono to stereo
+ final int inRemaining = inSBuff.remaining();
+ final int outSpace = outSBuff.remaining() / 2;
+
+ final int samplesToBeProcessed = Math.min(inRemaining, outSpace);
+ for (int i = 0; i < samplesToBeProcessed; ++i) {
+ final short inSample = inSBuff.get();
+ outSBuff.put(inSample);
+ outSBuff.put(inSample);
+ }
+ }
+ };
+
+ AudioRemixer PASSTHROUGH = new AudioRemixer() {
+ @Override
+ public void remix(final ShortBuffer inSBuff, final ShortBuffer outSBuff) {
+ // Passthrough
+ outSBuff.put(inSBuff);
+ }
+ };
+}