summaryrefslogtreecommitdiffstats
path: root/media/libeffects/downmix
diff options
context:
space:
mode:
authorJean-Michel Trivi <jmtrivi@google.com>2012-05-15 15:51:16 -0700
committerJean-Michel Trivi <jmtrivi@google.com>2012-05-16 12:28:45 -0700
commit6895deeecc8797e6f5b28e7d07ec6bc499355c0c (patch)
tree9dc5dcdccac3993d0604b69ec08ad2ce75015664 /media/libeffects/downmix
parent5d3d12bf58da5b48b1edb7c20b5d1edec0773f75 (diff)
downloadframeworks_av-6895deeecc8797e6f5b28e7d07ec6bc499355c0c.zip
frameworks_av-6895deeecc8797e6f5b28e7d07ec6bc499355c0c.tar.gz
frameworks_av-6895deeecc8797e6f5b28e7d07ec6bc499355c0c.tar.bz2
Stereo downmixer supports generic configurations. Fix 7.1 downmix
Added a generic downmixer to stereo function to handle the multichannel configurations not supported by the dedicated downmix functions. It first verifies the mask is supported, and then derives channel indices for the downmix. Added support for forcing the generic downmixer to be always used instead of the format-specific functions (define DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER to force it). Fixed 7.1 downmix function where handling of accumulate vs overwrite was inversed. Bug 4280902 Change-Id: I8259b32c4e90f76ef4dcd803592fc71df4ae90c5
Diffstat (limited to 'media/libeffects/downmix')
-rw-r--r--media/libeffects/downmix/EffectDownmix.c280
-rw-r--r--media/libeffects/downmix/EffectDownmix.h13
2 files changed, 282 insertions, 11 deletions
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index f37cd5e..8735503 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -22,6 +22,11 @@
#include <stdbool.h>
#include "EffectDownmix.h"
+// Do not submit with DOWNMIX_TEST_CHANNEL_INDEX defined, strictly for testing
+//#define DOWNMIX_TEST_CHANNEL_INDEX 0
+// Do not submit with DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER defined, strictly for testing
+//#define DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER 0
+
#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
typedef enum {
@@ -88,6 +93,67 @@ const int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *
/*----------------------------------------------------------------------------
+ * Test code
+ *--------------------------------------------------------------------------*/
+#ifdef DOWNMIX_TEST_CHANNEL_INDEX
+// strictly for testing, logs the indices of the channels for a given mask,
+// uses the same code as Downmix_foldGeneric()
+void Downmix_testIndexComputation(uint32_t mask) {
+ ALOGI("Testing index computation for 0x%x:", mask);
+ // check against unsupported channels
+ if (mask & kUnsupported) {
+ ALOGE("Unsupported channels (top or front left/right of center)");
+ return;
+ }
+ // verify has FL/FR
+ if ((mask & AUDIO_CHANNEL_OUT_STEREO) != AUDIO_CHANNEL_OUT_STEREO) {
+ ALOGE("Front channels must be present");
+ return;
+ }
+ // verify uses SIDE as a pair (ok if not using SIDE at all)
+ bool hasSides = false;
+ if ((mask & kSides) != 0) {
+ if ((mask & kSides) != kSides) {
+ ALOGE("Side channels must be used as a pair");
+ return;
+ }
+ hasSides = true;
+ }
+ // verify uses BACK as a pair (ok if not using BACK at all)
+ bool hasBacks = false;
+ if ((mask & kBacks) != 0) {
+ if ((mask & kBacks) != kBacks) {
+ ALOGE("Back channels must be used as a pair");
+ return;
+ }
+ hasBacks = true;
+ }
+
+ const int numChan = popcount(mask);
+ const bool hasFC = ((mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) == AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ const bool hasLFE =
+ ((mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) == AUDIO_CHANNEL_OUT_LOW_FREQUENCY);
+ const bool hasBC = ((mask & AUDIO_CHANNEL_OUT_BACK_CENTER) == AUDIO_CHANNEL_OUT_BACK_CENTER);
+ // compute at what index each channel is: samples will be in the following order:
+ // FL FR FC LFE BL BR BC SL SR
+ // when a channel is not present, its index is set to the same as the index of the preceding
+ // channel
+ const int indexFC = hasFC ? 2 : 1; // front center
+ const int indexLFE = hasLFE ? indexFC + 1 : indexFC; // low frequency
+ const int indexBL = hasBacks ? indexLFE + 1 : indexLFE; // back left
+ const int indexBR = hasBacks ? indexBL + 1 : indexBL; // back right
+ const int indexBC = hasBC ? indexBR + 1 : indexBR; // back center
+ const int indexSL = hasSides ? indexBC + 1 : indexBC; // side left
+ const int indexSR = hasSides ? indexSL + 1 : indexSL; // side right
+
+ ALOGI(" FL FR FC LFE BL BR BC SL SR");
+ ALOGI(" %d %d %d %d %d %d %d %d %d",
+ 0, 1, indexFC, indexLFE, indexBL, indexBR, indexBC, indexSL, indexSR);
+}
+#endif
+
+
+/*----------------------------------------------------------------------------
* Effect API implementation
*--------------------------------------------------------------------------*/
@@ -123,6 +189,26 @@ int32_t DownmixLib_Create(const effect_uuid_t *uuid,
ALOGV("DownmixLib_Create()");
+#ifdef DOWNMIX_TEST_CHANNEL_INDEX
+ // should work (won't log an error)
+ ALOGI("DOWNMIX_TEST_CHANNEL_INDEX: should work:");
+ Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_CENTER);
+ Downmix_testIndexComputation(CHANNEL_MASK_QUAD_SIDE | CHANNEL_MASK_QUAD_BACK);
+ Downmix_testIndexComputation(CHANNEL_MASK_5POINT1_SIDE | AUDIO_CHANNEL_OUT_BACK_CENTER);
+ Downmix_testIndexComputation(CHANNEL_MASK_5POINT1_BACK | AUDIO_CHANNEL_OUT_BACK_CENTER);
+ // shouldn't work (will log an error, won't display channel indices)
+ ALOGI("DOWNMIX_TEST_CHANNEL_INDEX: should NOT work:");
+ Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_LEFT);
+ Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_SIDE_LEFT);
+ Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_BACK_LEFT | AUDIO_CHANNEL_OUT_BACK_RIGHT);
+ Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_SIDE_LEFT | AUDIO_CHANNEL_OUT_SIDE_RIGHT);
+#endif
+
if (pHandle == NULL || uuid == NULL) {
return -EINVAL;
}
@@ -232,6 +318,7 @@ static int Downmix_Process(effect_handle_t self,
const bool accumulate =
(pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ const uint32_t downmixInputChannelMask = pDwmModule->config.inputCfg.channels;
switch(pDownmixer->type) {
@@ -256,8 +343,17 @@ static int Downmix_Process(effect_handle_t self,
break;
case DOWNMIX_TYPE_FOLD:
+#ifdef DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER
+ // bypass the optimized downmix routines for the common formats
+ if (!Downmix_foldGeneric(
+ downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
+ ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask);
+ return -EINVAL;
+ }
+ break;
+#endif
// optimize for the common formats
- switch((downmix_input_channel_mask_t)pDwmModule->config.inputCfg.channels) {
+ switch((downmix_input_channel_mask_t)downmixInputChannelMask) {
case CHANNEL_MASK_QUAD_BACK:
case CHANNEL_MASK_QUAD_SIDE:
Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate);
@@ -273,8 +369,11 @@ static int Downmix_Process(effect_handle_t self,
Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
break;
default:
- // FIXME implement generic downmix
- ALOGE("Multichannel configurations other than quad, 4.0, 5.1 and 7.1 are not supported");
+ if (!Downmix_foldGeneric(
+ downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
+ ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask);
+ return -EINVAL;
+ }
break;
}
break;
@@ -707,6 +806,8 @@ int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pS
* Inputs:
* pSrc quad audio samples to downmix
* numFrames the number of quad frames to downmix
+ * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
+ * or overwrite pDst (when false)
*
* Outputs:
* pDst downmixed stereo audio samples
@@ -751,6 +852,8 @@ void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool ac
* Inputs:
* pSrc surround signal to downmix
* numFrames the number of surround frames to downmix
+ * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
+ * or overwrite pDst (when false)
*
* Outputs:
* pDst downmixed stereo audio samples
@@ -763,6 +866,8 @@ void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, boo
// sample at index 1 is FR
// sample at index 2 is FC
// sample at index 3 is RC
+ // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+ // for every sample
if (accumulate) {
while (numFrames) {
// centerPlusRearContrib = FC(-3dB) + RC(-3dB)
@@ -771,6 +876,7 @@ void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, boo
lt = (pSrc[0] << 12) + centerPlusRearContrib;
// FR + centerPlusRearContrib
rt = (pSrc[1] << 12) + centerPlusRearContrib;
+ // accumulate in destination
pDst[0] = clamp16(pDst[0] + (lt >> 12));
pDst[1] = clamp16(pDst[1] + (rt >> 12));
pSrc += 4;
@@ -785,8 +891,9 @@ void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, boo
lt = (pSrc[0] << 12) + centerPlusRearContrib;
// FR + centerPlusRearContrib
rt = (pSrc[1] << 12) + centerPlusRearContrib;
- pDst[0] = clamp16(lt >> 12);
- pDst[1] = clamp16(rt >> 12);
+ // store in destination
+ pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
+ pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
pSrc += 4;
pDst += 2;
numFrames--;
@@ -804,6 +911,8 @@ void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, boo
* Inputs:
* pSrc 5.1 audio samples to downmix
* numFrames the number of 5.1 frames to downmix
+ * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
+ * or overwrite pDst (when false)
*
* Outputs:
* pDst downmixed stereo audio samples
@@ -818,6 +927,8 @@ void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
// sample at index 3 is LFE
// sample at index 4 is RL
// sample at index 5 is RR
+ // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+ // for every sample
if (accumulate) {
while (numFrames) {
// centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
@@ -827,6 +938,7 @@ void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
// FR + centerPlusLfeContrib + RR
rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
+ // accumulate in destination
pDst[0] = clamp16(pDst[0] + (lt >> 12));
pDst[1] = clamp16(pDst[1] + (rt >> 12));
pSrc += 6;
@@ -842,8 +954,9 @@ void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
// FR + centerPlusLfeContrib + RR
rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
- pDst[0] = clamp16(lt >> 12);
- pDst[1] = clamp16(rt >> 12);
+ // store in destination
+ pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
+ pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
pSrc += 6;
pDst += 2;
numFrames--;
@@ -861,6 +974,8 @@ void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
* Inputs:
* pSrc 7.1 audio samples to downmix
* numFrames the number of 7.1 frames to downmix
+ * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
+ * or overwrite pDst (when false)
*
* Outputs:
* pDst downmixed stereo audio samples
@@ -877,6 +992,8 @@ void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
// sample at index 5 is RR
// sample at index 6 is SL
// sample at index 7 is SR
+ // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+ // for every sample
if (accumulate) {
while (numFrames) {
// centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
@@ -886,8 +1003,9 @@ void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
// FR + centerPlusLfeContrib + SR + RR
rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
- pDst[0] = clamp16(lt >> 12);
- pDst[1] = clamp16(rt >> 12);
+ //accumulate in destination
+ pDst[0] = clamp16(pDst[0] + (lt >> 12));
+ pDst[1] = clamp16(pDst[1] + (rt >> 12));
pSrc += 8;
pDst += 2;
numFrames--;
@@ -901,8 +1019,9 @@ void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
// FR + centerPlusLfeContrib + SR + RR
rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
- pDst[0] = clamp16(pDst[0] + (lt >> 12));
- pDst[1] = clamp16(pDst[1] + (rt >> 12));
+ // store in destination
+ pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
+ pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
pSrc += 8;
pDst += 2;
numFrames--;
@@ -910,3 +1029,142 @@ void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool
}
}
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldGeneric()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix to stereo a multichannel signal whose format is:
+ * - has FL/FR
+ * - if using AUDIO_CHANNEL_OUT_SIDE*, it contains both left and right
+ * - if using AUDIO_CHANNEL_OUT_BACK*, it contains both left and right
+ * - doesn't use any of the AUDIO_CHANNEL_OUT_TOP* channels
+ * - doesn't use any of the AUDIO_CHANNEL_OUT_FRONT_*_OF_CENTER channels
+ * Only handles channel masks not enumerated in downmix_input_channel_mask_t
+ *
+ * Inputs:
+ * mask the channel mask of pSrc
+ * pSrc multichannel audio buffer to downmix
+ * numFrames the number of multichannel frames to downmix
+ * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
+ * or overwrite pDst (when false)
+ *
+ * Outputs:
+ * pDst downmixed stereo audio samples
+ *
+ * Returns: false if multichannel format is not supported
+ *
+ *----------------------------------------------------------------------------
+ */
+bool Downmix_foldGeneric(
+ uint32_t mask, int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+ // check against unsupported channels
+ if (mask & kUnsupported) {
+ ALOGE("Unsupported channels (top or front left/right of center)");
+ return false;
+ }
+ // verify has FL/FR
+ if ((mask & AUDIO_CHANNEL_OUT_STEREO) != AUDIO_CHANNEL_OUT_STEREO) {
+ ALOGE("Front channels must be present");
+ return false;
+ }
+ // verify uses SIDE as a pair (ok if not using SIDE at all)
+ bool hasSides = false;
+ if ((mask & kSides) != 0) {
+ if ((mask & kSides) != kSides) {
+ ALOGE("Side channels must be used as a pair");
+ return false;
+ }
+ hasSides = true;
+ }
+ // verify uses BACK as a pair (ok if not using BACK at all)
+ bool hasBacks = false;
+ if ((mask & kBacks) != 0) {
+ if ((mask & kBacks) != kBacks) {
+ ALOGE("Back channels must be used as a pair");
+ return false;
+ }
+ hasBacks = true;
+ }
+
+ const int numChan = popcount(mask);
+ const bool hasFC = ((mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) == AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ const bool hasLFE =
+ ((mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) == AUDIO_CHANNEL_OUT_LOW_FREQUENCY);
+ const bool hasBC = ((mask & AUDIO_CHANNEL_OUT_BACK_CENTER) == AUDIO_CHANNEL_OUT_BACK_CENTER);
+ // compute at what index each channel is: samples will be in the following order:
+ // FL FR FC LFE BL BR BC SL SR
+ // when a channel is not present, its index is set to the same as the index of the preceding
+ // channel
+ const int indexFC = hasFC ? 2 : 1; // front center
+ const int indexLFE = hasLFE ? indexFC + 1 : indexFC; // low frequency
+ const int indexBL = hasBacks ? indexLFE + 1 : indexLFE; // back left
+ const int indexBR = hasBacks ? indexBL + 1 : indexBL; // back right
+ const int indexBC = hasBC ? indexBR + 1 : indexBR; // back center
+ const int indexSL = hasSides ? indexBC + 1 : indexBC; // side left
+ const int indexSR = hasSides ? indexSL + 1 : indexSL; // side right
+
+ int32_t lt, rt, centersLfeContrib; // samples in Q19.12 format
+ // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+ // for every sample
+ if (accumulate) {
+ while (numFrames) {
+ // compute contribution of FC, BC and LFE
+ centersLfeContrib = 0;
+ if (hasFC) { centersLfeContrib += pSrc[indexFC]; }
+ if (hasLFE) { centersLfeContrib += pSrc[indexLFE]; }
+ if (hasBC) { centersLfeContrib += pSrc[indexBC]; }
+ centersLfeContrib *= MINUS_3_DB_IN_Q19_12;
+ // always has FL/FR
+ lt = (pSrc[0] << 12);
+ rt = (pSrc[1] << 12);
+ // mix in sides and backs
+ if (hasSides) {
+ lt += pSrc[indexSL] << 12;
+ rt += pSrc[indexSR] << 12;
+ }
+ if (hasBacks) {
+ lt += pSrc[indexBL] << 12;
+ rt += pSrc[indexBR] << 12;
+ }
+ lt += centersLfeContrib;
+ rt += centersLfeContrib;
+ // accumulate in destination
+ pDst[0] = clamp16(pDst[0] + (lt >> 12));
+ pDst[1] = clamp16(pDst[1] + (rt >> 12));
+ pSrc += numChan;
+ pDst += 2;
+ numFrames--;
+ }
+ } else {
+ while (numFrames) {
+ // compute contribution of FC, BC and LFE
+ centersLfeContrib = 0;
+ if (hasFC) { centersLfeContrib += pSrc[indexFC]; }
+ if (hasLFE) { centersLfeContrib += pSrc[indexLFE]; }
+ if (hasBC) { centersLfeContrib += pSrc[indexBC]; }
+ centersLfeContrib *= MINUS_3_DB_IN_Q19_12;
+ // always has FL/FR
+ lt = (pSrc[0] << 12);
+ rt = (pSrc[1] << 12);
+ // mix in sides and backs
+ if (hasSides) {
+ lt += pSrc[indexSL] << 12;
+ rt += pSrc[indexSR] << 12;
+ }
+ if (hasBacks) {
+ lt += pSrc[indexBL] << 12;
+ rt += pSrc[indexBR] << 12;
+ }
+ lt += centersLfeContrib;
+ rt += centersLfeContrib;
+ // store in destination
+ pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
+ pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
+ pSrc += numChan;
+ pDst += 2;
+ numFrames--;
+ }
+ }
+ return true;
+}
diff --git a/media/libeffects/downmix/EffectDownmix.h b/media/libeffects/downmix/EffectDownmix.h
index 4176b5a..be3ca3f 100644
--- a/media/libeffects/downmix/EffectDownmix.h
+++ b/media/libeffects/downmix/EffectDownmix.h
@@ -49,6 +49,17 @@ typedef struct downmix_module_s {
downmix_object_t context;
} downmix_module_t;
+const uint32_t kSides = AUDIO_CHANNEL_OUT_SIDE_LEFT | AUDIO_CHANNEL_OUT_SIDE_RIGHT;
+const uint32_t kBacks = AUDIO_CHANNEL_OUT_BACK_LEFT | AUDIO_CHANNEL_OUT_BACK_RIGHT;
+const uint32_t kUnsupported =
+ AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER | AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
+ AUDIO_CHANNEL_OUT_TOP_CENTER |
+ AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT |
+ AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER |
+ AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT |
+ AUDIO_CHANNEL_OUT_TOP_BACK_LEFT |
+ AUDIO_CHANNEL_OUT_TOP_BACK_CENTER |
+ AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT;
/*------------------------------------
* Effect API
@@ -92,5 +103,7 @@ void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool ac
void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+bool Downmix_foldGeneric(
+ uint32_t mask, int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
#endif /*ANDROID_EFFECTDOWNMIX_H_*/