AudioMixer: Expand mono track to multi-channel

Extend MONO_HACK to multi-channel output.

Mono track will have only one channel output on multi-channel devices.
Since ARC++ exposed a 4-channel output device and downmix track in
ChromeOS, we need to add this feature to support mono track sample
expansion.

Add support for both re-sample and non-resample path.
For resample path, we need to add MIXTYPE_STEREOEXPAND in
AudioMixerOps.h since AudioResampler will upmix mono track to stereo
track.

Bug: 120222604
Bug: 112341269
Bug: 117116052
Bug: crbug.com/890560
Test: Play mono tracks without re-sampling on ARC++
Test: Play mono tracks with re-sampling on ARC++
Test: Play normal stereo tracks on ARC++
(cherry picked from commit 9b79e0752e6536c31430aa31838a9de1b7b56f9f)

Change-Id: I51f5914c41dd0196db9c6a2e1a99b44e5d87c0d6
diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
index d3a26ad..2748182 100644
--- a/media/libaudioprocessing/AudioMixerOps.h
+++ b/media/libaudioprocessing/AudioMixerOps.h
@@ -219,6 +219,7 @@
     MIXTYPE_MULTI_SAVEONLY_MONOVOL,
     MIXTYPE_MULTI_STEREOVOL,
     MIXTYPE_MULTI_SAVEONLY_STEREOVOL,
+    MIXTYPE_STEREOEXPAND,
 };
 
 /*
@@ -232,7 +233,8 @@
 void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
     static_assert(NCHAN > 0 && NCHAN <= 8);
     static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL
-            || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL);
+            || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+            || MIXTYPE == MIXTYPE_STEREOEXPAND);
     auto proc = [](auto& a, const auto& b) {
         if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL) {
             a += b;
@@ -240,14 +242,22 @@
             a = b;
         }
     };
+    auto inp = [&in]() -> const TI& {
+        if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) {
+            return *in;
+        } else {
+            return *in++;
+        }
+    };
+
     // HALs should only expose the canonical channel masks.
-    proc(*out++, f(*in++, vol[0])); // front left
+    proc(*out++, f(inp(), vol[0])); // front left
     if constexpr (NCHAN == 1) return;
-    proc(*out++, f(*in++, vol[1])); // front right
+    proc(*out++, f(inp(), vol[1])); // front right
     if constexpr (NCHAN == 2)  return;
     if constexpr (NCHAN == 4) {
-        proc(*out++, f(*in++, vol[0])); // back left
-        proc(*out++, f(*in++, vol[1])); // back right
+        proc(*out++, f(inp(), vol[0])); // back left
+        proc(*out++, f(inp(), vol[1])); // back right
         return;
     }
 
@@ -258,25 +268,25 @@
     } else {
         center = (vol[0] >> 1) + (vol[1] >> 1); // rounds to 0.
     }
-    proc(*out++, f(*in++, center)); // center (or 2.1 LFE)
+    proc(*out++, f(inp(), center)); // center (or 2.1 LFE)
     if constexpr (NCHAN == 3) return;
     if constexpr (NCHAN == 5) {
-        proc(*out++, f(*in++, vol[0]));  // back left
-        proc(*out++, f(*in++, vol[1]));  // back right
+        proc(*out++, f(inp(), vol[0]));  // back left
+        proc(*out++, f(inp(), vol[1]));  // back right
         return;
     }
 
-    proc(*out++, f(*in++, center)); // lfe
-    proc(*out++, f(*in++, vol[0])); // back left
-    proc(*out++, f(*in++, vol[1])); // back right
+    proc(*out++, f(inp(), center)); // lfe
+    proc(*out++, f(inp(), vol[0])); // back left
+    proc(*out++, f(inp(), vol[1])); // back right
     if constexpr (NCHAN == 6) return;
     if constexpr (NCHAN == 7) {
-        proc(*out++, f(*in++, center)); // back center
+        proc(*out++, f(inp(), center)); // back center
         return;
     }
     // NCHAN == 8
-    proc(*out++, f(*in++, vol[0])); // side left
-    proc(*out++, f(*in++, vol[1])); // side right
+    proc(*out++, f(inp(), vol[0])); // side left
+    proc(*out++, f(inp(), vol[1])); // side right
 }
 
 /*
@@ -326,6 +336,11 @@
  * MIXTYPE_MULTI_SAVEONLY_STEREOVOL:
  *   Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0] and volume[1].
  *
+ * MIXTYPE_STEREOEXPAND:
+ *   Stereo input channel. NCHAN represents number of output channels.
+ *   Expand size 2 array "in" and "vol" to multi-channel output. Note
+ *   that the 2 array is assumed to have replicated L+R.
+ *
  */
 
 template <int MIXTYPE, int NCHAN,
@@ -366,11 +381,13 @@
                 }
                 vol[0] += volinc[0];
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
-                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(
                         out, in, vol, [&auxaccum] (auto &a, const auto &b) {
                     return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
                 vol[0] += volinc[0];
                 vol[1] += volinc[1];
             } else /* constexpr */ {
@@ -409,10 +426,12 @@
                 }
                 vol[0] += volinc[0];
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
-                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
                     return MixMul<TO, TI, TV>(a, b);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
                 vol[0] += volinc[0];
                 vol[1] += volinc[1];
             } else /* constexpr */ {
@@ -455,11 +474,13 @@
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                 }
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
-                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(
                         out, in, vol, [&auxaccum] (auto &a, const auto &b) {
                     return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
             } else /* constexpr */ {
                 static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
             }
@@ -490,10 +511,12 @@
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
                 }
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
-                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
                     return MixMul<TO, TI, TV>(a, b);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
             } else /* constexpr */ {
                 static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
             }