NetEq4: Make the algorithm buffer a member variable

This reduces the alloc count by more than 100,000 for
NetEqDecodingTest.TestBitExactness.

BUG=1363
TEST=out/Release/modules_unittests --gtest_filter=NetEqDecodingTest.TestBitExactness
R=turaj@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/2119004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4651 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_impl.cc b/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
index 6e495d2..1124f8b 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
@@ -70,6 +70,7 @@
       payload_splitter_(payload_splitter),
       timestamp_scaler_(timestamp_scaler),
       vad_(new PostDecodeVad()),
+      algorithm_buffer_(NULL),
       sync_buffer_(NULL),
       expand_(NULL),
       comfort_noise_(NULL),
@@ -112,6 +113,7 @@
 
 NetEqImpl::~NetEqImpl() {
   LOG(LS_INFO) << "Deleting NetEqImpl object.";
+  delete algorithm_buffer_;
   delete sync_buffer_;
   delete background_noise_;
   delete expand_;
@@ -620,58 +622,55 @@
   vad_->Update(decoded_buffer_.get(), length, speech_type,
                sid_frame_available, fs_hz_);
 
-  AudioMultiVector<int16_t> algorithm_buffer(sync_buffer_->Channels());
+  algorithm_buffer_->Clear();
   switch (operation) {
     case kNormal: {
-      DoNormal(decoded_buffer_.get(), length, speech_type, play_dtmf,
-               &algorithm_buffer);
+      DoNormal(decoded_buffer_.get(), length, speech_type, play_dtmf);
       break;
     }
     case kMerge: {
-      DoMerge(decoded_buffer_.get(), length, speech_type, play_dtmf,
-              &algorithm_buffer);
+      DoMerge(decoded_buffer_.get(), length, speech_type, play_dtmf);
       break;
     }
     case kExpand: {
-      return_value = DoExpand(play_dtmf, &algorithm_buffer);
+      return_value = DoExpand(play_dtmf);
       break;
     }
     case kAccelerate: {
       return_value = DoAccelerate(decoded_buffer_.get(), length, speech_type,
-                                  play_dtmf, &algorithm_buffer);
+                                  play_dtmf);
       break;
     }
     case kPreemptiveExpand: {
       return_value = DoPreemptiveExpand(decoded_buffer_.get(), length,
-                                        speech_type, play_dtmf,
-                                        &algorithm_buffer);
+                                        speech_type, play_dtmf);
       break;
     }
     case kRfc3389Cng:
     case kRfc3389CngNoPacket: {
-      return_value = DoRfc3389Cng(&packet_list, play_dtmf, &algorithm_buffer);
+      return_value = DoRfc3389Cng(&packet_list, play_dtmf);
       break;
     }
     case kCodecInternalCng: {
       // This handles the case when there is no transmission and the decoder
       // should produce internal comfort noise.
       // TODO(hlundin): Write test for codec-internal CNG.
-      DoCodecInternalCng(&algorithm_buffer);
+      DoCodecInternalCng();
       break;
     }
     case kDtmf: {
       // TODO(hlundin): Write test for this.
-      return_value = DoDtmf(dtmf_event, &play_dtmf, &algorithm_buffer);
+      return_value = DoDtmf(dtmf_event, &play_dtmf);
       break;
     }
     case kAlternativePlc: {
       // TODO(hlundin): Write test for this.
-      DoAlternativePlc(false, &algorithm_buffer);
+      DoAlternativePlc(false);
       break;
     }
     case kAlternativePlcIncreaseTimestamp: {
       // TODO(hlundin): Write test for this.
-      DoAlternativePlc(true, &algorithm_buffer);
+      DoAlternativePlc(true);
       break;
     }
     case kAudioRepetitionIncreaseTimestamp: {
@@ -684,7 +683,7 @@
       // TODO(hlundin): Write test for this.
       // Copy last |output_size_samples_| from |sync_buffer_| to
       // |algorithm_buffer|.
-      algorithm_buffer.PushBackFromIndex(
+      algorithm_buffer_->PushBackFromIndex(
           *sync_buffer_, sync_buffer_->Size() - output_size_samples_);
       expand_->Reset();
       break;
@@ -705,7 +704,7 @@
   }
 
   // Copy from |algorithm_buffer| to |sync_buffer_|.
-  sync_buffer_->PushBack(algorithm_buffer);
+  sync_buffer_->PushBack(*algorithm_buffer_);
 
   // Extract data from |sync_buffer_| to |output|.
   int num_output_samples_per_channel = output_size_samples_;
@@ -720,7 +719,7 @@
       num_output_samples_per_channel, output);
   *num_channels = sync_buffer_->Channels();
   LOG(LS_VERBOSE) << "Sync buffer (" << *num_channels << " channel(s)):" <<
-      " insert " << algorithm_buffer.Size() << " samples, extract " <<
+      " insert " << algorithm_buffer_->Size() << " samples, extract " <<
       samples_from_sync << " samples";
   if (samples_from_sync != output_size_samples_) {
     LOG_F(LS_ERROR) << "samples_from_sync != output_size_samples_";
@@ -1205,15 +1204,14 @@
 }
 
 void NetEqImpl::DoNormal(const int16_t* decoded_buffer, size_t decoded_length,
-                         AudioDecoder::SpeechType speech_type, bool play_dtmf,
-                         AudioMultiVector<int16_t>* algorithm_buffer) {
+                         AudioDecoder::SpeechType speech_type, bool play_dtmf) {
   assert(decoder_database_.get());
   assert(background_noise_);
   assert(expand_);
   Normal normal(fs_hz_, decoder_database_.get(), *background_noise_, expand_);
   assert(mute_factor_array_.get());
   normal.Process(decoded_buffer, decoded_length, last_mode_,
-                 mute_factor_array_.get(), algorithm_buffer);
+                 mute_factor_array_.get(), algorithm_buffer_);
   if (decoded_length != 0) {
     last_mode_ = kModeNormal;
   }
@@ -1232,12 +1230,11 @@
 }
 
 void NetEqImpl::DoMerge(int16_t* decoded_buffer, size_t decoded_length,
-                        AudioDecoder::SpeechType speech_type, bool play_dtmf,
-                        AudioMultiVector<int16_t>* algorithm_buffer) {
-  Merge merge(fs_hz_, algorithm_buffer->Channels(), expand_, sync_buffer_);
+                        AudioDecoder::SpeechType speech_type, bool play_dtmf) {
+  Merge merge(fs_hz_, algorithm_buffer_->Channels(), expand_, sync_buffer_);
   assert(mute_factor_array_.get());
   int new_length = merge.Process(decoded_buffer, decoded_length,
-                                 mute_factor_array_.get(), algorithm_buffer);
+                                 mute_factor_array_.get(), algorithm_buffer_);
 
   // Update in-call and post-call statistics.
   if (expand_->MuteFactor(0) == 0) {
@@ -1259,13 +1256,12 @@
   }
 }
 
-int NetEqImpl::DoExpand(bool play_dtmf,
-                        AudioMultiVector<int16_t>* algorithm_buffer) {
+int NetEqImpl::DoExpand(bool play_dtmf) {
   while ((sync_buffer_->FutureLength() - expand_->overlap_length()) <
       static_cast<size_t>(output_size_samples_)) {
-    algorithm_buffer->Clear();
-    int return_value = expand_->Process(algorithm_buffer);
-    int length = algorithm_buffer->Size();
+    algorithm_buffer_->Clear();
+    int return_value = expand_->Process(algorithm_buffer_);
+    int length = algorithm_buffer_->Size();
 
     // Update in-call and post-call statistics.
     if (expand_->MuteFactor(0) == 0) {
@@ -1282,8 +1278,8 @@
       return return_value;
     }
 
-    sync_buffer_->PushBack(*algorithm_buffer);
-    algorithm_buffer->Clear();
+    sync_buffer_->PushBack(*algorithm_buffer_);
+    algorithm_buffer_->Clear();
   }
   if (!play_dtmf) {
     dtmf_tone_generator_->Reset();
@@ -1293,11 +1289,10 @@
 
 int NetEqImpl::DoAccelerate(int16_t* decoded_buffer, size_t decoded_length,
                             AudioDecoder::SpeechType speech_type,
-                            bool play_dtmf,
-                            AudioMultiVector<int16_t>* algorithm_buffer) {
+                            bool play_dtmf) {
   const size_t required_samples = 240 * fs_mult_;  // Must have 30 ms.
   int borrowed_samples_per_channel = 0;
-  size_t num_channels = algorithm_buffer->Channels();
+  size_t num_channels = algorithm_buffer_->Channels();
   size_t decoded_length_per_channel = decoded_length / num_channels;
   if (decoded_length_per_channel < required_samples) {
     // Must move data from the |sync_buffer_| in order to get 30 ms.
@@ -1315,7 +1310,7 @@
   Accelerate accelerate(fs_hz_, num_channels, *background_noise_);
   Accelerate::ReturnCodes return_code = accelerate.Process(decoded_buffer,
                                                            decoded_length,
-                                                           algorithm_buffer,
+                                                           algorithm_buffer_,
                                                            &samples_removed);
   stats_.AcceleratedSamples(samples_removed);
   switch (return_code) {
@@ -1336,22 +1331,22 @@
 
   if (borrowed_samples_per_channel > 0) {
     // Copy borrowed samples back to the |sync_buffer_|.
-    int length = algorithm_buffer->Size();
+    int length = algorithm_buffer_->Size();
     if (length < borrowed_samples_per_channel) {
       // This destroys the beginning of the buffer, but will not cause any
       // problems.
-      sync_buffer_->ReplaceAtIndex(*algorithm_buffer,
+      sync_buffer_->ReplaceAtIndex(*algorithm_buffer_,
                                    sync_buffer_->Size() -
                                    borrowed_samples_per_channel);
       sync_buffer_->PushFrontZeros(borrowed_samples_per_channel - length);
-      algorithm_buffer->PopFront(length);
-      assert(algorithm_buffer->Empty());
+      algorithm_buffer_->PopFront(length);
+      assert(algorithm_buffer_->Empty());
     } else {
-      sync_buffer_->ReplaceAtIndex(*algorithm_buffer,
+      sync_buffer_->ReplaceAtIndex(*algorithm_buffer_,
                                    borrowed_samples_per_channel,
                                    sync_buffer_->Size() -
                                    borrowed_samples_per_channel);
-      algorithm_buffer->PopFront(borrowed_samples_per_channel);
+      algorithm_buffer_->PopFront(borrowed_samples_per_channel);
     }
   }
 
@@ -1369,10 +1364,9 @@
 int NetEqImpl::DoPreemptiveExpand(int16_t* decoded_buffer,
                                   size_t decoded_length,
                                   AudioDecoder::SpeechType speech_type,
-                                  bool play_dtmf,
-                                  AudioMultiVector<int16_t>* algorithm_buffer) {
+                                  bool play_dtmf) {
   const size_t required_samples = 240 * fs_mult_;  // Must have 30 ms.
-  size_t num_channels = algorithm_buffer->Channels();
+  size_t num_channels = algorithm_buffer_->Channels();
   int borrowed_samples_per_channel = 0;
   int old_borrowed_samples_per_channel = 0;
   size_t decoded_length_per_channel = decoded_length / num_channels;
@@ -1397,7 +1391,7 @@
   PreemptiveExpand preemptive_expand(fs_hz_, num_channels, *background_noise_);
   PreemptiveExpand::ReturnCodes return_code = preemptive_expand.Process(
       decoded_buffer, decoded_length, old_borrowed_samples_per_channel,
-      algorithm_buffer, &samples_added);
+      algorithm_buffer_, &samples_added);
   stats_.PreemptiveExpandedSamples(samples_added);
   switch (return_code) {
     case PreemptiveExpand::kSuccess:
@@ -1418,9 +1412,9 @@
   if (borrowed_samples_per_channel > 0) {
     // Copy borrowed samples back to the |sync_buffer_|.
     sync_buffer_->ReplaceAtIndex(
-        *algorithm_buffer, borrowed_samples_per_channel,
+        *algorithm_buffer_, borrowed_samples_per_channel,
         sync_buffer_->Size() - borrowed_samples_per_channel);
-    algorithm_buffer->PopFront(borrowed_samples_per_channel);
+    algorithm_buffer_->PopFront(borrowed_samples_per_channel);
   }
 
   // If last packet was decoded as an inband CNG, set mode to CNG instead.
@@ -1434,8 +1428,7 @@
   return 0;
 }
 
-int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf,
-                            AudioMultiVector<int16_t>* algorithm_buffer) {
+int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf) {
   if (!packet_list->empty()) {
     // Must have exactly one SID frame at this point.
     assert(packet_list->size() == 1);
@@ -1470,12 +1463,12 @@
     if (comfort_noise_->UpdateParameters(packet) ==
         ComfortNoise::kInternalError) {
       LOG_FERR0(LS_WARNING, UpdateParameters);
-      algorithm_buffer->Zeros(output_size_samples_);
+      algorithm_buffer_->Zeros(output_size_samples_);
       return -comfort_noise_->internal_error_code();
     }
   }
   int cn_return = comfort_noise_->Generate(output_size_samples_,
-                                           algorithm_buffer);
+                                           algorithm_buffer_);
   expand_->Reset();
   last_mode_ = kModeRfc3389Cng;
   if (!play_dtmf) {
@@ -1492,8 +1485,7 @@
   return 0;
 }
 
-void NetEqImpl::DoCodecInternalCng(
-    AudioMultiVector<int16_t>* algorithm_buffer) {
+void NetEqImpl::DoCodecInternalCng() {
   int length = 0;
   // TODO(hlundin): Will probably need a longer buffer for multi-channel.
   int16_t decoded_buffer[kMaxFrameSize];
@@ -1506,13 +1498,12 @@
   Normal normal(fs_hz_, decoder_database_.get(), *background_noise_, expand_);
   assert(mute_factor_array_.get());
   normal.Process(decoded_buffer, length, last_mode_, mute_factor_array_.get(),
-                 algorithm_buffer);
+                 algorithm_buffer_);
   last_mode_ = kModeCodecInternalCng;
   expand_->Reset();
 }
 
-int NetEqImpl::DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf,
-                      AudioMultiVector<int16_t>* algorithm_buffer) {
+int NetEqImpl::DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf) {
   // This block of the code and the block further down, handling |dtmf_switch|
   // are commented out. Otherwise playing out-of-band DTMF would fail in VoE
   // test, DtmfTest.ManualSuccessfullySendsOutOfBandTelephoneEvents. This is
@@ -1540,11 +1531,11 @@
   if (dtmf_return_value == 0) {
     // Generate DTMF signal.
     dtmf_return_value = dtmf_tone_generator_->Generate(output_size_samples_,
-                                                       algorithm_buffer);
+                                                       algorithm_buffer_);
   }
 
   if (dtmf_return_value < 0) {
-    algorithm_buffer->Zeros(output_size_samples_);
+    algorithm_buffer_->Zeros(output_size_samples_);
     return dtmf_return_value;
   }
 
@@ -1562,10 +1553,10 @@
   //    int required_length = sync_buffer_->FutureLength();
   //    assert(dtmf_tone_generator_->initialized());
   //    dtmf_return_value = dtmf_tone_generator_->Generate(required_length,
-  //                                                       algorithm_buffer);
-  //    assert((size_t) required_length == algorithm_buffer->Size());
+  //                                                       algorithm_buffer_);
+  //    assert((size_t) required_length == algorithm_buffer_->Size());
   //    if (dtmf_return_value < 0) {
-  //      algorithm_buffer->Zeros(output_size_samples_);
+  //      algorithm_buffer_->Zeros(output_size_samples_);
   //      return dtmf_return_value;
   //    }
   //
@@ -1573,13 +1564,13 @@
   //    // data.
   //    // TODO(hlundin): It seems that this overwriting has gone lost.
   //    // Not adapted for multi-channel yet.
-  //    assert(algorithm_buffer->Channels() == 1);
-  //    if (algorithm_buffer->Channels() != 1) {
+  //    assert(algorithm_buffer_->Channels() == 1);
+  //    if (algorithm_buffer_->Channels() != 1) {
   //      LOG(LS_WARNING) << "DTMF not supported for more than one channel";
   //      return kStereoNotSupported;
   //    }
   //    // Shuffle the remaining data to the beginning of algorithm buffer.
-  //    algorithm_buffer->PopFront(sync_buffer_->FutureLength());
+  //    algorithm_buffer_->PopFront(sync_buffer_->FutureLength());
   //  }
 
   sync_buffer_->IncreaseEndTimestamp(output_size_samples_);
@@ -1591,8 +1582,7 @@
   return 0;
 }
 
-void NetEqImpl::DoAlternativePlc(bool increase_timestamp,
-                                 AudioMultiVector<int16_t>* algorithm_buffer) {
+void NetEqImpl::DoAlternativePlc(bool increase_timestamp) {
   AudioDecoder* decoder = decoder_database_->GetActiveDecoder();
   int length;
   if (decoder && decoder->HasDecodePlc()) {
@@ -1601,14 +1591,14 @@
     int16_t decoded_buffer[kMaxFrameSize];
     length = decoder->DecodePlc(1, decoded_buffer);
     if (length > 0) {
-      algorithm_buffer->PushBackInterleaved(decoded_buffer, length);
+      algorithm_buffer_->PushBackInterleaved(decoded_buffer, length);
     } else {
       length = 0;
     }
   } else {
     // Do simple zero-stuffing.
     length = output_size_samples_;
-    algorithm_buffer->Zeros(length);
+    algorithm_buffer_->Zeros(length);
     // By not advancing the timestamp, NetEq inserts samples.
     stats_.AddZeros(length);
   }
@@ -1756,6 +1746,12 @@
   assert(vad_.get());  // Cannot be NULL here.
   vad_->Init();
 
+  // Delete algorithm buffer and create a new one.
+  if (algorithm_buffer_) {
+    delete algorithm_buffer_;
+  }
+  algorithm_buffer_ = new AudioMultiVector<int16_t>(channels);
+
   // Delete sync buffer and create a new one.
   if (sync_buffer_) {
     delete sync_buffer_;
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_impl.h b/webrtc/modules/audio_coding/neteq4/neteq_impl.h
index 56dde77..b000961 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_impl.h
+++ b/webrtc/modules/audio_coding/neteq4/neteq_impl.h
@@ -222,49 +222,42 @@
 
   // Sub-method which calls the Normal class to perform the normal operation.
   void DoNormal(const int16_t* decoded_buffer, size_t decoded_length,
-                AudioDecoder::SpeechType speech_type, bool play_dtmf,
-                AudioMultiVector<int16_t>* algorithm_buffer);
+                AudioDecoder::SpeechType speech_type, bool play_dtmf);
 
   // Sub-method which calls the Merge class to perform the merge operation.
   void DoMerge(int16_t* decoded_buffer, size_t decoded_length,
-               AudioDecoder::SpeechType speech_type, bool play_dtmf,
-               AudioMultiVector<int16_t>* algorithm_buffer);
+               AudioDecoder::SpeechType speech_type, bool play_dtmf);
 
   // Sub-method which calls the Expand class to perform the expand operation.
-  int DoExpand(bool play_dtmf, AudioMultiVector<int16_t>* algorithm_buffer);
+  int DoExpand(bool play_dtmf);
 
   // Sub-method which calls the Accelerate class to perform the accelerate
   // operation.
   int DoAccelerate(int16_t* decoded_buffer, size_t decoded_length,
-                   AudioDecoder::SpeechType speech_type, bool play_dtmf,
-                   AudioMultiVector<int16_t>* algorithm_buffer);
+                   AudioDecoder::SpeechType speech_type, bool play_dtmf);
 
   // Sub-method which calls the PreemptiveExpand class to perform the
   // preemtive expand operation.
   int DoPreemptiveExpand(int16_t* decoded_buffer, size_t decoded_length,
-                         AudioDecoder::SpeechType speech_type, bool play_dtmf,
-                         AudioMultiVector<int16_t>* algorithm_buffer);
+                         AudioDecoder::SpeechType speech_type, bool play_dtmf);
 
   // Sub-method which calls the ComfortNoise class to generate RFC 3389 comfort
   // noise. |packet_list| can either contain one SID frame to update the
   // noise parameters, or no payload at all, in which case the previously
   // received parameters are used.
-  int DoRfc3389Cng(PacketList* packet_list, bool play_dtmf,
-                   AudioMultiVector<int16_t>* algorithm_buffer);
+  int DoRfc3389Cng(PacketList* packet_list, bool play_dtmf);
 
   // Calls the audio decoder to generate codec-internal comfort noise when
   // no packet was received.
-  void DoCodecInternalCng(AudioMultiVector<int16_t>* algorithm_buffer);
+  void DoCodecInternalCng();
 
   // Calls the DtmfToneGenerator class to generate DTMF tones.
-  int DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf,
-             AudioMultiVector<int16_t>* algorithm_buffer);
+  int DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf);
 
   // Produces packet-loss concealment using alternative methods. If the codec
   // has an internal PLC, it is called to generate samples. Otherwise, the
   // method performs zero-stuffing.
-  void DoAlternativePlc(bool increase_timestamp,
-                        AudioMultiVector<int16_t>* algorithm_buffer);
+  void DoAlternativePlc(bool increase_timestamp);
 
   // Overdub DTMF on top of |output|.
   int DtmfOverdub(const DtmfEvent& dtmf_event, size_t num_channels,
@@ -296,6 +289,7 @@
   scoped_ptr<TimestampScaler> timestamp_scaler_;
   scoped_ptr<DecisionLogic> decision_logic_;
   scoped_ptr<PostDecodeVad> vad_;
+  AudioMultiVector<int16_t>* algorithm_buffer_;
   SyncBuffer* sync_buffer_;
   Expand* expand_;
   RandomVector random_vector_;