libeffects: Add multichannel support to Reverb

Test: SoloTester and Clarity app
Test: Standalone application test
Bug: 129491957
Change-Id: Ifac02eb2a7ac3eba5fae9318c3ae1e1c7df4f681
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index afc4220..021020c 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -53,6 +53,7 @@
 
     cppflags: [
         "-fvisibility=hidden",
+        "-DSUPPORT_MC",
 
         "-Wall",
         "-Werror",
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 39f5bb6..b95494d 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -259,6 +259,9 @@
 
     int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
 
+#ifdef SUPPORT_MC
+    channels = (pContext->auxiliary == true)? channels : FCC_2;
+#endif
     // Allocate memory for reverb process (*2 is for STEREO)
     pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(process_buffer_t) * channels;
     pContext->bufferSizeOut = LVREV_MAX_FRAME_SIZE * sizeof(process_buffer_t) * FCC_2;
@@ -343,11 +346,18 @@
     int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
     LVREV_ReturnStatus_en   LvmStatus = LVREV_SUCCESS;              /* Function call status */
 
-    // Check that the input is either mono or stereo
+    // Reverb only effects the stereo channels in multichannel source.
+#ifdef SUPPORT_MC
+    if (channels < 1 || channels > LVM_MAX_CHANNELS) {
+        ALOGE("\tLVREV_ERROR : process invalid PCM channels %d", channels);
+        return -EINVAL;
+    }
+#else
     if (!(channels == 1 || channels == FCC_2) ) {
         ALOGE("\tLVREV_ERROR : process invalid PCM format");
         return -EINVAL;
     }
+#endif
 
     size_t inSize = frameCount * sizeof(process_buffer_t) * channels;
     size_t outSize = frameCount * sizeof(process_buffer_t) * FCC_2;
@@ -380,12 +390,28 @@
         static_assert(std::is_same<decltype(*pIn), decltype(*pContext->InFrames)>::value,
                 "pIn and InFrames must be same type");
         memcpy(pContext->InFrames, pIn, frameCount * channels * sizeof(*pIn));
+    } else {
+        // mono input is duplicated
+#ifdef SUPPORT_MC
+        if (channels >= FCC_2) {
+            for (int i = 0; i < frameCount; i++) {
+                pContext->InFrames[FCC_2 * i] =
+                            (process_buffer_t)pIn[channels * i] * REVERB_SEND_LEVEL;
+                pContext->InFrames[FCC_2 * i + 1] =
+                            (process_buffer_t)pIn[channels * i + 1] * REVERB_SEND_LEVEL;
+            }
         } else {
-        // insert reverb input is always stereo
+            for (int i = 0; i < frameCount; i++) {
+                pContext->InFrames[FCC_2 * i] = pContext->InFrames[FCC_2 * i + 1] =
+                            (process_buffer_t)pIn[i] * REVERB_SEND_LEVEL;
+            }
+        }
+#else
         for (int i = 0; i < frameCount; i++) {
             pContext->InFrames[2 * i] = (process_buffer_t)pIn[2 * i] * REVERB_SEND_LEVEL;
             pContext->InFrames[2 * i + 1] = (process_buffer_t)pIn[2 * i + 1] * REVERB_SEND_LEVEL;
         }
+#endif
     }
 
     if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
@@ -412,10 +438,26 @@
     if (pContext->auxiliary) {
         // nothing to do here
     } else {
+#ifdef SUPPORT_MC
+        if (channels >= FCC_2) {
+            for (int i = 0; i < frameCount; i++) {
+                // Mix with dry input
+                pContext->OutFrames[FCC_2 * i] += pIn[channels * i];
+                pContext->OutFrames[FCC_2 * i + 1] += pIn[channels * i + 1];
+            }
+        } else {
+            for (int i = 0; i < frameCount; i++) {
+                // Mix with dry input
+                pContext->OutFrames[FCC_2 * i] += pIn[i];
+                pContext->OutFrames[FCC_2 * i + 1] += pIn[i];
+            }
+        }
+#else
         for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
             // Mix with dry input
             pContext->OutFrames[i] += pIn[i];
         }
+#endif
         // apply volume with ramp if needed
         if ((pContext->leftVolume != pContext->prevLeftVolume ||
                 pContext->rightVolume != pContext->prevRightVolume) &&
@@ -450,6 +492,35 @@
         }
     }
 
+#ifdef SUPPORT_MC
+    if (channels > 2) {
+        //Accumulate if required
+        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            for (int i = 0; i < frameCount; i++) {
+                pOut[channels * i] += pContext->OutFrames[FCC_2 * i];
+                pOut[channels * i + 1] += pContext->OutFrames[FCC_2 * i + 1];
+            }
+        } else {
+            for (int i = 0; i < frameCount; i++) {
+                pOut[channels * i] = pContext->OutFrames[FCC_2 * i];
+                pOut[channels * i + 1] = pContext->OutFrames[FCC_2 * i + 1];
+            }
+        }
+        for (int i = 0; i < frameCount; i++) {
+            for (int j = FCC_2; j < channels; j++) {
+                pOut[channels * i + j] = pIn[channels * i + j];
+            }
+        }
+    } else {
+        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            for (int i = 0; i < frameCount * FCC_2; i++) {
+                pOut[i] += pContext->OutFrames[i];
+            }
+        } else {
+            memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
+        }
+    }
+#else
 
     // Accumulate if required
     if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
@@ -462,6 +533,7 @@
         memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
     }
 
+#endif
     return 0;
 }    /* end process */
 
@@ -525,9 +597,18 @@
 
     CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
     CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+#ifdef SUPPORT_MC
+    int inputChannels = audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
+    CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
+              ((!pContext->auxiliary) &&
+              (inputChannels <= LVM_MAX_CHANNELS)));
+    int outputChannels = audio_channel_count_from_out_mask(pConfig->outputCfg.channels);
+    CHECK_ARG(outputChannels >= FCC_2 && outputChannels <= LVM_MAX_CHANNELS);
+#else
     CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
               ((!pContext->auxiliary) && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
     CHECK_ARG(pConfig->outputCfg.channels == AUDIO_CHANNEL_OUT_STEREO);
+#endif
     CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
               || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
     CHECK_ARG(pConfig->inputCfg.format == EFFECT_BUFFER_FORMAT);
@@ -749,6 +830,11 @@
         params.SourceFormat   = LVM_STEREO;
     }
 
+#ifdef SUPPORT_MC
+    if ((pContext->auxiliary == false) && (params.SourceFormat == LVM_MONO)) {
+        params.SourceFormat   = LVM_STEREO;
+    }
+#endif
     /* Reverb parameters */
     params.Level          = 0;
     params.LPF            = 23999;