19a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org/* 29a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 39a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * 49a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * Use of this source code is governed by a BSD-style license 59a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * that can be found in the LICENSE file in the root of the source 69a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * tree. An additional intellectual property rights grant can be found 79a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * in the file PATENTS. All contributing project authors may 89a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * be found in the AUTHORS file in the root of the source tree. 99a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org */ 109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 11e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/expand.h" 129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include <assert.h> 143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <string.h> // memset 159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include <algorithm> // min, max 1760bf21e85cdf9a8dd18376d934bde5e785ebba87turaj@webrtc.org#include <limits> // numeric_limits<T> 189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 20e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/background_noise.h" 21e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/dsp_helper.h" 22e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/random_vector.h" 23e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/sync_buffer.h" 249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgnamespace webrtc { 269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Expand::Reset() { 289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org first_expand_ = true; 299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org consecutive_expands_ = 0; 309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org max_lag_ = 0; 319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (size_t ix = 0; ix < num_channels_; ++ix) { 329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org channel_parameters_[ix].expand_vector0.Clear(); 339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org channel_parameters_[ix].expand_vector1.Clear(); 349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 370e9c399746f45ceaf46f12b11ba93c09cca0c2bbhenrik.lundin@webrtc.orgint Expand::Process(AudioMultiVector* output) { 389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t random_vector[kMaxSampleRate / 8000 * 120 + 30]; 399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125]; 409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kTempDataSize = 3600; 419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t temp_data[kTempDataSize]; // TODO(hlundin) Remove this. 429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* voiced_vector_storage = temp_data; 439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* voiced_vector = &voiced_vector_storage[overlap_length_]; 449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder; 459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t unvoiced_array_memory[kNoiseLpcOrder + kMaxSampleRate / 8000 * 125]; 469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* unvoiced_vector = unvoiced_array_memory + kUnvoicedLpcOrder; 479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* noise_vector = unvoiced_array_memory + kNoiseLpcOrder; 489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult = fs_hz_ / 8000; 509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (first_expand_) { 529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Perform initial setup if this is the first expansion since last reset. 539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org AnalyzeSignal(random_vector); 549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org first_expand_ = false; 559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // This is not the first expansion, parameters are already estimated. 579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Extract a noise segment. 589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t rand_length = max_lag_; 59c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // This only applies to SWB where length could be larger than 256. 60c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org assert(rand_length <= kMaxSampleRate / 8000 * 120 + 30); 61c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org GenerateRandomVector(2, rand_length, random_vector); 629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Generate signal. 669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org UpdateLagIndex(); 679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Voiced part. 699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Generate a weighted vector with the current lag. 709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t expansion_vector_length = max_lag_ + overlap_length_; 719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t current_lag = expand_lags_[current_lag_index_]; 729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Copy lag+overlap data. 739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t expansion_vector_position = expansion_vector_length - current_lag - 749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org overlap_length_; 759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t temp_length = current_lag + overlap_length_; 769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) { 779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ChannelParameters& parameters = channel_parameters_[channel_ix]; 789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (current_lag_index_ == 0) { 799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Use only expand_vector0. 809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(expansion_vector_position + temp_length <= 819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector0.Size()); 829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(voiced_vector_storage, 839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ¶meters.expand_vector0[expansion_vector_position], 849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * temp_length); 859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (current_lag_index_ == 1) { 869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Mix 3/4 of expand_vector0 with 1/4 of expand_vector1. 879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_ScaleAndAddVectorsWithRound( 889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ¶meters.expand_vector0[expansion_vector_position], 3, 899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ¶meters.expand_vector1[expansion_vector_position], 1, 2, 90045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org voiced_vector_storage, static_cast<int>(temp_length)); 919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (current_lag_index_ == 2) { 929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Mix 1/2 of expand_vector0 with 1/2 of expand_vector1. 939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(expansion_vector_position + temp_length <= 949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector0.Size()); 959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(expansion_vector_position + temp_length <= 969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector1.Size()); 979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_ScaleAndAddVectorsWithRound( 989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ¶meters.expand_vector0[expansion_vector_position], 1, 999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ¶meters.expand_vector1[expansion_vector_position], 1, 1, 100045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org voiced_vector_storage, static_cast<int>(temp_length)); 1019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Get tapering window parameters. Values are in Q15. 1049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t muting_window, muting_window_increment; 1059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t unmuting_window, unmuting_window_increment; 1069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (fs_hz_ == 8000) { 1079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window = DspHelper::kMuteFactorStart8kHz; 1089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window_increment = DspHelper::kMuteFactorIncrement8kHz; 1099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window = DspHelper::kUnmuteFactorStart8kHz; 1109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz; 1119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (fs_hz_ == 16000) { 1129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window = DspHelper::kMuteFactorStart16kHz; 1139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window_increment = DspHelper::kMuteFactorIncrement16kHz; 1149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window = DspHelper::kUnmuteFactorStart16kHz; 1159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz; 1169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (fs_hz_ == 32000) { 1179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window = DspHelper::kMuteFactorStart32kHz; 1189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window_increment = DspHelper::kMuteFactorIncrement32kHz; 1199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window = DspHelper::kUnmuteFactorStart32kHz; 1209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz; 1219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { // fs_ == 48000 1229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window = DspHelper::kMuteFactorStart48kHz; 1239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window_increment = DspHelper::kMuteFactorIncrement48kHz; 1249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window = DspHelper::kUnmuteFactorStart48kHz; 1259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz; 1269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Smooth the expanded if it has not been muted to a low amplitude and 1299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |current_voice_mix_factor| is larger than 0.5. 1309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((parameters.mute_factor > 819) && 1319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org (parameters.current_voice_mix_factor > 8192)) { 1329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t start_ix = sync_buffer_->Size() - overlap_length_; 1339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (size_t i = 0; i < overlap_length_; i++) { 1349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Do overlap add between new vector and overlap. 1359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org (*sync_buffer_)[channel_ix][start_ix + i] = 1369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org (((*sync_buffer_)[channel_ix][start_ix + i] * muting_window) + 1379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org (((parameters.mute_factor * voiced_vector_storage[i]) >> 14) * 1389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window) + 16384) >> 15; 1399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org muting_window += muting_window_increment; 1409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unmuting_window += unmuting_window_increment; 1419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (parameters.mute_factor == 0) { 1439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // The expanded signal will consist of only comfort noise if 1449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // mute_factor = 0. Set the output length to 15 ms for best noise 1459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // production. 1469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // TODO(hlundin): This has been disabled since the length of 1479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // parameters.expand_vector0 and parameters.expand_vector1 no longer 1489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // match with expand_lags_, causing invalid reads and writes. Is it a good 1499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // idea to enable this again, and solve the vector size problem? 1509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// max_lag_ = fs_mult * 120; 1519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// expand_lags_[0] = fs_mult * 120; 1529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// expand_lags_[1] = fs_mult * 120; 1539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// expand_lags_[2] = fs_mult * 120; 1549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Unvoiced part. 1579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Filter |scaled_random_vector| through |ar_filter_|. 1589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(unvoiced_vector - kUnvoicedLpcOrder, parameters.ar_filter_state, 1599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * kUnvoicedLpcOrder); 1609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t add_constant = 0; 1619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (parameters.ar_gain_scale > 0) { 1629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org add_constant = 1 << (parameters.ar_gain_scale - 1); 1639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_AffineTransformVector(scaled_random_vector, random_vector, 1659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.ar_gain, add_constant, 166045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org parameters.ar_gain_scale, 167045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org static_cast<int>(current_lag)); 1689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_FilterARFastQ12(scaled_random_vector, unvoiced_vector, 169045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org parameters.ar_filter, kUnvoicedLpcOrder + 1, 170045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org static_cast<int>(current_lag)); 1719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(parameters.ar_filter_state, 1729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(unvoiced_vector[current_lag - kUnvoicedLpcOrder]), 1739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * kUnvoicedLpcOrder); 1749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Combine voiced and unvoiced contributions. 1769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set a suitable cross-fading slope. 1789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // For lag = 1799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // <= 31 * fs_mult => go from 1 to 0 in about 8 ms; 1809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // (>= 31 .. <= 63) * fs_mult => go from 1 to 0 in about 16 ms; 1819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // >= 64 * fs_mult => go from 1 to 0 in about 32 ms. 1829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // temp_shift = getbits(max_lag_) - 5. 1839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int temp_shift = (31 - WebRtcSpl_NormW32(max_lag_)) - 5; 1849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t mix_factor_increment = 256 >> temp_shift; 1859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (stop_muting_) { 1869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org mix_factor_increment = 0; 1879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 1889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Create combined signal by shifting in more and more of unvoiced part. 1909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org temp_shift = 8 - temp_shift; // = getbits(mix_factor_increment). 1919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t temp_lenght = (parameters.current_voice_mix_factor - 1929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.voice_mix_factor) >> temp_shift; 1939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org temp_lenght = std::min(temp_lenght, current_lag); 1949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org DspHelper::CrossFade(voiced_vector, unvoiced_vector, temp_lenght, 1959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ¶meters.current_voice_mix_factor, 1969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org mix_factor_increment, temp_data); 1979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 1989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // End of cross-fading period was reached before end of expanded signal 1999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // path. Mix the rest with a fixed mixing factor. 2009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (temp_lenght < current_lag) { 2019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (mix_factor_increment != 0) { 2029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.current_voice_mix_factor = parameters.voice_mix_factor; 2039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int temp_scale = 16384 - parameters.current_voice_mix_factor; 2059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_ScaleAndAddVectorsWithRound( 2069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org voiced_vector + temp_lenght, parameters.current_voice_mix_factor, 2079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_vector + temp_lenght, temp_scale, 14, 208045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org temp_data + temp_lenght, static_cast<int>(current_lag - temp_lenght)); 2099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Select muting slope depending on how many consecutive expands we have 2129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // done. 2139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (consecutive_expands_ == 3) { 2149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Let the mute factor decrease from 1.0 to 0.95 in 6.25 ms. 2159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // mute_slope = 0.0010 / fs_mult in Q20. 2169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = std::max(parameters.mute_slope, 2179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static_cast<int16_t>(1049 / fs_mult)); 2189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (consecutive_expands_ == 7) { 2209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Let the mute factor decrease from 1.0 to 0.90 in 6.25 ms. 2219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // mute_slope = 0.0020 / fs_mult in Q20. 2229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = std::max(parameters.mute_slope, 2239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static_cast<int16_t>(2097 / fs_mult)); 2249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Mute segment according to slope value. 2279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((consecutive_expands_ != 0) || !parameters.onset) { 2289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Mute to the previous level, then continue with the muting. 2299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_AffineTransformVector(temp_data, temp_data, 2309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_factor, 8192, 231045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org 14, static_cast<int>(current_lag)); 2329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (!stop_muting_) { 2349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org DspHelper::MuteSignal(temp_data, parameters.mute_slope, current_lag); 2359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Shift by 6 to go from Q20 to Q14. 2379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // TODO(hlundin): Adding 8192 before shifting 6 steps seems wrong. 2389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Legacy. 239045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org int16_t gain = static_cast<int16_t>(16384 - 240045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org (((current_lag * parameters.mute_slope) + 8192) >> 6)); 2419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org gain = ((gain * parameters.mute_factor) + 8192) >> 14; 2429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Guard against getting stuck with very small (but sometimes audible) 2449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // gain. 2459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((consecutive_expands_ > 3) && (gain >= parameters.mute_factor)) { 2469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_factor = 0; 2479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 2489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_factor = gain; 2499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Background noise part. 254c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org GenerateBackgroundNoise(random_vector, 255c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org channel_ix, 256c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org channel_parameters_[channel_ix].mute_slope, 257c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org TooManyExpands(), 258c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org current_lag, 259c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org unvoiced_array_memory); 2609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Add background noise to the combined voiced-unvoiced signal. 2629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (size_t i = 0; i < current_lag; i++) { 2639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org temp_data[i] = temp_data[i] + noise_vector[i]; 2649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (channel_ix == 0) { 2669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org output->AssertSize(current_lag); 2679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 2689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(output->Size() == current_lag); 2699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(&(*output)[channel_ix][0], temp_data, 2719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(temp_data[0]) * current_lag); 2729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 2739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Increase call number and cap it. 275c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org consecutive_expands_ = consecutive_expands_ >= kMaxConsecutiveExpands ? 276c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org kMaxConsecutiveExpands : consecutive_expands_ + 1; 2779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return 0; 2789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 2799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Expand::SetParametersForNormalAfterExpand() { 2819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org current_lag_index_ = 0; 2829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lag_index_direction_ = 0; 2839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stop_muting_ = true; // Do not mute signal any more. 2849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 2859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 2869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Expand::SetParametersForMergeAfterExpand() { 2879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org current_lag_index_ = -1; /* out of the 3 possible ones */ 2889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lag_index_direction_ = 1; /* make sure we get the "optimal" lag */ 2899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stop_muting_ = true; 2909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 2919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 292c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.orgvoid Expand::InitializeForAnExpandPeriod() { 293c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org lag_index_direction_ = 1; 294c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org current_lag_index_ = -1; 295c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org stop_muting_ = false; 296c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org random_vector_->set_seed_increment(1); 297c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org consecutive_expands_ = 0; 298c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org for (size_t ix = 0; ix < num_channels_; ++ix) { 299c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org channel_parameters_[ix].current_voice_mix_factor = 16384; // 1.0 in Q14. 300c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org channel_parameters_[ix].mute_factor = 16384; // 1.0 in Q14. 301c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Start with 0 gain for background noise. 302c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->SetMuteFactor(ix, 0); 303c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 304c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org} 305c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 306c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.orgbool Expand::TooManyExpands() { 307c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org return consecutive_expands_ >= kMaxConsecutiveExpands; 308c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org} 309c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 3109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Expand::AnalyzeSignal(int16_t* random_vector) { 3119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t auto_correlation[kUnvoicedLpcOrder + 1]; 3129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t reflection_coeff[kUnvoicedLpcOrder]; 3139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t correlation_vector[kMaxSampleRate / 8000 * 102]; 3149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int best_correlation_index[kNumCorrelationCandidates]; 3159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t best_correlation[kNumCorrelationCandidates]; 3169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t best_distortion_index[kNumCorrelationCandidates]; 3179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t best_distortion[kNumCorrelationCandidates]; 3189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t correlation_vector2[(99 * kMaxSampleRate / 8000) + 1]; 3199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t best_distortion_w32[kNumCorrelationCandidates]; 3209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder; 3219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t unvoiced_array_memory[kNoiseLpcOrder + kMaxSampleRate / 8000 * 125]; 3229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* unvoiced_vector = unvoiced_array_memory + kUnvoicedLpcOrder; 3239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult = fs_hz_ / 8000; 3259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Pre-calculate common multiplications with fs_mult. 3279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult_4 = fs_mult * 4; 3289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult_20 = fs_mult * 20; 3299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult_120 = fs_mult * 120; 3309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult_dist_len = fs_mult * kDistortionLength; 3319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int fs_mult_lpc_analysis_len = fs_mult * kLpcAnalysisLength; 3329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const size_t signal_length = 256 * fs_mult; 3349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const int16_t* audio_history = 3359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(*sync_buffer_)[0][sync_buffer_->Size() - signal_length]; 3369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 337c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Initialize. 338c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org InitializeForAnExpandPeriod(); 3399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate correlation in downsampled domain (4 kHz sample rate). 3419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t correlation_scale; 342a9a788e12008fdf4ab9923ddcd7a1dbecf17b8e0turaj@webrtc.org int correlation_length = 51; // TODO(hlundin): Legacy bit-exactness. 343a9a788e12008fdf4ab9923ddcd7a1dbecf17b8e0turaj@webrtc.org // If it is decided to break bit-exactness |correlation_length| should be 344a9a788e12008fdf4ab9923ddcd7a1dbecf17b8e0turaj@webrtc.org // initialized to the return value of Correlation(). 345a9a788e12008fdf4ab9923ddcd7a1dbecf17b8e0turaj@webrtc.org Correlation(audio_history, signal_length, correlation_vector, 346a9a788e12008fdf4ab9923ddcd7a1dbecf17b8e0turaj@webrtc.org &correlation_scale); 3479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Find peaks in correlation vector. 3499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org DspHelper::PeakDetection(correlation_vector, correlation_length, 3509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kNumCorrelationCandidates, fs_mult, 3519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_correlation_index, best_correlation); 3529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Adjust peak locations; cross-correlation lags start at 2.5 ms 3549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // (20 * fs_mult samples). 3559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_correlation_index[0] += fs_mult_20; 3569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_correlation_index[1] += fs_mult_20; 3579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_correlation_index[2] += fs_mult_20; 3589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate distortion around the |kNumCorrelationCandidates| best lags. 3609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int distortion_scale = 0; 3619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (int i = 0; i < kNumCorrelationCandidates; i++) { 3629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t min_index = std::max(fs_mult_20, 3639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_correlation_index[i] - fs_mult_4); 3649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t max_index = std::min(fs_mult_120 - 1, 3659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_correlation_index[i] + fs_mult_4); 3669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_distortion_index[i] = DspHelper::MinDistortion( 3679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - fs_mult_dist_len]), min_index, 3689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org max_index, fs_mult_dist_len, &best_distortion_w32[i]); 3699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org distortion_scale = std::max(16 - WebRtcSpl_NormW32(best_distortion_w32[i]), 3709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org distortion_scale); 3719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 3729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Shift the distortion values to fit in 16 bits. 3739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_VectorBitShiftW32ToW16(best_distortion, kNumCorrelationCandidates, 3749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_distortion_w32, distortion_scale); 3759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Find the maximizing index |i| of the cost function 3779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // f[i] = best_correlation[i] / best_distortion[i]. 378a9a788e12008fdf4ab9923ddcd7a1dbecf17b8e0turaj@webrtc.org int32_t best_ratio = std::numeric_limits<int32_t>::min(); 3799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int best_index = -1; 3809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (int i = 0; i < kNumCorrelationCandidates; ++i) { 3819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t ratio; 3829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (best_distortion[i] > 0) { 3839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ratio = (best_correlation[i] << 16) / best_distortion[i]; 38460bf21e85cdf9a8dd18376d934bde5e785ebba87turaj@webrtc.org } else if (best_correlation[i] == 0) { 38560bf21e85cdf9a8dd18376d934bde5e785ebba87turaj@webrtc.org ratio = 0; // No correlation set result to zero. 3869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 38760bf21e85cdf9a8dd18376d934bde5e785ebba87turaj@webrtc.org ratio = std::numeric_limits<int32_t>::max(); // Denominator is zero. 3889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 3899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (ratio > best_ratio) { 3909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_index = i; 3919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_ratio = ratio; 3929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 3939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 3949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int distortion_lag = best_distortion_index[best_index]; 3969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int correlation_lag = best_correlation_index[best_index]; 3979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org max_lag_ = std::max(distortion_lag, correlation_lag); 3989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 3999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate the exact best correlation in the range between 4009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |correlation_lag| and |distortion_lag|. 4019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length = distortion_lag + 10; 4029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length = std::min(correlation_length, fs_mult_120); 4039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length = std::max(correlation_length, 60 * fs_mult); 4049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int start_index = std::min(distortion_lag, correlation_lag); 4069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int correlation_lags = WEBRTC_SPL_ABS_W16((distortion_lag-correlation_lag)) 4079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org + 1; 4089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(correlation_lags <= 99 * fs_mult + 1); // Cannot be larger. 4099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) { 4119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ChannelParameters& parameters = channel_parameters_[channel_ix]; 4129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate suitable scaling. 4139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t signal_max = WebRtcSpl_MaxAbsValueW16( 4149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &audio_history[signal_length - correlation_length - start_index 4159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org - correlation_lags], 4169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length + start_index + correlation_lags - 1); 4179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale = ((31 - WebRtcSpl_NormW32(signal_max * signal_max)) 4189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org + (31 - WebRtcSpl_NormW32(correlation_length))) - 31; 4199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale = std::max(static_cast<int16_t>(0), correlation_scale); 4209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate the correlation, store in |correlation_vector2|. 4229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_CrossCorrelation( 4239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_vector2, 4249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - correlation_length]), 4259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - correlation_length - start_index]), 4269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length, correlation_lags, correlation_scale, -1); 4279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Find maximizing index. 4299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_index = WebRtcSpl_MaxIndexW32(correlation_vector2, correlation_lags); 4309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t max_correlation = correlation_vector2[best_index]; 4319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Compensate index with start offset. 4329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org best_index = best_index + start_index; 4339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate energies. 4359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t energy1 = WebRtcSpl_DotProductWithScale( 4369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - correlation_length]), 4379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - correlation_length]), 4389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length, correlation_scale); 4399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t energy2 = WebRtcSpl_DotProductWithScale( 4409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - correlation_length - best_index]), 4419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - correlation_length - best_index]), 4429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_length, correlation_scale); 4439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate the correlation coefficient between the two portions of the 4459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // signal. 4469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t corr_coefficient; 4479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((energy1 > 0) && (energy2 > 0)) { 4489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int energy1_scale = std::max(16 - WebRtcSpl_NormW32(energy1), 0); 4499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int energy2_scale = std::max(16 - WebRtcSpl_NormW32(energy2), 0); 4509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Make sure total scaling is even (to simplify scale factor after sqrt). 4519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((energy1_scale + energy2_scale) & 1) { 4529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // If sum is odd, add 1 to make it even. 4539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org energy1_scale += 1; 4549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 4559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t scaled_energy1 = energy1 >> energy1_scale; 4569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t scaled_energy2 = energy2 >> energy2_scale; 4579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t sqrt_energy_product = WebRtcSpl_SqrtFloor( 4589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org scaled_energy1 * scaled_energy2); 4599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate max_correlation / sqrt(energy1 * energy2) in Q14. 4609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int cc_shift = 14 - (energy1_scale + energy2_scale) / 2; 4619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org max_correlation = WEBRTC_SPL_SHIFT_W32(max_correlation, cc_shift); 4629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org corr_coefficient = WebRtcSpl_DivW32W16(max_correlation, 4639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sqrt_energy_product); 4649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org corr_coefficient = std::min(static_cast<int16_t>(16384), 4659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org corr_coefficient); // Cap at 1.0 in Q14. 4669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 4679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org corr_coefficient = 0; 4689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 4699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Extract the two vectors expand_vector0 and expand_vector1 from 4719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |audio_history|. 472045e45efeca8776975254550137ec65268aadb54turaj@webrtc.org int16_t expansion_length = static_cast<int16_t>(max_lag_ + overlap_length_); 4739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const int16_t* vector1 = &(audio_history[signal_length - expansion_length]); 4749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const int16_t* vector2 = vector1 - distortion_lag; 4759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Normalize the second vector to the same energy as the first. 4769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org energy1 = WebRtcSpl_DotProductWithScale(vector1, vector1, expansion_length, 4779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale); 4789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org energy2 = WebRtcSpl_DotProductWithScale(vector2, vector2, expansion_length, 4799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale); 4809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Confirm that amplitude ratio sqrt(energy1 / energy2) is within 0.5 - 2.0, 4819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // i.e., energy1 / energy1 is within 0.25 - 4. 4829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t amplitude_ratio; 4839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((energy1 / 4 < energy2) && (energy1 > energy2 / 4)) { 4849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Energy constraint fulfilled. Use both vectors and scale them 4859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // accordingly. 4869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t scaled_energy2 = std::max(16 - WebRtcSpl_NormW32(energy2), 0); 4879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t scaled_energy1 = scaled_energy2 - 13; 4889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate scaled_energy1 / scaled_energy2 in Q13. 4899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t energy_ratio = WebRtcSpl_DivW32W16( 4909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WEBRTC_SPL_SHIFT_W32(energy1, -scaled_energy1), 4919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WEBRTC_SPL_RSHIFT_W32(energy2, scaled_energy2)); 4929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate sqrt ratio in Q13 (sqrt of en1/en2 in Q26). 4939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org amplitude_ratio = WebRtcSpl_SqrtFloor(energy_ratio << 13); 4949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Copy the two vectors and give them the same energy. 4959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector0.Clear(); 4969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector0.PushBack(vector1, expansion_length); 4979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector1.Clear(); 4989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (parameters.expand_vector1.Size() < 4999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static_cast<size_t>(expansion_length)) { 5009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector1.Extend( 5019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expansion_length - parameters.expand_vector1.Size()); 5029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_AffineTransformVector(¶meters.expand_vector1[0], 5049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const_cast<int16_t*>(vector2), 5059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org amplitude_ratio, 5069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 4096, 5079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 13, 5089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expansion_length); 5099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 5109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Energy change constraint not fulfilled. Only use last vector. 5119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector0.Clear(); 5129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.expand_vector0.PushBack(vector1, expansion_length); 5139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Copy from expand_vector0 to expand_vector1. 5140e4084a5b020b0364983acde9d4d420db876995ahenrik.lundin@webrtc.org parameters.expand_vector0.CopyTo(¶meters.expand_vector1); 5159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set the energy_ratio since it is used by muting slope. 5169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if ((energy1 / 4 < energy2) || (energy2 == 0)) { 5179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org amplitude_ratio = 4096; // 0.5 in Q13. 5189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 5199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org amplitude_ratio = 16384; // 2.0 in Q13. 5209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set the 3 lag values. 5249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int lag_difference = distortion_lag - correlation_lag; 5259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (lag_difference == 0) { 5269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |distortion_lag| and |correlation_lag| are equal. 5279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[0] = distortion_lag; 5289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[1] = distortion_lag; 5299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[2] = distortion_lag; 5309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 5319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |distortion_lag| and |correlation_lag| are not equal; use different 5329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // combinations of the two. 5339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // First lag is |distortion_lag| only. 5349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[0] = distortion_lag; 5359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Second lag is the average of the two. 5369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[1] = (distortion_lag + correlation_lag) / 2; 5379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Third lag is the average again, but rounding towards |correlation_lag|. 5389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (lag_difference > 0) { 5399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[2] = (distortion_lag + correlation_lag - 1) / 2; 5409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 5419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expand_lags_[2] = (distortion_lag + correlation_lag + 1) / 2; 5429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate the LPC and the gain of the filters. 5469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate scale value needed for auto-correlation. 5479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale = WebRtcSpl_MaxAbsValueW16( 5489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - fs_mult_lpc_analysis_len]), 5499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org fs_mult_lpc_analysis_len); 5509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale = std::min(16 - WebRtcSpl_NormW32(correlation_scale), 0); 5529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale = std::max(correlation_scale * 2 + 7, 0); 5539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate kUnvoicedLpcOrder + 1 lags of the auto-correlation function. 5559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org size_t temp_index = signal_length - fs_mult_lpc_analysis_len - 5569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kUnvoicedLpcOrder; 5579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Copy signal to temporary vector to be able to pad with leading zeros. 5589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* temp_signal = new int16_t[fs_mult_lpc_analysis_len 5599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org + kUnvoicedLpcOrder]; 5609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memset(temp_signal, 0, 5619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * (fs_mult_lpc_analysis_len + kUnvoicedLpcOrder)); 5629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(&temp_signal[kUnvoicedLpcOrder], 5639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &audio_history[temp_index + kUnvoicedLpcOrder], 5649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * fs_mult_lpc_analysis_len); 5659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_CrossCorrelation(auto_correlation, 5669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &temp_signal[kUnvoicedLpcOrder], 5679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &temp_signal[kUnvoicedLpcOrder], 5689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org fs_mult_lpc_analysis_len, kUnvoicedLpcOrder + 1, 5699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation_scale, -1); 5709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org delete [] temp_signal; 5719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Verify that variance is positive. 5739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (auto_correlation[0] > 0) { 5749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Estimate AR filter parameters using Levinson-Durbin algorithm; 5759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // kUnvoicedLpcOrder + 1 filter coefficients. 5769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t stability = WebRtcSpl_LevinsonDurbin(auto_correlation, 5779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.ar_filter, 5789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org reflection_coeff, 5799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kUnvoicedLpcOrder); 5809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Keep filter parameters only if filter is stable. 5829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (stability != 1) { 5839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set first coefficient to 4096 (1.0 in Q12). 5849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.ar_filter[0] = 4096; 5859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set remaining |kUnvoicedLpcOrder| coefficients to zero. 5869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_MemSetW16(parameters.ar_filter + 1, 0, kUnvoicedLpcOrder); 5879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 5909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (channel_ix == 0) { 5919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Extract a noise segment. 5929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t noise_length; 5939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (distortion_lag < 40) { 5949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org noise_length = 2 * distortion_lag + 30; 5959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 5969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org noise_length = distortion_lag + 30; 5979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 5989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (noise_length <= RandomVector::kRandomTableSize) { 5999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(random_vector, RandomVector::kRandomTable, 6009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * noise_length); 6019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 6029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Only applies to SWB where length could be larger than 6039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |kRandomTableSize|. 6049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(random_vector, RandomVector::kRandomTable, 6059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * RandomVector::kRandomTableSize); 6069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org assert(noise_length <= kMaxSampleRate / 8000 * 120 + 30); 6079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org random_vector_->IncreaseSeedIncrement(2); 6089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org random_vector_->Generate( 6099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org noise_length - RandomVector::kRandomTableSize, 6109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &random_vector[RandomVector::kRandomTableSize]); 6119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 6129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 6139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 6149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set up state vector and calculate scale factor for unvoiced filtering. 6159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(parameters.ar_filter_state, 6169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - kUnvoicedLpcOrder]), 6179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * kUnvoicedLpcOrder); 6189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org memcpy(unvoiced_vector - kUnvoicedLpcOrder, 6199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &(audio_history[signal_length - 128 - kUnvoicedLpcOrder]), 6209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org sizeof(int16_t) * kUnvoicedLpcOrder); 6219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_FilterMAFastQ12( 6229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const_cast<int16_t*>(&audio_history[signal_length - 128]), 6239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_vector, parameters.ar_filter, kUnvoicedLpcOrder + 1, 128); 6249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t unvoiced_prescale; 6259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (WebRtcSpl_MaxAbsValueW16(unvoiced_vector, 128) > 4000) { 6269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_prescale = 4; 6279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 6289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_prescale = 0; 6299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 6309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t unvoiced_energy = WebRtcSpl_DotProductWithScale(unvoiced_vector, 6319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_vector, 6329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 128, 6339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_prescale); 6349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 6359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Normalize |unvoiced_energy| to 28 or 29 bits to preserve sqrt() accuracy. 6369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t unvoiced_scale = WebRtcSpl_NormW32(unvoiced_energy) - 3; 6379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Make sure we do an odd number of shifts since we already have 7 shifts 6389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // from dividing with 128 earlier. This will make the total scale factor 6399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // even, which is suitable for the sqrt. 6409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_scale += ((unvoiced_scale & 0x1) ^ 0x1); 6419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org unvoiced_energy = WEBRTC_SPL_SHIFT_W32(unvoiced_energy, unvoiced_scale); 6429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t unvoiced_gain = WebRtcSpl_SqrtFloor(unvoiced_energy); 6439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.ar_gain_scale = 13 6449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org + (unvoiced_scale + 7 - unvoiced_prescale) / 2; 6459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.ar_gain = unvoiced_gain; 6469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 6479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate voice_mix_factor from corr_coefficient. 6489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Let x = corr_coefficient. Then, we compute: 6499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // if (x > 0.48) 6509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // voice_mix_factor = (-5179 + 19931x - 16422x^2 + 5776x^3) / 4096; 6519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // else 6529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // voice_mix_factor = 0; 6539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (corr_coefficient > 7875) { 6549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t x1, x2, x3; 6559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org x1 = corr_coefficient; // |corr_coefficient| is in Q14. 6569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org x2 = (x1 * x1) >> 14; // Shift 14 to keep result in Q14. 6579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org x3 = (x1 * x2) >> 14; 6589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kCoefficients[4] = { -5179, 19931, -16422, 5776 }; 6599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t temp_sum = kCoefficients[0] << 14; 6609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org temp_sum += kCoefficients[1] * x1; 6619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org temp_sum += kCoefficients[2] * x2; 6629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org temp_sum += kCoefficients[3] * x3; 6639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.voice_mix_factor = temp_sum / 4096; 6649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.voice_mix_factor = std::min(parameters.voice_mix_factor, 6659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static_cast<int16_t>(16384)); 6669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.voice_mix_factor = std::max(parameters.voice_mix_factor, 6679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static_cast<int16_t>(0)); 6689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 6699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.voice_mix_factor = 0; 6709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 6719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 6729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate muting slope. Reuse value from earlier scaling of 6739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |expand_vector0| and |expand_vector1|. 6749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t slope = amplitude_ratio; 6759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (slope > 12288) { 6769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // slope > 1.5. 6779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate (1 - (1 / slope)) / distortion_lag = 6789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // (slope - 1) / (distortion_lag * slope). 6799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // |slope| is in Q13, so 1 corresponds to 8192. Shift up to Q25 before 6809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // the division. 6819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Shift the denominator from Q13 to Q5 before the division. The result of 6829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // the division will then be in Q20. 6839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t temp_ratio = WebRtcSpl_DivW32W16((slope - 8192) << 12, 6849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org (distortion_lag * slope) >> 8); 6859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (slope > 14746) { 6869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // slope > 1.8. 6879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Divide by 2, with proper rounding. 6889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = (temp_ratio + 1) / 2; 6899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 6909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Divide by 8, with proper rounding. 6919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = (temp_ratio + 4) / 8; 6929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 6939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.onset = true; 6949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 6959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate (1 - slope) / distortion_lag. 6969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Shift |slope| by 7 to Q20 before the division. The result is in Q20. 6979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = WebRtcSpl_DivW32W16((8192 - slope) << 7, 6989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org distortion_lag); 6999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (parameters.voice_mix_factor <= 13107) { 7009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Make sure the mute factor decreases from 1.0 to 0.9 in no more than 7019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // 6.25 ms. 7029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // mute_slope >= 0.005 / fs_mult in Q20. 7039a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = std::max(static_cast<int16_t>(5243 / fs_mult), 7049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope); 7059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (slope > 8028) { 7069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.mute_slope = 0; 7079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 7089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org parameters.onset = false; 7099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 7109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 7119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 7129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 713045e45efeca8776975254550137ec65268aadb54turaj@webrtc.orgint16_t Expand::Correlation(const int16_t* input, size_t input_length, 7149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t* output, int16_t* output_scale) const { 7159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Set parameters depending on sample rate. 7169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org const int16_t* filter_coefficients; 7179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t num_coefficients; 7189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t downsampling_factor; 7199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (fs_hz_ == 8000) { 7209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org num_coefficients = 3; 7219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org downsampling_factor = 2; 7229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org filter_coefficients = DspHelper::kDownsample8kHzTbl; 7239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (fs_hz_ == 16000) { 7249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org num_coefficients = 5; 7259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org downsampling_factor = 4; 7269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org filter_coefficients = DspHelper::kDownsample16kHzTbl; 7279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (fs_hz_ == 32000) { 7289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org num_coefficients = 7; 7299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org downsampling_factor = 8; 7309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org filter_coefficients = DspHelper::kDownsample32kHzTbl; 7319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { // fs_hz_ == 48000. 7329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org num_coefficients = 7; 7339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org downsampling_factor = 12; 7349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org filter_coefficients = DspHelper::kDownsample48kHzTbl; 7359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 7369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 7379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Correlate from lag 10 to lag 60 in downsampled domain. 7389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // (Corresponds to 20-120 for narrow-band, 40-240 for wide-band, and so on.) 7399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kCorrelationStartLag = 10; 7409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kNumCorrelationLags = 54; 7419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kCorrelationLength = 60; 7429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Downsample to 4 kHz sample rate. 7439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kDownsampledLength = kCorrelationStartLag 7449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org + kNumCorrelationLags + kCorrelationLength; 7459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t downsampled_input[kDownsampledLength]; 7469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kFilterDelay = 0; 7479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_DownsampleFast( 7489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org input + input_length - kDownsampledLength * downsampling_factor, 7499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kDownsampledLength * downsampling_factor, downsampled_input, 7509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kDownsampledLength, filter_coefficients, num_coefficients, 7519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org downsampling_factor, kFilterDelay); 7529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 7539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Normalize |downsampled_input| to using all 16 bits. 7549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t max_value = WebRtcSpl_MaxAbsValueW16(downsampled_input, 7559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kDownsampledLength); 7569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t norm_shift = 16 - WebRtcSpl_NormW32(max_value); 7579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_VectorBitShiftW16(downsampled_input, kDownsampledLength, 7589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org downsampled_input, norm_shift); 7599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 7609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t correlation[kNumCorrelationLags]; 7619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org static const int kCorrelationShift = 6; 7629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_CrossCorrelation( 7639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org correlation, 7649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &downsampled_input[kDownsampledLength - kCorrelationLength], 7659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org &downsampled_input[kDownsampledLength - kCorrelationLength 7669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org - kCorrelationStartLag], 7679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kCorrelationLength, kNumCorrelationLags, kCorrelationShift, -1); 7689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 7699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Normalize and move data from 32-bit to 16-bit vector. 7709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t max_correlation = WebRtcSpl_MaxAbsValueW32(correlation, 7719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org kNumCorrelationLags); 7729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t norm_shift2 = std::max(18 - WebRtcSpl_NormW32(max_correlation), 0); 7739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org WebRtcSpl_VectorBitShiftW32ToW16(output, kNumCorrelationLags, correlation, 7749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org norm_shift2); 7759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Total scale factor (right shifts) of correlation value. 7769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *output_scale = 2 * norm_shift + kCorrelationShift + norm_shift2; 7779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org return kNumCorrelationLags; 7789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 7799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 7809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Expand::UpdateLagIndex() { 7819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org current_lag_index_ = current_lag_index_ + lag_index_direction_; 7829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Change direction if needed. 7839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (current_lag_index_ <= 0) { 7849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lag_index_direction_ = 1; 7859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 7869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (current_lag_index_ >= kNumLags - 1) { 7879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org lag_index_direction_ = -1; 7889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 7899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 7909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 79137fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.orgExpand* ExpandFactory::Create(BackgroundNoise* background_noise, 79237fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org SyncBuffer* sync_buffer, 79337fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org RandomVector* random_vector, 79437fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org int fs, 79537fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org size_t num_channels) const { 79637fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org return new Expand(background_noise, sync_buffer, random_vector, fs, 79737fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org num_channels); 79837fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org} 79937fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org 800c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org// TODO(turajs): This can be moved to BackgroundNoise class. 801c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.orgvoid Expand::GenerateBackgroundNoise(int16_t* random_vector, 802c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org size_t channel, 803c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t mute_slope, 804c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org bool too_many_expands, 805c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org size_t num_noise_samples, 806c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t* buffer) { 807c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org static const int kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder; 808c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125]; 809d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org assert(static_cast<size_t>(kMaxSampleRate / 8000 * 125) >= num_noise_samples); 810c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t* noise_samples = &buffer[kNoiseLpcOrder]; 811c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org if (background_noise_->initialized()) { 812c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Use background noise parameters. 813c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org memcpy(noise_samples - kNoiseLpcOrder, 814c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->FilterState(channel), 815c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org sizeof(int16_t) * kNoiseLpcOrder); 816c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 817c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int dc_offset = 0; 818c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org if (background_noise_->ScaleShift(channel) > 1) { 819c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org dc_offset = 1 << (background_noise_->ScaleShift(channel) - 1); 820c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 821c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 822c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Scale random vector to correct energy level. 823c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org WebRtcSpl_AffineTransformVector( 824c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org scaled_random_vector, random_vector, 825c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->Scale(channel), dc_offset, 826c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->ScaleShift(channel), 827c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org static_cast<int>(num_noise_samples)); 828c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 829c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org WebRtcSpl_FilterARFastQ12(scaled_random_vector, noise_samples, 830c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->Filter(channel), 831c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org kNoiseLpcOrder + 1, 832c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org static_cast<int>(num_noise_samples)); 833c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 834c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->SetFilterState( 835c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org channel, 836c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org &(noise_samples[num_noise_samples - kNoiseLpcOrder]), 837c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org kNoiseLpcOrder); 838c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 839c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Unmute the background noise. 840c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t bgn_mute_factor = background_noise_->MuteFactor(channel); 841d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org NetEq::BackgroundNoiseMode bgn_mode = background_noise_->mode(); 842d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org if (bgn_mode == NetEq::kBgnFade && too_many_expands && 843d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org bgn_mute_factor > 0) { 844c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Fade BGN to zero. 845c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Calculate muting slope, approximately -2^18 / fs_hz. 846c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t mute_slope; 847c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org if (fs_hz_ == 8000) { 848c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org mute_slope = -32; 849c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } else if (fs_hz_ == 16000) { 850c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org mute_slope = -16; 851c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } else if (fs_hz_ == 32000) { 852c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org mute_slope = -8; 853c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } else { 854c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org mute_slope = -5; 855c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 856c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Use UnmuteSignal function with negative slope. 857c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // |bgn_mute_factor| is in Q14. |mute_slope| is in Q20. 858c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org DspHelper::UnmuteSignal(noise_samples, 859c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org num_noise_samples, 860c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org &bgn_mute_factor, 861c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org mute_slope, 862c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org noise_samples); 863c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } else if (bgn_mute_factor < 16384) { 8648c5063edeaee6421489dd1c0d22fd6353019484chenrik.lundin@webrtc.org // If mode is kBgnOn, or if kBgnFade has started fading, 8658c5063edeaee6421489dd1c0d22fd6353019484chenrik.lundin@webrtc.org // use regular |mute_slope|. 866d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org if (!stop_muting_ && bgn_mode != NetEq::kBgnOff && 867d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org !(bgn_mode == NetEq::kBgnFade && too_many_expands)) { 868c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org DspHelper::UnmuteSignal(noise_samples, 869c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org static_cast<int>(num_noise_samples), 870c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org &bgn_mute_factor, 871c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org mute_slope, 872c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org noise_samples); 873c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } else { 874c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // kBgnOn and stop muting, or 875c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // kBgnOff (mute factor is always 0), or 876c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // kBgnFade has reached 0. 877c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org WebRtcSpl_AffineTransformVector(noise_samples, noise_samples, 878c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org bgn_mute_factor, 8192, 14, 879c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org static_cast<int>(num_noise_samples)); 880c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 881c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 882c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // Update mute_factor in BackgroundNoise class. 883c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org background_noise_->SetMuteFactor(channel, bgn_mute_factor); 884c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } else { 885c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // BGN parameters have not been initialized; use zero noise. 886c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org memset(noise_samples, 0, sizeof(int16_t) * num_noise_samples); 887c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 888c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org} 889c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org 890c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.orgvoid Expand::GenerateRandomVector(int seed_increment, 891c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org size_t length, 892c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org int16_t* random_vector) { 893c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // TODO(turajs): According to hlundin The loop should not be needed. Should be 894c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org // just as good to generate all of the vector in one call. 895c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org size_t samples_generated = 0; 896c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org const size_t kMaxRandSamples = RandomVector::kRandomTableSize; 897d8b9cd100e889aa8b4a7d8b391ebd39a1298913ehenrik.lundin@webrtc.org while (samples_generated < length) { 898c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org size_t rand_length = std::min(length - samples_generated, kMaxRandSamples); 899c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org random_vector_->IncreaseSeedIncrement(seed_increment); 900c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org random_vector_->Generate(rand_length, &random_vector[samples_generated]); 901c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org samples_generated += rand_length; 902c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org } 903c1caa69f05663fc729af5a921eb95a73709f7dcdturaj@webrtc.org} 90437fb66d3bde95c19f5c80ece459f5dd632077ff5henrik.lundin@webrtc.org 9059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} // namespace webrtc 906