To support playing mono file with stereo codec as mixing with microphone capture

BUG=413
TEST=Manual test.
Review URL: https://webrtc-codereview.appspot.com/460004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1953 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/voice_engine/main/source/channel.cc b/src/voice_engine/main/source/channel.cc
index cd76607..94b6dd4 100644
--- a/src/voice_engine/main/source/channel.cc
+++ b/src/voice_engine/main/source/channel.cc
@@ -6151,7 +6151,7 @@
 WebRtc_Word32
 Channel::MixOrReplaceAudioWithFile(const int mixingFrequency)
 {
-    WebRtc_Word16 fileBuffer[320];
+    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
     WebRtc_UWord32 fileSamples(0);
 
     {
@@ -6166,7 +6166,7 @@
             return -1;
         }
 
-        if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer,
+        if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
                                                       fileSamples,
                                                       mixingFrequency) == -1)
         {
@@ -6189,17 +6189,23 @@
 
     if (_mixFileWithMicrophone)
     {
+        // Currently file stream is always mono.
+        // TODO(xians): Change the code when FilePlayer supports real stereo.
         Utility::MixWithSat(_audioFrame._payloadData,
-                            fileBuffer,
-                            (WebRtc_UWord16)fileSamples);
+                            static_cast<int>(_audioFrame._audioChannel),
+                            fileBuffer.get(),
+                            1,
+                            static_cast<int>(fileSamples));
     }
     else
     {
-        // replace ACM audio with file
+        // Replace ACM audio with file.
+        // Currently file stream is always mono.
+        // TODO(xians): Change the code when FilePlayer supports real stereo.
         _audioFrame.UpdateFrame(_channelId,
                                 -1,
-                                fileBuffer,
-                                (WebRtc_UWord16)fileSamples,
+                                fileBuffer.get(),
+                                static_cast<WebRtc_UWord16>(fileSamples),
                                 mixingFrequency,
                                 AudioFrame::kNormalSpeech,
                                 AudioFrame::kVadUnknown,
@@ -6215,7 +6221,7 @@
 {
     assert(mixingFrequency <= 32000);
 
-    WebRtc_Word16 fileBuffer[640];
+    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
     WebRtc_UWord32 fileSamples(0);
 
     {
@@ -6230,7 +6236,7 @@
         }
 
         // We should get the frequency we ask for.
-        if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer,
+        if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
                                                        fileSamples,
                                                        mixingFrequency) == -1)
         {
@@ -6243,28 +6249,13 @@
 
     if (audioFrame._payloadDataLengthInSamples == fileSamples)
     {
-        // In case the incoming stream is stereo and file stream is mono,
-        // turn the file stream into stereo.
-        // TODO(xians): remove the code when FilePlayer supports real stereo.
-        if (audioFrame._audioChannel == 2)
-        {
-            // The mono file stream is copied to be stereo.
-            WebRtc_Word16* FileBufferCopy = new WebRtc_Word16[fileSamples];
-            memcpy(FileBufferCopy, fileBuffer,
-                   sizeof(WebRtc_Word16) * fileSamples);
-            for (unsigned int i = 0; i < fileSamples; i++)
-            {
-                fileBuffer[2*i]   = FileBufferCopy[i];
-                fileBuffer[2*i+1] = FileBufferCopy[i];
-            }
-            fileSamples = 2*fileSamples;
-            delete [] FileBufferCopy;
-        }
-
-        // Mix the incoming stream and file stream.
+        // Currently file stream is always mono.
+        // TODO(xians): Change the code when FilePlayer supports real stereo.
         Utility::MixWithSat(audioFrame._payloadData,
-                            fileBuffer,
-                            (WebRtc_UWord16)fileSamples);
+                            static_cast<int>(audioFrame._audioChannel),
+                            fileBuffer.get(),
+                            1,
+                            static_cast<int>(fileSamples));
     }
     else
     {
diff --git a/src/voice_engine/main/source/transmit_mixer.cc b/src/voice_engine/main/source/transmit_mixer.cc
index cf7f38e..cd1e2ac 100644
--- a/src/voice_engine/main/source/transmit_mixer.cc
+++ b/src/voice_engine/main/source/transmit_mixer.cc
@@ -1218,7 +1218,7 @@
 WebRtc_Word32 TransmitMixer::MixOrReplaceAudioWithFile(
     const int mixingFrequency)
 {
-    WebRtc_Word16 fileBuffer[320];
+    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
 
     WebRtc_UWord32 fileSamples(0);
 
@@ -1233,7 +1233,7 @@
             return -1;
         }
 
-        if (_filePlayerPtr->Get10msAudioFromFile(fileBuffer,
+        if (_filePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
                                                  fileSamples,
                                                  mixingFrequency) == -1)
         {
@@ -1244,19 +1244,27 @@
         }
     }
 
+    assert(_audioFrame._payloadDataLengthInSamples == fileSamples);
+
     if (_mixFileWithMicrophone)
     {
+        // Currently file stream is always mono.
+        // TODO(xians): Change the code when FilePlayer supports real stereo.
         Utility::MixWithSat(_audioFrame._payloadData,
-                             fileBuffer,
-                             (WebRtc_UWord16) fileSamples);
-        assert(_audioFrame._payloadDataLengthInSamples == fileSamples);
+                            static_cast<int>(_audioFrame._audioChannel),
+                            fileBuffer.get(),
+                            1,
+                            static_cast<int>(fileSamples));
     } else
     {
-        // replace ACM audio with file
+        // Replace ACM audio with file.
+        // Currently file stream is always mono.
+        // TODO(xians): Change the code when FilePlayer supports real stereo.
         _audioFrame.UpdateFrame(-1,
                                 -1,
-                                fileBuffer,
-                                (WebRtc_UWord16) fileSamples, mixingFrequency,
+                                fileBuffer.get(),
+                                static_cast<WebRtc_UWord16>(fileSamples),
+                                mixingFrequency,
                                 AudioFrame::kNormalSpeech,
                                 AudioFrame::kVadUnknown,
                                 1);
diff --git a/src/voice_engine/main/source/utility.cc b/src/voice_engine/main/source/utility.cc
index 6e70156..1ef108e 100644
--- a/src/voice_engine/main/source/utility.cc
+++ b/src/voice_engine/main/source/utility.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
@@ -12,27 +12,53 @@
 
 #include "module.h"
 #include "trace.h"
+#include "signal_processing_library.h"
 
 namespace webrtc
 {
 
 namespace voe
 {
+enum{kMaxTargetLen = 2*32*10}; // stereo 32KHz 10ms
 
 void Utility::MixWithSat(WebRtc_Word16 target[],
+                         int target_channel,
                          const WebRtc_Word16 source[],
-                         WebRtc_UWord16 len)
+                         int source_channel,
+                         int source_len)
 {
-    WebRtc_Word32 temp(0);
-    for (int i = 0; i < len; i++)
+    assert((target_channel == 1) || (target_channel == 2));
+    assert((source_channel == 1) || (source_channel == 2));
+    assert(source_len <= kMaxTargetLen);
+
+    if ((target_channel == 2) && (source_channel == 1))
     {
-        temp = source[i] + target[i];
-        if (temp > 32767)
-            target[i] = 32767;
-        else if (temp < -32768)
-            target[i] = -32768;
-        else
-            target[i] = (WebRtc_Word16) temp;
+        // Convert source from mono to stereo.
+        WebRtc_Word32 left = 0;
+        WebRtc_Word32 right = 0;
+        for (int i = 0; i < source_len; ++i) {
+            left  = source[i] + target[i*2];
+            right = source[i] + target[i*2 + 1];
+            target[i*2]     = WebRtcSpl_SatW32ToW16(left);
+            target[i*2 + 1] = WebRtcSpl_SatW32ToW16(right);
+        }
+    }
+    else if ((target_channel == 1) && (source_channel == 2))
+    {
+        // Convert source from stereo to mono.
+        WebRtc_Word32 temp = 0;
+        for (int i = 0; i < source_len/2; ++i) {
+          temp = ((source[i*2] + source[i*2 + 1])>>1) + target[i];
+          target[i] = WebRtcSpl_SatW32ToW16(temp);
+        }
+    }
+    else
+    {
+        WebRtc_Word32 temp = 0;
+        for (int i = 0; i < source_len; ++i) {
+          temp = source[i] + target[i];
+          target[i] = WebRtcSpl_SatW32ToW16(temp);
+        }
     }
 }
 
diff --git a/src/voice_engine/main/source/utility.h b/src/voice_engine/main/source/utility.h
index 084ddf4..a8af8bd 100644
--- a/src/voice_engine/main/source/utility.h
+++ b/src/voice_engine/main/source/utility.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
@@ -30,8 +30,10 @@
 {
 public:
     static void MixWithSat(WebRtc_Word16 target[],
+                           int target_channel,
                            const WebRtc_Word16 source[],
-                           WebRtc_UWord16 len);
+                           int source_channel,
+                           int source_len);
 
     static void MixSubtractWithSat(WebRtc_Word16 target[],
                                    const WebRtc_Word16 source[],