LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/neteq - expand.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 498 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/audio_coding/neteq/expand.h"
      12             : 
      13             : #include <assert.h>
      14             : #include <string.h>  // memset
      15             : 
      16             : #include <algorithm>  // min, max
      17             : #include <limits>  // numeric_limits<T>
      18             : 
      19             : #include "webrtc/base/safe_conversions.h"
      20             : #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
      21             : #include "webrtc/modules/audio_coding/neteq/background_noise.h"
      22             : #include "webrtc/modules/audio_coding/neteq/cross_correlation.h"
      23             : #include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
      24             : #include "webrtc/modules/audio_coding/neteq/random_vector.h"
      25             : #include "webrtc/modules/audio_coding/neteq/statistics_calculator.h"
      26             : #include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
      27             : 
      28             : namespace webrtc {
      29             : 
      30           0 : Expand::Expand(BackgroundNoise* background_noise,
      31             :                SyncBuffer* sync_buffer,
      32             :                RandomVector* random_vector,
      33             :                StatisticsCalculator* statistics,
      34             :                int fs,
      35           0 :                size_t num_channels)
      36             :     : random_vector_(random_vector),
      37             :       sync_buffer_(sync_buffer),
      38             :       first_expand_(true),
      39             :       fs_hz_(fs),
      40             :       num_channels_(num_channels),
      41             :       consecutive_expands_(0),
      42             :       background_noise_(background_noise),
      43             :       statistics_(statistics),
      44           0 :       overlap_length_(5 * fs / 8000),
      45             :       lag_index_direction_(0),
      46             :       current_lag_index_(0),
      47             :       stop_muting_(false),
      48             :       expand_duration_samples_(0),
      49           0 :       channel_parameters_(new ChannelParameters[num_channels_]) {
      50           0 :   assert(fs == 8000 || fs == 16000 || fs == 32000 || fs == 48000);
      51           0 :   assert(fs <= static_cast<int>(kMaxSampleRate));  // Should not be possible.
      52           0 :   assert(num_channels_ > 0);
      53           0 :   memset(expand_lags_, 0, sizeof(expand_lags_));
      54           0 :   Reset();
      55           0 : }
      56             : 
      57             : Expand::~Expand() = default;
      58             : 
      59           0 : void Expand::Reset() {
      60           0 :   first_expand_ = true;
      61           0 :   consecutive_expands_ = 0;
      62           0 :   max_lag_ = 0;
      63           0 :   for (size_t ix = 0; ix < num_channels_; ++ix) {
      64           0 :     channel_parameters_[ix].expand_vector0.Clear();
      65           0 :     channel_parameters_[ix].expand_vector1.Clear();
      66             :   }
      67           0 : }
      68             : 
      69           0 : int Expand::Process(AudioMultiVector* output) {
      70             :   int16_t random_vector[kMaxSampleRate / 8000 * 120 + 30];
      71             :   int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125];
      72             :   static const int kTempDataSize = 3600;
      73             :   int16_t temp_data[kTempDataSize];  // TODO(hlundin) Remove this.
      74           0 :   int16_t* voiced_vector_storage = temp_data;
      75           0 :   int16_t* voiced_vector = &voiced_vector_storage[overlap_length_];
      76             :   static const size_t kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder;
      77             :   int16_t unvoiced_array_memory[kNoiseLpcOrder + kMaxSampleRate / 8000 * 125];
      78           0 :   int16_t* unvoiced_vector = unvoiced_array_memory + kUnvoicedLpcOrder;
      79           0 :   int16_t* noise_vector = unvoiced_array_memory + kNoiseLpcOrder;
      80             : 
      81           0 :   int fs_mult = fs_hz_ / 8000;
      82             : 
      83           0 :   if (first_expand_) {
      84             :     // Perform initial setup if this is the first expansion since last reset.
      85           0 :     AnalyzeSignal(random_vector);
      86           0 :     first_expand_ = false;
      87           0 :     expand_duration_samples_ = 0;
      88             :   } else {
      89             :     // This is not the first expansion, parameters are already estimated.
      90             :     // Extract a noise segment.
      91           0 :     size_t rand_length = max_lag_;
      92             :     // This only applies to SWB where length could be larger than 256.
      93           0 :     assert(rand_length <= kMaxSampleRate / 8000 * 120 + 30);
      94           0 :     GenerateRandomVector(2, rand_length, random_vector);
      95             :   }
      96             : 
      97             : 
      98             :   // Generate signal.
      99           0 :   UpdateLagIndex();
     100             : 
     101             :   // Voiced part.
     102             :   // Generate a weighted vector with the current lag.
     103           0 :   size_t expansion_vector_length = max_lag_ + overlap_length_;
     104           0 :   size_t current_lag = expand_lags_[current_lag_index_];
     105             :   // Copy lag+overlap data.
     106           0 :   size_t expansion_vector_position = expansion_vector_length - current_lag -
     107           0 :       overlap_length_;
     108           0 :   size_t temp_length = current_lag + overlap_length_;
     109           0 :   for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
     110           0 :     ChannelParameters& parameters = channel_parameters_[channel_ix];
     111           0 :     if (current_lag_index_ == 0) {
     112             :       // Use only expand_vector0.
     113           0 :       assert(expansion_vector_position + temp_length <=
     114           0 :              parameters.expand_vector0.Size());
     115           0 :       parameters.expand_vector0.CopyTo(temp_length, expansion_vector_position,
     116           0 :                                        voiced_vector_storage);
     117           0 :     } else if (current_lag_index_ == 1) {
     118           0 :       std::unique_ptr<int16_t[]> temp_0(new int16_t[temp_length]);
     119           0 :       parameters.expand_vector0.CopyTo(temp_length, expansion_vector_position,
     120           0 :                                        temp_0.get());
     121           0 :       std::unique_ptr<int16_t[]> temp_1(new int16_t[temp_length]);
     122           0 :       parameters.expand_vector1.CopyTo(temp_length, expansion_vector_position,
     123           0 :                                        temp_1.get());
     124             :       // Mix 3/4 of expand_vector0 with 1/4 of expand_vector1.
     125           0 :       WebRtcSpl_ScaleAndAddVectorsWithRound(temp_0.get(), 3, temp_1.get(), 1, 2,
     126           0 :                                             voiced_vector_storage, temp_length);
     127           0 :     } else if (current_lag_index_ == 2) {
     128             :       // Mix 1/2 of expand_vector0 with 1/2 of expand_vector1.
     129           0 :       assert(expansion_vector_position + temp_length <=
     130           0 :              parameters.expand_vector0.Size());
     131           0 :       assert(expansion_vector_position + temp_length <=
     132           0 :              parameters.expand_vector1.Size());
     133             : 
     134           0 :       std::unique_ptr<int16_t[]> temp_0(new int16_t[temp_length]);
     135           0 :       parameters.expand_vector0.CopyTo(temp_length, expansion_vector_position,
     136           0 :                                        temp_0.get());
     137           0 :       std::unique_ptr<int16_t[]> temp_1(new int16_t[temp_length]);
     138           0 :       parameters.expand_vector1.CopyTo(temp_length, expansion_vector_position,
     139           0 :                                        temp_1.get());
     140           0 :       WebRtcSpl_ScaleAndAddVectorsWithRound(temp_0.get(), 1, temp_1.get(), 1, 1,
     141           0 :                                             voiced_vector_storage, temp_length);
     142             :     }
     143             : 
     144             :     // Get tapering window parameters. Values are in Q15.
     145             :     int16_t muting_window, muting_window_increment;
     146             :     int16_t unmuting_window, unmuting_window_increment;
     147           0 :     if (fs_hz_ == 8000) {
     148           0 :       muting_window = DspHelper::kMuteFactorStart8kHz;
     149           0 :       muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
     150           0 :       unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
     151           0 :       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
     152           0 :     } else if (fs_hz_ == 16000) {
     153           0 :       muting_window = DspHelper::kMuteFactorStart16kHz;
     154           0 :       muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
     155           0 :       unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
     156           0 :       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
     157           0 :     } else if (fs_hz_ == 32000) {
     158           0 :       muting_window = DspHelper::kMuteFactorStart32kHz;
     159           0 :       muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
     160           0 :       unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
     161           0 :       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
     162             :     } else {  // fs_ == 48000
     163           0 :       muting_window = DspHelper::kMuteFactorStart48kHz;
     164           0 :       muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
     165           0 :       unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
     166           0 :       unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
     167             :     }
     168             : 
     169             :     // Smooth the expanded if it has not been muted to a low amplitude and
     170             :     // |current_voice_mix_factor| is larger than 0.5.
     171           0 :     if ((parameters.mute_factor > 819) &&
     172           0 :         (parameters.current_voice_mix_factor > 8192)) {
     173           0 :       size_t start_ix = sync_buffer_->Size() - overlap_length_;
     174           0 :       for (size_t i = 0; i < overlap_length_; i++) {
     175             :         // Do overlap add between new vector and overlap.
     176           0 :         (*sync_buffer_)[channel_ix][start_ix + i] =
     177           0 :             (((*sync_buffer_)[channel_ix][start_ix + i] * muting_window) +
     178           0 :                 (((parameters.mute_factor * voiced_vector_storage[i]) >> 14) *
     179           0 :                     unmuting_window) + 16384) >> 15;
     180           0 :         muting_window += muting_window_increment;
     181           0 :         unmuting_window += unmuting_window_increment;
     182             :       }
     183           0 :     } else if (parameters.mute_factor == 0) {
     184             :       // The expanded signal will consist of only comfort noise if
     185             :       // mute_factor = 0. Set the output length to 15 ms for best noise
     186             :       // production.
     187             :       // TODO(hlundin): This has been disabled since the length of
     188             :       // parameters.expand_vector0 and parameters.expand_vector1 no longer
     189             :       // match with expand_lags_, causing invalid reads and writes. Is it a good
     190             :       // idea to enable this again, and solve the vector size problem?
     191             : //      max_lag_ = fs_mult * 120;
     192             : //      expand_lags_[0] = fs_mult * 120;
     193             : //      expand_lags_[1] = fs_mult * 120;
     194             : //      expand_lags_[2] = fs_mult * 120;
     195             :     }
     196             : 
     197             :     // Unvoiced part.
     198             :     // Filter |scaled_random_vector| through |ar_filter_|.
     199           0 :     memcpy(unvoiced_vector - kUnvoicedLpcOrder, parameters.ar_filter_state,
     200           0 :            sizeof(int16_t) * kUnvoicedLpcOrder);
     201           0 :     int32_t add_constant = 0;
     202           0 :     if (parameters.ar_gain_scale > 0) {
     203           0 :       add_constant = 1 << (parameters.ar_gain_scale - 1);
     204             :     }
     205           0 :     WebRtcSpl_AffineTransformVector(scaled_random_vector, random_vector,
     206           0 :                                     parameters.ar_gain, add_constant,
     207           0 :                                     parameters.ar_gain_scale,
     208           0 :                                     current_lag);
     209           0 :     WebRtcSpl_FilterARFastQ12(scaled_random_vector, unvoiced_vector,
     210             :                               parameters.ar_filter, kUnvoicedLpcOrder + 1,
     211           0 :                               current_lag);
     212           0 :     memcpy(parameters.ar_filter_state,
     213           0 :            &(unvoiced_vector[current_lag - kUnvoicedLpcOrder]),
     214           0 :            sizeof(int16_t) * kUnvoicedLpcOrder);
     215             : 
     216             :     // Combine voiced and unvoiced contributions.
     217             : 
     218             :     // Set a suitable cross-fading slope.
     219             :     // For lag =
     220             :     //   <= 31 * fs_mult            => go from 1 to 0 in about 8 ms;
     221             :     //  (>= 31 .. <= 63) * fs_mult  => go from 1 to 0 in about 16 ms;
     222             :     //   >= 64 * fs_mult            => go from 1 to 0 in about 32 ms.
     223             :     // temp_shift = getbits(max_lag_) - 5.
     224             :     int temp_shift =
     225           0 :         (31 - WebRtcSpl_NormW32(rtc::checked_cast<int32_t>(max_lag_))) - 5;
     226           0 :     int16_t mix_factor_increment = 256 >> temp_shift;
     227           0 :     if (stop_muting_) {
     228           0 :       mix_factor_increment = 0;
     229             :     }
     230             : 
     231             :     // Create combined signal by shifting in more and more of unvoiced part.
     232           0 :     temp_shift = 8 - temp_shift;  // = getbits(mix_factor_increment).
     233           0 :     size_t temp_length = (parameters.current_voice_mix_factor -
     234           0 :         parameters.voice_mix_factor) >> temp_shift;
     235           0 :     temp_length = std::min(temp_length, current_lag);
     236           0 :     DspHelper::CrossFade(voiced_vector, unvoiced_vector, temp_length,
     237             :                          &parameters.current_voice_mix_factor,
     238           0 :                          mix_factor_increment, temp_data);
     239             : 
     240             :     // End of cross-fading period was reached before end of expanded signal
     241             :     // path. Mix the rest with a fixed mixing factor.
     242           0 :     if (temp_length < current_lag) {
     243           0 :       if (mix_factor_increment != 0) {
     244           0 :         parameters.current_voice_mix_factor = parameters.voice_mix_factor;
     245             :       }
     246           0 :       int16_t temp_scale = 16384 - parameters.current_voice_mix_factor;
     247           0 :       WebRtcSpl_ScaleAndAddVectorsWithRound(
     248           0 :           voiced_vector + temp_length, parameters.current_voice_mix_factor,
     249           0 :           unvoiced_vector + temp_length, temp_scale, 14,
     250           0 :           temp_data + temp_length, current_lag - temp_length);
     251             :     }
     252             : 
     253             :     // Select muting slope depending on how many consecutive expands we have
     254             :     // done.
     255           0 :     if (consecutive_expands_ == 3) {
     256             :       // Let the mute factor decrease from 1.0 to 0.95 in 6.25 ms.
     257             :       // mute_slope = 0.0010 / fs_mult in Q20.
     258           0 :       parameters.mute_slope = std::max(parameters.mute_slope, 1049 / fs_mult);
     259             :     }
     260           0 :     if (consecutive_expands_ == 7) {
     261             :       // Let the mute factor decrease from 1.0 to 0.90 in 6.25 ms.
     262             :       // mute_slope = 0.0020 / fs_mult in Q20.
     263           0 :       parameters.mute_slope = std::max(parameters.mute_slope, 2097 / fs_mult);
     264             :     }
     265             : 
     266             :     // Mute segment according to slope value.
     267           0 :     if ((consecutive_expands_ != 0) || !parameters.onset) {
     268             :       // Mute to the previous level, then continue with the muting.
     269           0 :       WebRtcSpl_AffineTransformVector(temp_data, temp_data,
     270           0 :                                       parameters.mute_factor, 8192,
     271           0 :                                       14, current_lag);
     272             : 
     273           0 :       if (!stop_muting_) {
     274           0 :         DspHelper::MuteSignal(temp_data, parameters.mute_slope, current_lag);
     275             : 
     276             :         // Shift by 6 to go from Q20 to Q14.
     277             :         // TODO(hlundin): Adding 8192 before shifting 6 steps seems wrong.
     278             :         // Legacy.
     279           0 :         int16_t gain = static_cast<int16_t>(16384 -
     280           0 :             (((current_lag * parameters.mute_slope) + 8192) >> 6));
     281           0 :         gain = ((gain * parameters.mute_factor) + 8192) >> 14;
     282             : 
     283             :         // Guard against getting stuck with very small (but sometimes audible)
     284             :         // gain.
     285           0 :         if ((consecutive_expands_ > 3) && (gain >= parameters.mute_factor)) {
     286           0 :           parameters.mute_factor = 0;
     287             :         } else {
     288           0 :           parameters.mute_factor = gain;
     289             :         }
     290             :       }
     291             :     }
     292             : 
     293             :     // Background noise part.
     294           0 :     GenerateBackgroundNoise(random_vector,
     295             :                             channel_ix,
     296           0 :                             channel_parameters_[channel_ix].mute_slope,
     297           0 :                             TooManyExpands(),
     298             :                             current_lag,
     299           0 :                             unvoiced_array_memory);
     300             : 
     301             :     // Add background noise to the combined voiced-unvoiced signal.
     302           0 :     for (size_t i = 0; i < current_lag; i++) {
     303           0 :       temp_data[i] = temp_data[i] + noise_vector[i];
     304             :     }
     305           0 :     if (channel_ix == 0) {
     306           0 :       output->AssertSize(current_lag);
     307             :     } else {
     308           0 :       assert(output->Size() == current_lag);
     309             :     }
     310           0 :     (*output)[channel_ix].OverwriteAt(temp_data, current_lag, 0);
     311             :   }
     312             : 
     313             :   // Increase call number and cap it.
     314           0 :   consecutive_expands_ = consecutive_expands_ >= kMaxConsecutiveExpands ?
     315           0 :       kMaxConsecutiveExpands : consecutive_expands_ + 1;
     316           0 :   expand_duration_samples_ += output->Size();
     317             :   // Clamp the duration counter at 2 seconds.
     318           0 :   expand_duration_samples_ =
     319           0 :       std::min(expand_duration_samples_, rtc::checked_cast<size_t>(fs_hz_ * 2));
     320           0 :   return 0;
     321             : }
     322             : 
     323           0 : void Expand::SetParametersForNormalAfterExpand() {
     324           0 :   current_lag_index_ = 0;
     325           0 :   lag_index_direction_ = 0;
     326           0 :   stop_muting_ = true;  // Do not mute signal any more.
     327           0 :   statistics_->LogDelayedPacketOutageEvent(
     328           0 :       rtc::checked_cast<int>(expand_duration_samples_) / (fs_hz_ / 1000));
     329           0 : }
     330             : 
     331           0 : void Expand::SetParametersForMergeAfterExpand() {
     332           0 :   current_lag_index_ = -1; /* out of the 3 possible ones */
     333           0 :   lag_index_direction_ = 1; /* make sure we get the "optimal" lag */
     334           0 :   stop_muting_ = true;
     335           0 : }
     336             : 
     337           0 : bool Expand::Muted() const {
     338           0 :   if (first_expand_ || stop_muting_)
     339           0 :     return false;
     340           0 :   RTC_DCHECK(channel_parameters_);
     341           0 :   for (size_t ch = 0; ch < num_channels_; ++ch) {
     342           0 :     if (channel_parameters_[ch].mute_factor != 0)
     343           0 :       return false;
     344             :   }
     345           0 :   return true;
     346             : }
     347             : 
     348           0 : size_t Expand::overlap_length() const {
     349           0 :   return overlap_length_;
     350             : }
     351             : 
     352           0 : void Expand::InitializeForAnExpandPeriod() {
     353           0 :   lag_index_direction_ = 1;
     354           0 :   current_lag_index_ = -1;
     355           0 :   stop_muting_ = false;
     356           0 :   random_vector_->set_seed_increment(1);
     357           0 :   consecutive_expands_ = 0;
     358           0 :   for (size_t ix = 0; ix < num_channels_; ++ix) {
     359           0 :     channel_parameters_[ix].current_voice_mix_factor = 16384;  // 1.0 in Q14.
     360           0 :     channel_parameters_[ix].mute_factor = 16384;  // 1.0 in Q14.
     361             :     // Start with 0 gain for background noise.
     362           0 :     background_noise_->SetMuteFactor(ix, 0);
     363             :   }
     364           0 : }
     365             : 
     366           0 : bool Expand::TooManyExpands() {
     367           0 :   return consecutive_expands_ >= kMaxConsecutiveExpands;
     368             : }
     369             : 
     370           0 : void Expand::AnalyzeSignal(int16_t* random_vector) {
     371             :   int32_t auto_correlation[kUnvoicedLpcOrder + 1];
     372             :   int16_t reflection_coeff[kUnvoicedLpcOrder];
     373             :   int16_t correlation_vector[kMaxSampleRate / 8000 * 102];
     374             :   size_t best_correlation_index[kNumCorrelationCandidates];
     375             :   int16_t best_correlation[kNumCorrelationCandidates];
     376             :   size_t best_distortion_index[kNumCorrelationCandidates];
     377             :   int16_t best_distortion[kNumCorrelationCandidates];
     378             :   int32_t correlation_vector2[(99 * kMaxSampleRate / 8000) + 1];
     379             :   int32_t best_distortion_w32[kNumCorrelationCandidates];
     380             :   static const size_t kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder;
     381             :   int16_t unvoiced_array_memory[kNoiseLpcOrder + kMaxSampleRate / 8000 * 125];
     382           0 :   int16_t* unvoiced_vector = unvoiced_array_memory + kUnvoicedLpcOrder;
     383             : 
     384           0 :   int fs_mult = fs_hz_ / 8000;
     385             : 
     386             :   // Pre-calculate common multiplications with fs_mult.
     387           0 :   size_t fs_mult_4 = static_cast<size_t>(fs_mult * 4);
     388           0 :   size_t fs_mult_20 = static_cast<size_t>(fs_mult * 20);
     389           0 :   size_t fs_mult_120 = static_cast<size_t>(fs_mult * 120);
     390           0 :   size_t fs_mult_dist_len = fs_mult * kDistortionLength;
     391           0 :   size_t fs_mult_lpc_analysis_len = fs_mult * kLpcAnalysisLength;
     392             : 
     393           0 :   const size_t signal_length = static_cast<size_t>(256 * fs_mult);
     394             : 
     395           0 :   const size_t audio_history_position = sync_buffer_->Size() - signal_length;
     396           0 :   std::unique_ptr<int16_t[]> audio_history(new int16_t[signal_length]);
     397           0 :   (*sync_buffer_)[0].CopyTo(signal_length, audio_history_position,
     398           0 :                             audio_history.get());
     399             : 
     400             :   // Initialize.
     401           0 :   InitializeForAnExpandPeriod();
     402             : 
     403             :   // Calculate correlation in downsampled domain (4 kHz sample rate).
     404           0 :   size_t correlation_length = 51;  // TODO(hlundin): Legacy bit-exactness.
     405             :   // If it is decided to break bit-exactness |correlation_length| should be
     406             :   // initialized to the return value of Correlation().
     407           0 :   Correlation(audio_history.get(), signal_length, correlation_vector);
     408             : 
     409             :   // Find peaks in correlation vector.
     410             :   DspHelper::PeakDetection(correlation_vector, correlation_length,
     411             :                            kNumCorrelationCandidates, fs_mult,
     412           0 :                            best_correlation_index, best_correlation);
     413             : 
     414             :   // Adjust peak locations; cross-correlation lags start at 2.5 ms
     415             :   // (20 * fs_mult samples).
     416           0 :   best_correlation_index[0] += fs_mult_20;
     417           0 :   best_correlation_index[1] += fs_mult_20;
     418           0 :   best_correlation_index[2] += fs_mult_20;
     419             : 
     420             :   // Calculate distortion around the |kNumCorrelationCandidates| best lags.
     421           0 :   int distortion_scale = 0;
     422           0 :   for (size_t i = 0; i < kNumCorrelationCandidates; i++) {
     423             :     size_t min_index = std::max(fs_mult_20,
     424           0 :                                 best_correlation_index[i] - fs_mult_4);
     425           0 :     size_t max_index = std::min(fs_mult_120 - 1,
     426           0 :                                 best_correlation_index[i] + fs_mult_4);
     427           0 :     best_distortion_index[i] = DspHelper::MinDistortion(
     428           0 :         &(audio_history[signal_length - fs_mult_dist_len]), min_index,
     429             :         max_index, fs_mult_dist_len, &best_distortion_w32[i]);
     430           0 :     distortion_scale = std::max(16 - WebRtcSpl_NormW32(best_distortion_w32[i]),
     431           0 :                                 distortion_scale);
     432             :   }
     433             :   // Shift the distortion values to fit in 16 bits.
     434             :   WebRtcSpl_VectorBitShiftW32ToW16(best_distortion, kNumCorrelationCandidates,
     435           0 :                                    best_distortion_w32, distortion_scale);
     436             : 
     437             :   // Find the maximizing index |i| of the cost function
     438             :   // f[i] = best_correlation[i] / best_distortion[i].
     439           0 :   int32_t best_ratio = std::numeric_limits<int32_t>::min();
     440           0 :   size_t best_index = std::numeric_limits<size_t>::max();
     441           0 :   for (size_t i = 0; i < kNumCorrelationCandidates; ++i) {
     442             :     int32_t ratio;
     443           0 :     if (best_distortion[i] > 0) {
     444           0 :       ratio = (best_correlation[i] * (1 << 16)) / best_distortion[i];
     445           0 :     } else if (best_correlation[i] == 0) {
     446           0 :       ratio = 0;  // No correlation set result to zero.
     447             :     } else {
     448           0 :       ratio = std::numeric_limits<int32_t>::max();  // Denominator is zero.
     449             :     }
     450           0 :     if (ratio > best_ratio) {
     451           0 :       best_index = i;
     452           0 :       best_ratio = ratio;
     453             :     }
     454             :   }
     455             : 
     456           0 :   size_t distortion_lag = best_distortion_index[best_index];
     457           0 :   size_t correlation_lag = best_correlation_index[best_index];
     458           0 :   max_lag_ = std::max(distortion_lag, correlation_lag);
     459             : 
     460             :   // Calculate the exact best correlation in the range between
     461             :   // |correlation_lag| and |distortion_lag|.
     462           0 :   correlation_length =
     463           0 :       std::max(std::min(distortion_lag + 10, fs_mult_120),
     464           0 :                static_cast<size_t>(60 * fs_mult));
     465             : 
     466           0 :   size_t start_index = std::min(distortion_lag, correlation_lag);
     467             :   size_t correlation_lags = static_cast<size_t>(
     468           0 :       WEBRTC_SPL_ABS_W16((distortion_lag-correlation_lag)) + 1);
     469           0 :   assert(correlation_lags <= static_cast<size_t>(99 * fs_mult + 1));
     470             : 
     471           0 :   for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
     472           0 :     ChannelParameters& parameters = channel_parameters_[channel_ix];
     473             :     // Calculate suitable scaling.
     474           0 :     int16_t signal_max = WebRtcSpl_MaxAbsValueW16(
     475           0 :         &audio_history[signal_length - correlation_length - start_index
     476           0 :                        - correlation_lags],
     477           0 :                        correlation_length + start_index + correlation_lags - 1);
     478           0 :     int correlation_scale = (31 - WebRtcSpl_NormW32(signal_max * signal_max)) +
     479           0 :         (31 - WebRtcSpl_NormW32(static_cast<int32_t>(correlation_length))) - 31;
     480           0 :     correlation_scale = std::max(0, correlation_scale);
     481             : 
     482             :     // Calculate the correlation, store in |correlation_vector2|.
     483             :     WebRtcSpl_CrossCorrelation(
     484             :         correlation_vector2,
     485           0 :         &(audio_history[signal_length - correlation_length]),
     486           0 :         &(audio_history[signal_length - correlation_length - start_index]),
     487           0 :         correlation_length, correlation_lags, correlation_scale, -1);
     488             : 
     489             :     // Find maximizing index.
     490           0 :     best_index = WebRtcSpl_MaxIndexW32(correlation_vector2, correlation_lags);
     491           0 :     int32_t max_correlation = correlation_vector2[best_index];
     492             :     // Compensate index with start offset.
     493           0 :     best_index = best_index + start_index;
     494             : 
     495             :     // Calculate energies.
     496           0 :     int32_t energy1 = WebRtcSpl_DotProductWithScale(
     497           0 :         &(audio_history[signal_length - correlation_length]),
     498           0 :         &(audio_history[signal_length - correlation_length]),
     499           0 :         correlation_length, correlation_scale);
     500           0 :     int32_t energy2 = WebRtcSpl_DotProductWithScale(
     501           0 :         &(audio_history[signal_length - correlation_length - best_index]),
     502           0 :         &(audio_history[signal_length - correlation_length - best_index]),
     503           0 :         correlation_length, correlation_scale);
     504             : 
     505             :     // Calculate the correlation coefficient between the two portions of the
     506             :     // signal.
     507             :     int32_t corr_coefficient;
     508           0 :     if ((energy1 > 0) && (energy2 > 0)) {
     509           0 :       int energy1_scale = std::max(16 - WebRtcSpl_NormW32(energy1), 0);
     510           0 :       int energy2_scale = std::max(16 - WebRtcSpl_NormW32(energy2), 0);
     511             :       // Make sure total scaling is even (to simplify scale factor after sqrt).
     512           0 :       if ((energy1_scale + energy2_scale) & 1) {
     513             :         // If sum is odd, add 1 to make it even.
     514           0 :         energy1_scale += 1;
     515             :       }
     516           0 :       int32_t scaled_energy1 = energy1 >> energy1_scale;
     517           0 :       int32_t scaled_energy2 = energy2 >> energy2_scale;
     518             :       int16_t sqrt_energy_product = static_cast<int16_t>(
     519           0 :           WebRtcSpl_SqrtFloor(scaled_energy1 * scaled_energy2));
     520             :       // Calculate max_correlation / sqrt(energy1 * energy2) in Q14.
     521           0 :       int cc_shift = 14 - (energy1_scale + energy2_scale) / 2;
     522           0 :       max_correlation = WEBRTC_SPL_SHIFT_W32(max_correlation, cc_shift);
     523           0 :       corr_coefficient = WebRtcSpl_DivW32W16(max_correlation,
     524             :                                              sqrt_energy_product);
     525             :       // Cap at 1.0 in Q14.
     526           0 :       corr_coefficient = std::min(16384, corr_coefficient);
     527             :     } else {
     528           0 :       corr_coefficient = 0;
     529             :     }
     530             : 
     531             :     // Extract the two vectors expand_vector0 and expand_vector1 from
     532             :     // |audio_history|.
     533           0 :     size_t expansion_length = max_lag_ + overlap_length_;
     534           0 :     const int16_t* vector1 = &(audio_history[signal_length - expansion_length]);
     535           0 :     const int16_t* vector2 = vector1 - distortion_lag;
     536             :     // Normalize the second vector to the same energy as the first.
     537           0 :     energy1 = WebRtcSpl_DotProductWithScale(vector1, vector1, expansion_length,
     538           0 :                                             correlation_scale);
     539           0 :     energy2 = WebRtcSpl_DotProductWithScale(vector2, vector2, expansion_length,
     540           0 :                                             correlation_scale);
     541             :     // Confirm that amplitude ratio sqrt(energy1 / energy2) is within 0.5 - 2.0,
     542             :     // i.e., energy1 / energy2 is within 0.25 - 4.
     543             :     int16_t amplitude_ratio;
     544           0 :     if ((energy1 / 4 < energy2) && (energy1 > energy2 / 4)) {
     545             :       // Energy constraint fulfilled. Use both vectors and scale them
     546             :       // accordingly.
     547           0 :       int32_t scaled_energy2 = std::max(16 - WebRtcSpl_NormW32(energy2), 0);
     548           0 :       int32_t scaled_energy1 = scaled_energy2 - 13;
     549             :       // Calculate scaled_energy1 / scaled_energy2 in Q13.
     550           0 :       int32_t energy_ratio = WebRtcSpl_DivW32W16(
     551           0 :           WEBRTC_SPL_SHIFT_W32(energy1, -scaled_energy1),
     552           0 :           static_cast<int16_t>(energy2 >> scaled_energy2));
     553             :       // Calculate sqrt ratio in Q13 (sqrt of en1/en2 in Q26).
     554           0 :       amplitude_ratio =
     555           0 :           static_cast<int16_t>(WebRtcSpl_SqrtFloor(energy_ratio << 13));
     556             :       // Copy the two vectors and give them the same energy.
     557           0 :       parameters.expand_vector0.Clear();
     558           0 :       parameters.expand_vector0.PushBack(vector1, expansion_length);
     559           0 :       parameters.expand_vector1.Clear();
     560           0 :       if (parameters.expand_vector1.Size() < expansion_length) {
     561           0 :         parameters.expand_vector1.Extend(
     562           0 :             expansion_length - parameters.expand_vector1.Size());
     563             :       }
     564           0 :       std::unique_ptr<int16_t[]> temp_1(new int16_t[expansion_length]);
     565           0 :       WebRtcSpl_AffineTransformVector(temp_1.get(),
     566             :                                       const_cast<int16_t*>(vector2),
     567             :                                       amplitude_ratio,
     568             :                                       4096,
     569             :                                       13,
     570           0 :                                       expansion_length);
     571           0 :       parameters.expand_vector1.OverwriteAt(temp_1.get(), expansion_length, 0);
     572             :     } else {
     573             :       // Energy change constraint not fulfilled. Only use last vector.
     574           0 :       parameters.expand_vector0.Clear();
     575           0 :       parameters.expand_vector0.PushBack(vector1, expansion_length);
     576             :       // Copy from expand_vector0 to expand_vector1.
     577           0 :       parameters.expand_vector0.CopyTo(&parameters.expand_vector1);
     578             :       // Set the energy_ratio since it is used by muting slope.
     579           0 :       if ((energy1 / 4 < energy2) || (energy2 == 0)) {
     580           0 :         amplitude_ratio = 4096;  // 0.5 in Q13.
     581             :       } else {
     582           0 :         amplitude_ratio = 16384;  // 2.0 in Q13.
     583             :       }
     584             :     }
     585             : 
     586             :     // Set the 3 lag values.
     587           0 :     if (distortion_lag == correlation_lag) {
     588           0 :       expand_lags_[0] = distortion_lag;
     589           0 :       expand_lags_[1] = distortion_lag;
     590           0 :       expand_lags_[2] = distortion_lag;
     591             :     } else {
     592             :       // |distortion_lag| and |correlation_lag| are not equal; use different
     593             :       // combinations of the two.
     594             :       // First lag is |distortion_lag| only.
     595           0 :       expand_lags_[0] = distortion_lag;
     596             :       // Second lag is the average of the two.
     597           0 :       expand_lags_[1] = (distortion_lag + correlation_lag) / 2;
     598             :       // Third lag is the average again, but rounding towards |correlation_lag|.
     599           0 :       if (distortion_lag > correlation_lag) {
     600           0 :         expand_lags_[2] = (distortion_lag + correlation_lag - 1) / 2;
     601             :       } else {
     602           0 :         expand_lags_[2] = (distortion_lag + correlation_lag + 1) / 2;
     603             :       }
     604             :     }
     605             : 
     606             :     // Calculate the LPC and the gain of the filters.
     607             : 
     608             :     // Calculate kUnvoicedLpcOrder + 1 lags of the auto-correlation function.
     609           0 :     size_t temp_index = signal_length - fs_mult_lpc_analysis_len -
     610           0 :         kUnvoicedLpcOrder;
     611             :     // Copy signal to temporary vector to be able to pad with leading zeros.
     612             :     int16_t* temp_signal = new int16_t[fs_mult_lpc_analysis_len
     613           0 :                                        + kUnvoicedLpcOrder];
     614           0 :     memset(temp_signal, 0,
     615           0 :            sizeof(int16_t) * (fs_mult_lpc_analysis_len + kUnvoicedLpcOrder));
     616           0 :     memcpy(&temp_signal[kUnvoicedLpcOrder],
     617           0 :            &audio_history[temp_index + kUnvoicedLpcOrder],
     618           0 :            sizeof(int16_t) * fs_mult_lpc_analysis_len);
     619             :     CrossCorrelationWithAutoShift(
     620           0 :         &temp_signal[kUnvoicedLpcOrder], &temp_signal[kUnvoicedLpcOrder],
     621           0 :         fs_mult_lpc_analysis_len, kUnvoicedLpcOrder + 1, -1, auto_correlation);
     622           0 :     delete [] temp_signal;
     623             : 
     624             :     // Verify that variance is positive.
     625           0 :     if (auto_correlation[0] > 0) {
     626             :       // Estimate AR filter parameters using Levinson-Durbin algorithm;
     627             :       // kUnvoicedLpcOrder + 1 filter coefficients.
     628           0 :       int16_t stability = WebRtcSpl_LevinsonDurbin(auto_correlation,
     629             :                                                    parameters.ar_filter,
     630             :                                                    reflection_coeff,
     631           0 :                                                    kUnvoicedLpcOrder);
     632             : 
     633             :       // Keep filter parameters only if filter is stable.
     634           0 :       if (stability != 1) {
     635             :         // Set first coefficient to 4096 (1.0 in Q12).
     636           0 :         parameters.ar_filter[0] = 4096;
     637             :         // Set remaining |kUnvoicedLpcOrder| coefficients to zero.
     638           0 :         WebRtcSpl_MemSetW16(parameters.ar_filter + 1, 0, kUnvoicedLpcOrder);
     639             :       }
     640             :     }
     641             : 
     642           0 :     if (channel_ix == 0) {
     643             :       // Extract a noise segment.
     644             :       size_t noise_length;
     645           0 :       if (distortion_lag < 40) {
     646           0 :         noise_length = 2 * distortion_lag + 30;
     647             :       } else {
     648           0 :         noise_length = distortion_lag + 30;
     649             :       }
     650           0 :       if (noise_length <= RandomVector::kRandomTableSize) {
     651           0 :         memcpy(random_vector, RandomVector::kRandomTable,
     652           0 :                sizeof(int16_t) * noise_length);
     653             :       } else {
     654             :         // Only applies to SWB where length could be larger than
     655             :         // |kRandomTableSize|.
     656             :         memcpy(random_vector, RandomVector::kRandomTable,
     657           0 :                sizeof(int16_t) * RandomVector::kRandomTableSize);
     658           0 :         assert(noise_length <= kMaxSampleRate / 8000 * 120 + 30);
     659           0 :         random_vector_->IncreaseSeedIncrement(2);
     660           0 :         random_vector_->Generate(
     661             :             noise_length - RandomVector::kRandomTableSize,
     662           0 :             &random_vector[RandomVector::kRandomTableSize]);
     663             :       }
     664             :     }
     665             : 
     666             :     // Set up state vector and calculate scale factor for unvoiced filtering.
     667           0 :     memcpy(parameters.ar_filter_state,
     668           0 :            &(audio_history[signal_length - kUnvoicedLpcOrder]),
     669           0 :            sizeof(int16_t) * kUnvoicedLpcOrder);
     670           0 :     memcpy(unvoiced_vector - kUnvoicedLpcOrder,
     671           0 :            &(audio_history[signal_length - 128 - kUnvoicedLpcOrder]),
     672           0 :            sizeof(int16_t) * kUnvoicedLpcOrder);
     673           0 :     WebRtcSpl_FilterMAFastQ12(&audio_history[signal_length - 128],
     674             :                               unvoiced_vector,
     675             :                               parameters.ar_filter,
     676             :                               kUnvoicedLpcOrder + 1,
     677           0 :                               128);
     678           0 :     const int unvoiced_max_abs = [&] {
     679           0 :       const int16_t max_abs = WebRtcSpl_MaxAbsValueW16(unvoiced_vector, 128);
     680             :       // Since WebRtcSpl_MaxAbsValueW16 returns 2^15 - 1 when the input contains
     681             :       // -2^15, we have to conservatively bump the return value by 1
     682             :       // if it is 2^15 - 1.
     683           0 :       return max_abs == WEBRTC_SPL_WORD16_MAX ? max_abs + 1 : max_abs;
     684           0 :     }();
     685             :     // Pick the smallest n such that 2^n > unvoiced_max_abs; then the maximum
     686             :     // value of the dot product is less than 2^7 * 2^(2*n) = 2^(2*n + 7), so to
     687             :     // prevent overflows we want 2n + 7 <= 31, which means we should shift by
     688             :     // 2n + 7 - 31 bits, if this value is greater than zero.
     689             :     int unvoiced_prescale =
     690           0 :         std::max(0, 2 * WebRtcSpl_GetSizeInBits(unvoiced_max_abs) - 24);
     691             : 
     692           0 :     int32_t unvoiced_energy = WebRtcSpl_DotProductWithScale(unvoiced_vector,
     693             :                                                             unvoiced_vector,
     694             :                                                             128,
     695           0 :                                                             unvoiced_prescale);
     696             : 
     697             :     // Normalize |unvoiced_energy| to 28 or 29 bits to preserve sqrt() accuracy.
     698           0 :     int16_t unvoiced_scale = WebRtcSpl_NormW32(unvoiced_energy) - 3;
     699             :     // Make sure we do an odd number of shifts since we already have 7 shifts
     700             :     // from dividing with 128 earlier. This will make the total scale factor
     701             :     // even, which is suitable for the sqrt.
     702           0 :     unvoiced_scale += ((unvoiced_scale & 0x1) ^ 0x1);
     703           0 :     unvoiced_energy = WEBRTC_SPL_SHIFT_W32(unvoiced_energy, unvoiced_scale);
     704             :     int16_t unvoiced_gain =
     705           0 :         static_cast<int16_t>(WebRtcSpl_SqrtFloor(unvoiced_energy));
     706           0 :     parameters.ar_gain_scale = 13
     707           0 :         + (unvoiced_scale + 7 - unvoiced_prescale) / 2;
     708           0 :     parameters.ar_gain = unvoiced_gain;
     709             : 
     710             :     // Calculate voice_mix_factor from corr_coefficient.
     711             :     // Let x = corr_coefficient. Then, we compute:
     712             :     // if (x > 0.48)
     713             :     //   voice_mix_factor = (-5179 + 19931x - 16422x^2 + 5776x^3) / 4096;
     714             :     // else
     715             :     //   voice_mix_factor = 0;
     716           0 :     if (corr_coefficient > 7875) {
     717             :       int16_t x1, x2, x3;
     718             :       // |corr_coefficient| is in Q14.
     719           0 :       x1 = static_cast<int16_t>(corr_coefficient);
     720           0 :       x2 = (x1 * x1) >> 14;   // Shift 14 to keep result in Q14.
     721           0 :       x3 = (x1 * x2) >> 14;
     722             :       static const int kCoefficients[4] = { -5179, 19931, -16422, 5776 };
     723           0 :       int32_t temp_sum = kCoefficients[0] * 16384;
     724           0 :       temp_sum += kCoefficients[1] * x1;
     725           0 :       temp_sum += kCoefficients[2] * x2;
     726           0 :       temp_sum += kCoefficients[3] * x3;
     727           0 :       parameters.voice_mix_factor =
     728           0 :           static_cast<int16_t>(std::min(temp_sum / 4096, 16384));
     729           0 :       parameters.voice_mix_factor = std::max(parameters.voice_mix_factor,
     730           0 :                                              static_cast<int16_t>(0));
     731             :     } else {
     732           0 :       parameters.voice_mix_factor = 0;
     733             :     }
     734             : 
     735             :     // Calculate muting slope. Reuse value from earlier scaling of
     736             :     // |expand_vector0| and |expand_vector1|.
     737           0 :     int16_t slope = amplitude_ratio;
     738           0 :     if (slope > 12288) {
     739             :       // slope > 1.5.
     740             :       // Calculate (1 - (1 / slope)) / distortion_lag =
     741             :       // (slope - 1) / (distortion_lag * slope).
     742             :       // |slope| is in Q13, so 1 corresponds to 8192. Shift up to Q25 before
     743             :       // the division.
     744             :       // Shift the denominator from Q13 to Q5 before the division. The result of
     745             :       // the division will then be in Q20.
     746           0 :       int temp_ratio = WebRtcSpl_DivW32W16(
     747           0 :           (slope - 8192) << 12,
     748           0 :           static_cast<int16_t>((distortion_lag * slope) >> 8));
     749           0 :       if (slope > 14746) {
     750             :         // slope > 1.8.
     751             :         // Divide by 2, with proper rounding.
     752           0 :         parameters.mute_slope = (temp_ratio + 1) / 2;
     753             :       } else {
     754             :         // Divide by 8, with proper rounding.
     755           0 :         parameters.mute_slope = (temp_ratio + 4) / 8;
     756             :       }
     757           0 :       parameters.onset = true;
     758             :     } else {
     759             :       // Calculate (1 - slope) / distortion_lag.
     760             :       // Shift |slope| by 7 to Q20 before the division. The result is in Q20.
     761           0 :       parameters.mute_slope = WebRtcSpl_DivW32W16(
     762           0 :           (8192 - slope) * 128, static_cast<int16_t>(distortion_lag));
     763           0 :       if (parameters.voice_mix_factor <= 13107) {
     764             :         // Make sure the mute factor decreases from 1.0 to 0.9 in no more than
     765             :         // 6.25 ms.
     766             :         // mute_slope >= 0.005 / fs_mult in Q20.
     767           0 :         parameters.mute_slope = std::max(5243 / fs_mult, parameters.mute_slope);
     768           0 :       } else if (slope > 8028) {
     769           0 :         parameters.mute_slope = 0;
     770             :       }
     771           0 :       parameters.onset = false;
     772             :     }
     773             :   }
     774           0 : }
     775             : 
     776           0 : Expand::ChannelParameters::ChannelParameters()
     777             :     : mute_factor(16384),
     778             :       ar_gain(0),
     779             :       ar_gain_scale(0),
     780             :       voice_mix_factor(0),
     781             :       current_voice_mix_factor(0),
     782             :       onset(false),
     783           0 :       mute_slope(0) {
     784           0 :   memset(ar_filter, 0, sizeof(ar_filter));
     785           0 :   memset(ar_filter_state, 0, sizeof(ar_filter_state));
     786           0 : }
     787             : 
     788           0 : void Expand::Correlation(const int16_t* input,
     789             :                          size_t input_length,
     790             :                          int16_t* output) const {
     791             :   // Set parameters depending on sample rate.
     792             :   const int16_t* filter_coefficients;
     793             :   size_t num_coefficients;
     794             :   int16_t downsampling_factor;
     795           0 :   if (fs_hz_ == 8000) {
     796           0 :     num_coefficients = 3;
     797           0 :     downsampling_factor = 2;
     798           0 :     filter_coefficients = DspHelper::kDownsample8kHzTbl;
     799           0 :   } else if (fs_hz_ == 16000) {
     800           0 :     num_coefficients = 5;
     801           0 :     downsampling_factor = 4;
     802           0 :     filter_coefficients = DspHelper::kDownsample16kHzTbl;
     803           0 :   } else if (fs_hz_ == 32000) {
     804           0 :     num_coefficients = 7;
     805           0 :     downsampling_factor = 8;
     806           0 :     filter_coefficients = DspHelper::kDownsample32kHzTbl;
     807             :   } else {  // fs_hz_ == 48000.
     808           0 :     num_coefficients = 7;
     809           0 :     downsampling_factor = 12;
     810           0 :     filter_coefficients = DspHelper::kDownsample48kHzTbl;
     811             :   }
     812             : 
     813             :   // Correlate from lag 10 to lag 60 in downsampled domain.
     814             :   // (Corresponds to 20-120 for narrow-band, 40-240 for wide-band, and so on.)
     815             :   static const size_t kCorrelationStartLag = 10;
     816             :   static const size_t kNumCorrelationLags = 54;
     817             :   static const size_t kCorrelationLength = 60;
     818             :   // Downsample to 4 kHz sample rate.
     819             :   static const size_t kDownsampledLength = kCorrelationStartLag
     820             :       + kNumCorrelationLags + kCorrelationLength;
     821             :   int16_t downsampled_input[kDownsampledLength];
     822             :   static const size_t kFilterDelay = 0;
     823           0 :   WebRtcSpl_DownsampleFast(
     824           0 :       input + input_length - kDownsampledLength * downsampling_factor,
     825             :       kDownsampledLength * downsampling_factor, downsampled_input,
     826             :       kDownsampledLength, filter_coefficients, num_coefficients,
     827           0 :       downsampling_factor, kFilterDelay);
     828             : 
     829             :   // Normalize |downsampled_input| to using all 16 bits.
     830           0 :   int16_t max_value = WebRtcSpl_MaxAbsValueW16(downsampled_input,
     831           0 :                                                kDownsampledLength);
     832           0 :   int16_t norm_shift = 16 - WebRtcSpl_NormW32(max_value);
     833           0 :   WebRtcSpl_VectorBitShiftW16(downsampled_input, kDownsampledLength,
     834           0 :                               downsampled_input, norm_shift);
     835             : 
     836             :   int32_t correlation[kNumCorrelationLags];
     837             :   CrossCorrelationWithAutoShift(
     838             :       &downsampled_input[kDownsampledLength - kCorrelationLength],
     839             :       &downsampled_input[kDownsampledLength - kCorrelationLength
     840             :           - kCorrelationStartLag],
     841           0 :       kCorrelationLength, kNumCorrelationLags, -1, correlation);
     842             : 
     843             :   // Normalize and move data from 32-bit to 16-bit vector.
     844           0 :   int32_t max_correlation = WebRtcSpl_MaxAbsValueW32(correlation,
     845           0 :                                                      kNumCorrelationLags);
     846             :   int16_t norm_shift2 = static_cast<int16_t>(
     847           0 :       std::max(18 - WebRtcSpl_NormW32(max_correlation), 0));
     848           0 :   WebRtcSpl_VectorBitShiftW32ToW16(output, kNumCorrelationLags, correlation,
     849           0 :                                    norm_shift2);
     850           0 : }
     851             : 
     852           0 : void Expand::UpdateLagIndex() {
     853           0 :   current_lag_index_ = current_lag_index_ + lag_index_direction_;
     854             :   // Change direction if needed.
     855           0 :   if (current_lag_index_ <= 0) {
     856           0 :     lag_index_direction_ = 1;
     857             :   }
     858           0 :   if (current_lag_index_ >= kNumLags - 1) {
     859           0 :     lag_index_direction_ = -1;
     860             :   }
     861           0 : }
     862             : 
     863           0 : Expand* ExpandFactory::Create(BackgroundNoise* background_noise,
     864             :                               SyncBuffer* sync_buffer,
     865             :                               RandomVector* random_vector,
     866             :                               StatisticsCalculator* statistics,
     867             :                               int fs,
     868             :                               size_t num_channels) const {
     869             :   return new Expand(background_noise, sync_buffer, random_vector, statistics,
     870           0 :                     fs, num_channels);
     871             : }
     872             : 
     873             : // TODO(turajs): This can be moved to BackgroundNoise class.
     874           0 : void Expand::GenerateBackgroundNoise(int16_t* random_vector,
     875             :                                      size_t channel,
     876             :                                      int mute_slope,
     877             :                                      bool too_many_expands,
     878             :                                      size_t num_noise_samples,
     879             :                                      int16_t* buffer) {
     880             :   static const size_t kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder;
     881             :   int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125];
     882           0 :   assert(num_noise_samples <= (kMaxSampleRate / 8000 * 125));
     883           0 :   int16_t* noise_samples = &buffer[kNoiseLpcOrder];
     884           0 :   if (background_noise_->initialized()) {
     885             :     // Use background noise parameters.
     886           0 :     memcpy(noise_samples - kNoiseLpcOrder,
     887           0 :            background_noise_->FilterState(channel),
     888           0 :            sizeof(int16_t) * kNoiseLpcOrder);
     889             : 
     890           0 :     int dc_offset = 0;
     891           0 :     if (background_noise_->ScaleShift(channel) > 1) {
     892           0 :       dc_offset = 1 << (background_noise_->ScaleShift(channel) - 1);
     893             :     }
     894             : 
     895             :     // Scale random vector to correct energy level.
     896           0 :     WebRtcSpl_AffineTransformVector(
     897             :         scaled_random_vector, random_vector,
     898           0 :         background_noise_->Scale(channel), dc_offset,
     899           0 :         background_noise_->ScaleShift(channel),
     900           0 :         num_noise_samples);
     901             : 
     902           0 :     WebRtcSpl_FilterARFastQ12(scaled_random_vector, noise_samples,
     903           0 :                               background_noise_->Filter(channel),
     904             :                               kNoiseLpcOrder + 1,
     905           0 :                               num_noise_samples);
     906             : 
     907           0 :     background_noise_->SetFilterState(
     908             :         channel,
     909           0 :         &(noise_samples[num_noise_samples - kNoiseLpcOrder]),
     910           0 :         kNoiseLpcOrder);
     911             : 
     912             :     // Unmute the background noise.
     913           0 :     int16_t bgn_mute_factor = background_noise_->MuteFactor(channel);
     914           0 :     NetEq::BackgroundNoiseMode bgn_mode = background_noise_->mode();
     915           0 :     if (bgn_mode == NetEq::kBgnFade && too_many_expands &&
     916           0 :         bgn_mute_factor > 0) {
     917             :       // Fade BGN to zero.
     918             :       // Calculate muting slope, approximately -2^18 / fs_hz.
     919             :       int mute_slope;
     920           0 :       if (fs_hz_ == 8000) {
     921           0 :         mute_slope = -32;
     922           0 :       } else if (fs_hz_ == 16000) {
     923           0 :         mute_slope = -16;
     924           0 :       } else if (fs_hz_ == 32000) {
     925           0 :         mute_slope = -8;
     926             :       } else {
     927           0 :         mute_slope = -5;
     928             :       }
     929             :       // Use UnmuteSignal function with negative slope.
     930             :       // |bgn_mute_factor| is in Q14. |mute_slope| is in Q20.
     931             :       DspHelper::UnmuteSignal(noise_samples,
     932             :                               num_noise_samples,
     933             :                               &bgn_mute_factor,
     934             :                               mute_slope,
     935           0 :                               noise_samples);
     936           0 :     } else if (bgn_mute_factor < 16384) {
     937             :       // If mode is kBgnOn, or if kBgnFade has started fading,
     938             :       // use regular |mute_slope|.
     939           0 :       if (!stop_muting_ && bgn_mode != NetEq::kBgnOff &&
     940           0 :           !(bgn_mode == NetEq::kBgnFade && too_many_expands)) {
     941           0 :         DspHelper::UnmuteSignal(noise_samples,
     942             :                                 static_cast<int>(num_noise_samples),
     943             :                                 &bgn_mute_factor,
     944             :                                 mute_slope,
     945           0 :                                 noise_samples);
     946             :       } else {
     947             :         // kBgnOn and stop muting, or
     948             :         // kBgnOff (mute factor is always 0), or
     949             :         // kBgnFade has reached 0.
     950           0 :         WebRtcSpl_AffineTransformVector(noise_samples, noise_samples,
     951             :                                         bgn_mute_factor, 8192, 14,
     952           0 :                                         num_noise_samples);
     953             :       }
     954             :     }
     955             :     // Update mute_factor in BackgroundNoise class.
     956           0 :     background_noise_->SetMuteFactor(channel, bgn_mute_factor);
     957             :   } else {
     958             :     // BGN parameters have not been initialized; use zero noise.
     959           0 :     memset(noise_samples, 0, sizeof(int16_t) * num_noise_samples);
     960             :   }
     961           0 : }
     962             : 
     963           0 : void Expand::GenerateRandomVector(int16_t seed_increment,
     964             :                                   size_t length,
     965             :                                   int16_t* random_vector) {
     966             :   // TODO(turajs): According to hlundin The loop should not be needed. Should be
     967             :   // just as good to generate all of the vector in one call.
     968           0 :   size_t samples_generated = 0;
     969           0 :   const size_t kMaxRandSamples = RandomVector::kRandomTableSize;
     970           0 :   while (samples_generated < length) {
     971           0 :     size_t rand_length = std::min(length - samples_generated, kMaxRandSamples);
     972           0 :     random_vector_->IncreaseSeedIncrement(seed_increment);
     973           0 :     random_vector_->Generate(rand_length, &random_vector[samples_generated]);
     974           0 :     samples_generated += rand_length;
     975             :   }
     976           0 : }
     977             : 
     978             : }  // namespace webrtc

Generated by: LCOV version 1.13