Removing deprecated legacy noise suppressor This CL removes the code for the deprecated legacy noise. Bug: webrtc:5298 Change-Id: If287d8967a3079ef96bff4790afa31f37d178823 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/167922 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Commit-Queue: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30434}
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn index b238a9f..6215ab5 100644 --- a/modules/audio_processing/BUILD.gn +++ b/modules/audio_processing/BUILD.gn
@@ -137,6 +137,7 @@ "transient/transient_detector.h", "transient/transient_suppressor.cc", "transient/transient_suppressor.h", + "transient/windows_private.h", "transient/wpd_node.cc", "transient/wpd_node.h", "transient/wpd_tree.cc", @@ -183,8 +184,6 @@ "agc2:adaptive_digital", "agc2:fixed_digital", "agc2:gain_applier", - "legacy_ns:legacy_ns", - "legacy_ns:legacy_ns_c", "ns", "vad", "//third_party/abseil-cpp/absl/types:optional", @@ -376,7 +375,6 @@ "agc2:rnn_vad_with_level_unittests", "agc2:test_utils", "agc2/rnn_vad:unittests", - "legacy_ns:legacy_ns", "test/conversational_speech:unittest", "utility:legacy_delay_estimator_unittest", "utility:pffft_wrapper_unittest",
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 02a82f4..5cdfe37 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc
@@ -70,11 +70,6 @@ sample_rate_hz == AudioProcessing::kSampleRate48kHz; } -// Checks whether the legacy ns functionality should be enforced. -bool DetectLegacyNsEnforcement() { - return field_trial::IsEnabled("WebRTC-NewNoiseSuppressionKillSwitch"); -} - // Checks whether the high-pass filter should be done in the full-band. bool EnforceSplitBandHpf() { return field_trial::IsEnabled("WebRTC-FullBandHpfKillSwitch"); @@ -106,23 +101,6 @@ return uppermost_native_rate; } -NoiseSuppression::Level NsConfigLevelToInterfaceLevel( - AudioProcessing::Config::NoiseSuppression::Level level) { - using NsConfig = AudioProcessing::Config::NoiseSuppression; - switch (level) { - case NsConfig::kLow: - return NoiseSuppression::Level::kLow; - case NsConfig::kModerate: - return NoiseSuppression::Level::kModerate; - case NsConfig::kHigh: - return NoiseSuppression::Level::kHigh; - case NsConfig::kVeryHigh: - return NoiseSuppression::Level::kVeryHigh; - default: - RTC_NOTREACHED(); - } -} - GainControl::Mode Agc1ConfigModeToInterfaceMode( AudioProcessing::Config::GainController1::Mode mode) { using Agc1Config = AudioProcessing::Config::GainController1; @@ -319,7 +297,6 @@ std::unique_ptr<CustomAudioAnalyzer> capture_analyzer) : data_dumper_( new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), - enforced_usage_of_legacy_ns_(DetectLegacyNsEnforcement()), use_setup_specific_default_aec3_config_( UseSetupSpecificDefaultAec3Congfig()), capture_runtime_settings_(kRuntimeSettingQueueSize), @@ -1220,16 +1197,11 @@ RETURN_ON_ERR( submodules_.gain_control->AnalyzeCaptureAudio(*capture_buffer)); } - RTC_DCHECK( - !(submodules_.legacy_noise_suppressor && submodules_.noise_suppressor)); - if (!config_.noise_suppression.analyze_linear_aec_output_when_available || - !linear_aec_buffer || submodules_.echo_control_mobile) { - if (submodules_.noise_suppressor) { - submodules_.noise_suppressor->Analyze(*capture_buffer); - } else if (submodules_.legacy_noise_suppressor) { - submodules_.legacy_noise_suppressor->AnalyzeCaptureAudio(capture_buffer); - } + if ((!config_.noise_suppression.analyze_linear_aec_output_when_available || + !linear_aec_buffer || submodules_.echo_control_mobile) && + submodules_.noise_suppressor) { + submodules_.noise_suppressor->Analyze(*capture_buffer); } if (submodules_.echo_control_mobile) { @@ -1241,9 +1213,6 @@ if (submodules_.noise_suppressor) { submodules_.noise_suppressor->Process(capture_buffer); - } else if (submodules_.legacy_noise_suppressor) { - submodules_.echo_control_mobile->CopyLowPassReference(capture_buffer); - submodules_.legacy_noise_suppressor->ProcessCaptureAudio(capture_buffer); } RETURN_ON_ERR(submodules_.echo_control_mobile->ProcessCaptureAudio( @@ -1261,19 +1230,12 @@ } if (config_.noise_suppression.analyze_linear_aec_output_when_available && - linear_aec_buffer) { - if (submodules_.noise_suppressor) { - submodules_.noise_suppressor->Analyze(*linear_aec_buffer); - } else if (submodules_.legacy_noise_suppressor) { - submodules_.legacy_noise_suppressor->AnalyzeCaptureAudio( - linear_aec_buffer); - } + linear_aec_buffer && submodules_.noise_suppressor) { + submodules_.noise_suppressor->Analyze(*linear_aec_buffer); } if (submodules_.noise_suppressor) { submodules_.noise_suppressor->Process(capture_buffer); - } else if (submodules_.legacy_noise_suppressor) { - submodules_.legacy_noise_suppressor->ProcessCaptureAudio(capture_buffer); } } @@ -1682,8 +1644,7 @@ bool AudioProcessingImpl::UpdateActiveSubmoduleStates() { return submodule_states_.Update( config_.high_pass_filter.enabled, !!submodules_.echo_control_mobile, - config_.residual_echo_detector.enabled, - !!submodules_.legacy_noise_suppressor || !!submodules_.noise_suppressor, + config_.residual_echo_detector.enabled, !!submodules_.noise_suppressor, !!submodules_.gain_control, !!submodules_.gain_controller2, config_.pre_amplifier.enabled, capture_nonlocked_.echo_controller_enabled, config_.voice_detection.enabled, !!submodules_.transient_suppressor); @@ -1896,14 +1857,9 @@ } void AudioProcessingImpl::InitializeNoiseSuppressor() { - submodules_.legacy_noise_suppressor.reset(); submodules_.noise_suppressor.reset(); if (config_.noise_suppression.enabled) { - const bool use_legacy_ns = - config_.noise_suppression.use_legacy_ns || enforced_usage_of_legacy_ns_; - - if (!use_legacy_ns) { auto map_level = [](AudioProcessing::Config::NoiseSuppression::Level level) { using NoiseSuppresionConfig = @@ -1926,12 +1882,6 @@ cfg.target_level = map_level(config_.noise_suppression.level); submodules_.noise_suppressor = std::make_unique<NoiseSuppressor>( cfg, proc_sample_rate_hz(), num_proc_channels()); - } else { - auto ns_level = - NsConfigLevelToInterfaceLevel(config_.noise_suppression.level); - submodules_.legacy_noise_suppressor = std::make_unique<NoiseSuppression>( - num_proc_channels(), proc_sample_rate_hz(), ns_level); - } } }
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h index c74d7ca..fd86f39 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h
@@ -27,7 +27,6 @@ #include "modules/audio_processing/include/aec_dump.h" #include "modules/audio_processing/include/audio_processing.h" #include "modules/audio_processing/include/audio_processing_statistics.h" -#include "modules/audio_processing/legacy_ns/legacy_noise_suppression.h" #include "modules/audio_processing/level_estimator.h" #include "modules/audio_processing/ns/noise_suppressor.h" #include "modules/audio_processing/render_queue_item_verifier.h" @@ -152,7 +151,6 @@ std::unique_ptr<ApmDataDumper> data_dumper_; static int instance_count_; - const bool enforced_usage_of_legacy_ns_; const bool use_setup_specific_default_aec3_config_; SwapQueue<RuntimeSetting> capture_runtime_settings_; @@ -346,7 +344,6 @@ rtc::scoped_refptr<EchoDetector> echo_detector; std::unique_ptr<EchoControl> echo_controller; std::unique_ptr<EchoControlMobileImpl> echo_control_mobile; - std::unique_ptr<NoiseSuppression> legacy_noise_suppressor; std::unique_ptr<NoiseSuppressor> noise_suppressor; std::unique_ptr<TransientSuppressor> transient_suppressor; std::unique_ptr<CustomProcessing> capture_post_processor;
diff --git a/modules/audio_processing/echo_control_mobile_impl.cc b/modules/audio_processing/echo_control_mobile_impl.cc index 6221aec..8116608 100644 --- a/modules/audio_processing/echo_control_mobile_impl.cc +++ b/modules/audio_processing/echo_control_mobile_impl.cc
@@ -220,16 +220,6 @@ return AudioProcessing::kNoError; } -void EchoControlMobileImpl::CopyLowPassReference(AudioBuffer* audio) { - RTC_DCHECK_LE(audio->num_channels(), low_pass_reference_.size()); - reference_copied_ = true; - for (size_t capture = 0; capture < audio->num_channels(); ++capture) { - FloatS16ToS16(audio->split_bands_const(capture)[kBand0To8kHz], - audio->num_frames_per_band(), - low_pass_reference_[capture].data()); - } -} - int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { if (MapSetting(mode) == -1) { return AudioProcessing::kBadParameterError;
diff --git a/modules/audio_processing/echo_control_mobile_impl.h b/modules/audio_processing/echo_control_mobile_impl.h index f12ce2a..23f3c06 100644 --- a/modules/audio_processing/echo_control_mobile_impl.h +++ b/modules/audio_processing/echo_control_mobile_impl.h
@@ -54,7 +54,6 @@ void ProcessRenderAudio(rtc::ArrayView<const int16_t> packed_render_audio); int ProcessCaptureAudio(AudioBuffer* audio, int stream_delay_ms); - void CopyLowPassReference(AudioBuffer* audio); void Initialize(int sample_rate_hz, size_t num_reverse_channels,
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h index f5d37b9..b63fa70 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h
@@ -250,8 +250,6 @@ enum Level { kLow, kModerate, kHigh, kVeryHigh }; Level level = kModerate; bool analyze_linear_aec_output_when_available = false; - // Recommended not to use. Will be removed in the future. - bool use_legacy_ns = false; } noise_suppression; // Enables transient suppression.
diff --git a/modules/audio_processing/legacy_ns/BUILD.gn b/modules/audio_processing/legacy_ns/BUILD.gn deleted file mode 100644 index 13ff9cf..0000000 --- a/modules/audio_processing/legacy_ns/BUILD.gn +++ /dev/null
@@ -1,105 +0,0 @@ -# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. -# -# Use of this source code is governed by a BSD-style license -# that can be found in the LICENSE file in the root of the source -# tree. An additional intellectual property rights grant can be found -# in the file PATENTS. All contributing project authors may -# be found in the AUTHORS file in the root of the source tree. - -import("../../../webrtc.gni") - -rtc_library("legacy_ns") { - visibility = [ "*" ] # Only targets in this file can depend on this. - sources = [ - "legacy_noise_suppression.cc", - "legacy_noise_suppression.h", - ] - - if (rtc_prefer_fixed_point) { - defines = [ "WEBRTC_NS_FIXED" ] - } else { - defines = [ "WEBRTC_NS_FLOAT" ] - } - - deps = [ - ":legacy_ns_c", - "..:audio_buffer", - "../../../common_audio", - "../../../common_audio:common_audio_c", - "../../../rtc_base:checks", - "../../../rtc_base:rtc_base_approved", - "../../../system_wrappers:cpu_features_api", - ] -} - -rtc_library("legacy_ns_c") { - visibility = [ "*" ] # Only targets in this file can depend on this. - sources = [ "windows_private.h" ] - - if (rtc_prefer_fixed_point) { - sources += [ - "noise_suppression_x.c", - "noise_suppression_x.h", - "nsx_core.c", - "nsx_core.h", - "nsx_core_c.c", - "nsx_defines.h", - ] - } else { - sources += [ - "defines.h", - "noise_suppression.c", - "noise_suppression.h", - "ns_core.c", - "ns_core.h", - ] - } - - if (rtc_prefer_fixed_point) { - defines = [ "WEBRTC_NS_FIXED" ] - } else { - defines = [ "WEBRTC_NS_FLOAT" ] - } - - deps = [ - "..:audio_buffer", - "../../../common_audio", - "../../../common_audio:common_audio_c", - "../../../common_audio/third_party/fft4g", - "../../../rtc_base:checks", - "../../../rtc_base:rtc_base_approved", - "../../../system_wrappers:cpu_features_api", - ] - - if (rtc_build_with_neon) { - sources += [ "nsx_core_neon.c" ] - - if (current_cpu != "arm64") { - # Enable compilation for the NEON instruction set. - suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ] - cflags = [ "-mfpu=neon" ] - } - } -} - -if (rtc_include_tests) { - rtc_source_set("legacy_ns_unittests") { - testonly = true - - configs += [] - sources = [ "legacy_noise_suppression_unittest.cc" ] - - deps = [ - "..:audio_buffer", - "..:audioproc_test_utils", - "../../../api:array_view", - "../../../test:test_support", - ] - - defines = [] - - if (rtc_enable_protobuf) { - sources += [] - } - } -}
diff --git a/modules/audio_processing/legacy_ns/defines.h b/modules/audio_processing/legacy_ns/defines.h deleted file mode 100644 index 02e0318..0000000 --- a/modules/audio_processing/legacy_ns/defines.h +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_DEFINES_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_DEFINES_H_ - -#define BLOCKL_MAX 160 // max processing block length: 160 -#define ANAL_BLOCKL_MAX 256 // max analysis block length: 256 -#define HALF_ANAL_BLOCKL 129 // half max analysis block length + 1 -#define NUM_HIGH_BANDS_MAX 2 // max number of high bands: 2 - -#define QUANTILE 0.25f - -#define SIMULT 3 -#define END_STARTUP_LONG 200 -#define END_STARTUP_SHORT 50 -#define FACTOR 40.f -#define WIDTH 0.01f - -// Length of fft work arrays. -#define IP_LENGTH \ - (ANAL_BLOCKL_MAX >> 1) // must be at least ceil(2 + sqrt(ANAL_BLOCKL_MAX/2)) -#define W_LENGTH (ANAL_BLOCKL_MAX >> 1) - -// PARAMETERS FOR NEW METHOD -#define DD_PR_SNR 0.98f // DD update of prior SNR -#define LRT_TAVG 0.5f // tavg parameter for LRT (previously 0.90) -#define SPECT_FL_TAVG 0.30f // tavg parameter for spectral flatness measure -#define SPECT_DIFF_TAVG 0.30f // tavg parameter for spectral difference measure -#define PRIOR_UPDATE 0.1f // update parameter of prior model -#define NOISE_UPDATE 0.9f // update parameter for noise -#define SPEECH_UPDATE 0.99f // update parameter when likely speech -#define WIDTH_PR_MAP 4.0f // width parameter in sigmoid map for prior model -#define LRT_FEATURE_THR 0.5f // default threshold for LRT feature -#define SF_FEATURE_THR 0.5f // default threshold for Spectral Flatness feature -#define SD_FEATURE_THR \ - 0.5f // default threshold for Spectral Difference feature -#define PROB_RANGE \ - 0.2f // probability threshold for noise state in - // speech/noise likelihood -#define HIST_PAR_EST 1000 // histogram size for estimation of parameters -#define GAMMA_PAUSE 0.05f // update for conservative noise estimate -// -#define B_LIM 0.5f // threshold in final energy gain factor calculation -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_DEFINES_H_
diff --git a/modules/audio_processing/legacy_ns/legacy_noise_suppression.cc b/modules/audio_processing/legacy_ns/legacy_noise_suppression.cc deleted file mode 100644 index 52193a9..0000000 --- a/modules/audio_processing/legacy_ns/legacy_noise_suppression.cc +++ /dev/null
@@ -1,172 +0,0 @@ -/* - * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_processing/legacy_ns/legacy_noise_suppression.h" - -#include "modules/audio_processing/audio_buffer.h" -#include "rtc_base/checks.h" -#if defined(WEBRTC_NS_FLOAT) -#include "modules/audio_processing/legacy_ns/noise_suppression.h" - -#define NS_CREATE WebRtcNs_Create -#define NS_FREE WebRtcNs_Free -#define NS_INIT WebRtcNs_Init -#define NS_SET_POLICY WebRtcNs_set_policy -typedef NsHandle NsState; -#elif defined(WEBRTC_NS_FIXED) -#include "modules/audio_processing/legacy_ns/noise_suppression_x.h" - -#define NS_CREATE WebRtcNsx_Create -#define NS_FREE WebRtcNsx_Free -#define NS_INIT WebRtcNsx_Init -#define NS_SET_POLICY WebRtcNsx_set_policy -typedef NsxHandle NsState; -#endif - -namespace webrtc { -namespace { -int NoiseSuppressionLevelToPolicy(NoiseSuppression::Level level) { - switch (level) { - case NoiseSuppression::Level::kLow: - return 0; - case NoiseSuppression::Level::kModerate: - return 1; - case NoiseSuppression::Level::kHigh: - return 2; - case NoiseSuppression::Level::kVeryHigh: - return 3; - default: - RTC_NOTREACHED(); - } - return 1; -} -} // namespace - -class NoiseSuppression::Suppressor { - public: - explicit Suppressor(int sample_rate_hz) { - state_ = NS_CREATE(); - RTC_CHECK(state_); - int error = NS_INIT(state_, sample_rate_hz); - RTC_DCHECK_EQ(0, error); - } - ~Suppressor() { NS_FREE(state_); } - - Suppressor(Suppressor&) = delete; - Suppressor& operator=(Suppressor&) = delete; - - NsState* state() { return state_; } - - private: - NsState* state_ = nullptr; -}; - -NoiseSuppression::NoiseSuppression(size_t channels, - int sample_rate_hz, - Level level) { - const int policy = NoiseSuppressionLevelToPolicy(level); - for (size_t i = 0; i < channels; ++i) { - suppressors_.push_back(std::make_unique<Suppressor>(sample_rate_hz)); - int error = NS_SET_POLICY(suppressors_[i]->state(), policy); - RTC_DCHECK_EQ(0, error); - } -} - -NoiseSuppression::~NoiseSuppression() {} - -void NoiseSuppression::AnalyzeCaptureAudio(AudioBuffer* audio) { - RTC_DCHECK(audio); -#if defined(WEBRTC_NS_FLOAT) - RTC_DCHECK_GE(160, audio->num_frames_per_band()); - RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels()); - for (size_t i = 0; i < suppressors_.size(); i++) { - WebRtcNs_Analyze(suppressors_[i]->state(), - audio->split_bands_const(i)[kBand0To8kHz]); - } -#endif -} - -void NoiseSuppression::ProcessCaptureAudio(AudioBuffer* audio) { - RTC_DCHECK(audio); - RTC_DCHECK_GE(160, audio->num_frames_per_band()); - RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels()); - for (size_t i = 0; i < suppressors_.size(); i++) { -#if defined(WEBRTC_NS_FLOAT) - WebRtcNs_Process(suppressors_[i]->state(), audio->split_bands_const(i), - audio->num_bands(), audio->split_bands(i)); -#elif defined(WEBRTC_NS_FIXED) - int16_t split_band_data[AudioBuffer::kMaxNumBands] - [AudioBuffer::kMaxSplitFrameLength]; - int16_t* split_bands[AudioBuffer::kMaxNumBands] = { - split_band_data[0], split_band_data[1], split_band_data[2]}; - audio->ExportSplitChannelData(i, split_bands); - - WebRtcNsx_Process(suppressors_[i]->state(), split_bands, audio->num_bands(), - split_bands); - - audio->ImportSplitChannelData(i, split_bands); -#endif - } -} - -float NoiseSuppression::speech_probability() const { -#if defined(WEBRTC_NS_FLOAT) - float probability_average = 0.0f; - for (auto& suppressor : suppressors_) { - probability_average += - WebRtcNs_prior_speech_probability(suppressor->state()); - } - if (!suppressors_.empty()) { - probability_average /= suppressors_.size(); - } - return probability_average; -#elif defined(WEBRTC_NS_FIXED) - // TODO(peah): Returning error code as a float! Remove this. - // Currently not available for the fixed point implementation. - return AudioProcessing::kUnsupportedFunctionError; -#endif -} - -std::vector<float> NoiseSuppression::NoiseEstimate() { - std::vector<float> noise_estimate; -#if defined(WEBRTC_NS_FLOAT) - const float kNumChannelsFraction = 1.f / suppressors_.size(); - noise_estimate.assign(WebRtcNs_num_freq(), 0.f); - for (auto& suppressor : suppressors_) { - const float* noise = WebRtcNs_noise_estimate(suppressor->state()); - for (size_t i = 0; i < noise_estimate.size(); ++i) { - noise_estimate[i] += kNumChannelsFraction * noise[i]; - } - } -#elif defined(WEBRTC_NS_FIXED) - noise_estimate.assign(WebRtcNsx_num_freq(), 0.f); - for (auto& suppressor : suppressors_) { - int q_noise; - const uint32_t* noise = - WebRtcNsx_noise_estimate(suppressor->state(), &q_noise); - const float kNormalizationFactor = - 1.f / ((1 << q_noise) * suppressors_.size()); - for (size_t i = 0; i < noise_estimate.size(); ++i) { - noise_estimate[i] += kNormalizationFactor * noise[i]; - } - } -#endif - return noise_estimate; -} - -size_t NoiseSuppression::num_noise_bins() { -#if defined(WEBRTC_NS_FLOAT) - return WebRtcNs_num_freq(); -#elif defined(WEBRTC_NS_FIXED) - return WebRtcNsx_num_freq(); -#endif -} - -} // namespace webrtc
diff --git a/modules/audio_processing/legacy_ns/legacy_noise_suppression.h b/modules/audio_processing/legacy_ns/legacy_noise_suppression.h deleted file mode 100644 index c599bc5..0000000 --- a/modules/audio_processing/legacy_ns/legacy_noise_suppression.h +++ /dev/null
@@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_LEGACY_NOISE_SUPPRESSION_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_LEGACY_NOISE_SUPPRESSION_H_ - -#include <memory> -#include <vector> - -namespace webrtc { - -class AudioBuffer; - -// The noise suppression (NS) component attempts to remove noise while -// retaining speech. Recommended to be enabled on the client-side. -class NoiseSuppression { - public: - // Determines the aggressiveness of the suppression. Increasing the level - // will reduce the noise level at the expense of a higher speech distortion. - enum class Level { kLow, kModerate, kHigh, kVeryHigh }; - - NoiseSuppression(size_t channels, int sample_rate_hz, Level level); - ~NoiseSuppression(); - - NoiseSuppression(NoiseSuppression&) = delete; - NoiseSuppression& operator=(NoiseSuppression&) = delete; - - void AnalyzeCaptureAudio(AudioBuffer* audio); - void ProcessCaptureAudio(AudioBuffer* audio); - - // LEGACY: Returns the internally computed prior speech probability of current - // frame averaged over output channels. This is not supported in fixed point, - // for which |kUnsupportedFunctionError| is returned. - float speech_probability() const; - - // LEGACY: Returns the size of the noise vector returned by NoiseEstimate(). - static size_t num_noise_bins(); - - // LEGACY: Returns the noise estimate per frequency bin averaged over all - // channels. - std::vector<float> NoiseEstimate(); - - private: - class Suppressor; - - std::vector<std::unique_ptr<Suppressor>> suppressors_; -}; -} // namespace webrtc - -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_LEGACY_NOISE_SUPPRESSION_H_
diff --git a/modules/audio_processing/legacy_ns/legacy_noise_suppression_unittest.cc b/modules/audio_processing/legacy_ns/legacy_noise_suppression_unittest.cc deleted file mode 100644 index 57deedb..0000000 --- a/modules/audio_processing/legacy_ns/legacy_noise_suppression_unittest.cc +++ /dev/null
@@ -1,279 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#include <vector> - -#include "api/array_view.h" -#include "modules/audio_processing/audio_buffer.h" -#include "modules/audio_processing/legacy_noise_suppression.h" -#include "modules/audio_processing/test/audio_buffer_tools.h" -#include "modules/audio_processing/test/bitexactness_tools.h" -#include "test/gtest.h" - -namespace webrtc { -namespace { - -const int kNumFramesToProcess = 1000; - -// Process one frame of data and produce the output. -void ProcessOneFrame(int sample_rate_hz, - AudioBuffer* capture_buffer, - NoiseSuppression* noise_suppressor) { - if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { - capture_buffer->SplitIntoFrequencyBands(); - } - - noise_suppressor->AnalyzeCaptureAudio(capture_buffer); - noise_suppressor->ProcessCaptureAudio(capture_buffer); - - if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { - capture_buffer->MergeFrequencyBands(); - } -} - -// Processes a specified amount of frames, verifies the results and reports -// any errors. -void RunBitexactnessTest(int sample_rate_hz, - size_t num_channels, - NoiseSuppression::Level level, - float speech_probability_reference, - rtc::ArrayView<const float> noise_estimate_reference, - rtc::ArrayView<const float> output_reference) { - NoiseSuppression noise_suppressor(num_channels, sample_rate_hz, level); - - int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100); - const StreamConfig capture_config(sample_rate_hz, num_channels, false); - AudioBuffer capture_buffer( - capture_config.sample_rate_hz(), capture_config.num_channels(), - capture_config.sample_rate_hz(), capture_config.num_channels(), - capture_config.sample_rate_hz(), capture_config.num_channels()); - test::InputAudioFile capture_file( - test::GetApmCaptureTestVectorFileName(sample_rate_hz)); - std::vector<float> capture_input(samples_per_channel * num_channels); - for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) { - ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, - &capture_file, capture_input); - - test::CopyVectorToAudioBuffer(capture_config, capture_input, - &capture_buffer); - - ProcessOneFrame(sample_rate_hz, &capture_buffer, &noise_suppressor); - } - - // Extract test results. - std::vector<float> capture_output; - test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer, - &capture_output); - float speech_probability = noise_suppressor.speech_probability(); - std::vector<float> noise_estimate = noise_suppressor.NoiseEstimate(); - - const float kVectorElementErrorBound = 1.0f / 32768.0f; - EXPECT_FLOAT_EQ(speech_probability_reference, speech_probability); - EXPECT_TRUE(test::VerifyArray(noise_estimate_reference, noise_estimate, - kVectorElementErrorBound)); - - // Compare the output with the reference. Only the first values of the output - // from last frame processed are compared in order not having to specify all - // preceeding frames as testvectors. As the algorithm being tested has a - // memory, testing only the last frame implicitly also tests the preceeding - // frames. - EXPECT_TRUE(test::VerifyDeinterleavedArray( - capture_config.num_frames(), capture_config.num_channels(), - output_reference, capture_output, kVectorElementErrorBound)); -} - -} // namespace - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono8kHzLow) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {1432.341431f, 3321.919922f, - 7677.521973f}; - const float kOutputReference[] = {0.003510f, 0.004517f, 0.004669f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {1432.341431f, 3321.919922f, - 7677.521973f}; - const float kOutputReference[] = {0.003510f, 0.004517f, 0.004669f}; -#else - const float kSpeechProbabilityReference = 0.73650402f; - const float kNoiseEstimateReference[] = {1176.856812f, 3287.490967f, - 7525.964844f}; - const float kOutputReference[] = {0.003306f, 0.004442f, 0.004574f}; -#endif - - RunBitexactnessTest(8000, 1, NoiseSuppression::Level::kLow, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzLow) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2534.461914f, 6277.638672f, - 14367.499023f}; - const float kOutputReference[] = {0.003449f, 0.004334f, 0.004303f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2534.461914f, 6277.638672f, - 14367.499023f}; - const float kOutputReference[] = {0.003449f, 0.004334f, 0.004303f}; -#else - const float kSpeechProbabilityReference = 0.71743423f; - const float kNoiseEstimateReference[] = {2179.853027f, 6507.995117f, - 15652.758789f}; - const float kOutputReference[] = {0.003574f, 0.004494f, 0.004499f}; -#endif - - RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kLow, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono32kHzLow) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2540.059082f, 6317.822754f, - 14440.845703f}; - const float kOutputReference[] = {0.001679f, 0.002411f, 0.002594f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2540.059082f, 6317.822754f, - 14440.845703f}; - const float kOutputReference[] = {0.001679f, 0.002411f, 0.002594f}; -#else - const float kSpeechProbabilityReference = 0.67999554f; - const float kNoiseEstimateReference[] = {2149.780518f, 7076.936035f, - 14939.945312f}; - const float kOutputReference[] = {0.001221f, 0.001984f, 0.002228f}; -#endif - - RunBitexactnessTest(32000, 1, NoiseSuppression::Level::kLow, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono48kHzLow) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2135.292480f, 6692.695801f, - 14647.632812f}; - const float kOutputReference[] = {-0.012738f, -0.012312f, -0.011576f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2135.292480f, 6692.695801f, - 14647.632812f}; - const float kOutputReference[] = {-0.012738f, -0.012312f, -0.011576f}; -#else - const float kSpeechProbabilityReference = 0.70737761f; - const float kNoiseEstimateReference[] = {2187.394043f, 6913.306641f, - 13182.945312f}; - const float kOutputReference[] = {-0.013062f, -0.012657f, -0.011934f}; -#endif - - RunBitexactnessTest(48000, 1, NoiseSuppression::Level::kLow, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Stereo16kHzLow) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {9992.127930f, 12689.569336f, - 11589.296875f}; - const float kOutputReference[] = {-0.011108f, -0.007904f, -0.012390f, - -0.002441f, 0.000855f, -0.003204f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {10321.353516f, 12133.852539f, - 10923.060547f}; - const float kOutputReference[] = {-0.011108f, -0.007904f, -0.012390f, - -0.002472f, 0.000916f, -0.003235f}; -#else - const float kSpeechProbabilityReference = 0.67285913f; - const float kNoiseEstimateReference[] = {9753.257812f, 11515.603516f, - 10503.309570f}; - const float kOutputReference[] = {-0.011459f, -0.008110f, -0.012728f, - -0.002399f, 0.001018f, -0.003189f}; -#endif - - RunBitexactnessTest(16000, 2, NoiseSuppression::Level::kLow, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzModerate) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2057.085938f, 7601.055176f, - 19666.187500f}; - const float kOutputReference[] = {0.004669f, 0.005524f, 0.005432f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2244.497803f, 6864.164062f, - 16726.523438f}; - const float kOutputReference[] = {0.004669f, 0.005615f, 0.005585f}; -#else - const float kSpeechProbabilityReference = 0.70916927f; - const float kNoiseEstimateReference[] = {2172.830566f, 6552.661133f, - 15624.025391f}; - const float kOutputReference[] = {0.004513f, 0.005590f, 0.005614f}; -#endif - - RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kModerate, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzHigh) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2095.148193f, 7698.553711f, - 19689.533203f}; - const float kOutputReference[] = {0.004639f, 0.005402f, 0.005310f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2282.515625f, 6984.408203f, - 16920.960938f}; - const float kOutputReference[] = {0.004547f, 0.005432f, 0.005402f}; -#else - const float kSpeechProbabilityReference = 0.70104003f; - const float kNoiseEstimateReference[] = {2225.081055f, 6711.529785f, - 15785.949219}; - const float kOutputReference[] = {0.004394f, 0.005406f, 0.005416f}; -#endif - - RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kHigh, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} - -TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzVeryHigh) { -#if defined(WEBRTC_ARCH_ARM64) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2677.733398f, 6186.987305f, - 14365.744141f}; - const float kOutputReference[] = {0.004273f, 0.005127f, 0.005188f}; -#elif defined(WEBRTC_ARCH_ARM) - const float kSpeechProbabilityReference = -4.0f; - const float kNoiseEstimateReference[] = {2677.733398f, 6186.987305f, - 14365.744141f}; - const float kOutputReference[] = {0.004273f, 0.005127f, 0.005188f}; -#else - const float kSpeechProbabilityReference = 0.70290041f; - const float kNoiseEstimateReference[] = {2254.921875f, 6723.172852f, - 15770.559570f}; - const float kOutputReference[] = {0.004321f, 0.005247f, 0.005263f}; -#endif - - RunBitexactnessTest(16000, 1, NoiseSuppression::Level::kVeryHigh, - kSpeechProbabilityReference, kNoiseEstimateReference, - kOutputReference); -} -} // namespace webrtc
diff --git a/modules/audio_processing/legacy_ns/noise_suppression.c b/modules/audio_processing/legacy_ns/noise_suppression.c deleted file mode 100644 index 8b95640..0000000 --- a/modules/audio_processing/legacy_ns/noise_suppression.c +++ /dev/null
@@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_processing/legacy_ns/noise_suppression.h" - -#include <stdlib.h> -#include <string.h> - -#include "common_audio/signal_processing/include/signal_processing_library.h" -#include "modules/audio_processing/legacy_ns/defines.h" -#include "modules/audio_processing/legacy_ns/ns_core.h" - -NsHandle* WebRtcNs_Create() { - NoiseSuppressionC* self = malloc(sizeof(NoiseSuppressionC)); - self->initFlag = 0; - return (NsHandle*)self; -} - -void WebRtcNs_Free(NsHandle* NS_inst) { - free(NS_inst); -} - -int WebRtcNs_Init(NsHandle* NS_inst, uint32_t fs) { - return WebRtcNs_InitCore((NoiseSuppressionC*)NS_inst, fs); -} - -int WebRtcNs_set_policy(NsHandle* NS_inst, int mode) { - return WebRtcNs_set_policy_core((NoiseSuppressionC*)NS_inst, mode); -} - -void WebRtcNs_Analyze(NsHandle* NS_inst, const float* spframe) { - WebRtcNs_AnalyzeCore((NoiseSuppressionC*)NS_inst, spframe); -} - -void WebRtcNs_Process(NsHandle* NS_inst, - const float* const* spframe, - size_t num_bands, - float* const* outframe) { - WebRtcNs_ProcessCore((NoiseSuppressionC*)NS_inst, spframe, num_bands, - outframe); -} - -float WebRtcNs_prior_speech_probability(NsHandle* handle) { - NoiseSuppressionC* self = (NoiseSuppressionC*)handle; - if (handle == NULL) { - return -1; - } - if (self->initFlag == 0) { - return -1; - } - return self->priorSpeechProb; -} - -const float* WebRtcNs_noise_estimate(const NsHandle* handle) { - const NoiseSuppressionC* self = (const NoiseSuppressionC*)handle; - if (handle == NULL || self->initFlag == 0) { - return NULL; - } - return self->noise; -} - -size_t WebRtcNs_num_freq() { - return HALF_ANAL_BLOCKL; -}
diff --git a/modules/audio_processing/legacy_ns/noise_suppression.h b/modules/audio_processing/legacy_ns/noise_suppression.h deleted file mode 100644 index 01f04cc..0000000 --- a/modules/audio_processing/legacy_ns/noise_suppression.h +++ /dev/null
@@ -1,134 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_H_ - -#include <stddef.h> -#include <stdint.h> - -typedef struct NsHandleT NsHandle; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This function creates an instance of the floating point Noise Suppression. - */ -NsHandle* WebRtcNs_Create(void); - -/* - * This function frees the dynamic memory of a specified noise suppression - * instance. - * - * Input: - * - NS_inst : Pointer to NS instance that should be freed - */ -void WebRtcNs_Free(NsHandle* NS_inst); - -/* - * This function initializes a NS instance and has to be called before any other - * processing is made. - * - * Input: - * - NS_inst : Instance that should be initialized - * - fs : sampling frequency - * - * Output: - * - NS_inst : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNs_Init(NsHandle* NS_inst, uint32_t fs); - -/* - * This changes the aggressiveness of the noise suppression method. - * - * Input: - * - NS_inst : Noise suppression instance. - * - mode : 0: Mild, 1: Medium , 2: Aggressive - * - * Output: - * - NS_inst : Updated instance. - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNs_set_policy(NsHandle* NS_inst, int mode); - -/* - * This functions estimates the background noise for the inserted speech frame. - * The input and output signals should always be 10ms (80 or 160 samples). - * - * Input - * - NS_inst : Noise suppression instance. - * - spframe : Pointer to speech frame buffer for L band - * - * Output: - * - NS_inst : Updated NS instance - */ -void WebRtcNs_Analyze(NsHandle* NS_inst, const float* spframe); - -/* - * This functions does Noise Suppression for the inserted speech frame. The - * input and output signals should always be 10ms (80 or 160 samples). - * - * Input - * - NS_inst : Noise suppression instance. - * - spframe : Pointer to speech frame buffer for each band - * - num_bands : Number of bands - * - * Output: - * - NS_inst : Updated NS instance - * - outframe : Pointer to output frame for each band - */ -void WebRtcNs_Process(NsHandle* NS_inst, - const float* const* spframe, - size_t num_bands, - float* const* outframe); - -/* Returns the internally used prior speech probability of the current frame. - * There is a frequency bin based one as well, with which this should not be - * confused. - * - * Input - * - handle : Noise suppression instance. - * - * Return value : Prior speech probability in interval [0.0, 1.0]. - * -1 - NULL pointer or uninitialized instance. - */ -float WebRtcNs_prior_speech_probability(NsHandle* handle); - -/* Returns a pointer to the noise estimate per frequency bin. The number of - * frequency bins can be provided using WebRtcNs_num_freq(). - * - * Input - * - handle : Noise suppression instance. - * - * Return value : Pointer to the noise estimate per frequency bin. - * Returns NULL if the input is a NULL pointer or an - * uninitialized instance. - */ -const float* WebRtcNs_noise_estimate(const NsHandle* handle); - -/* Returns the number of frequency bins, which is the length of the noise - * estimate for example. - * - * Return value : Number of frequency bins. - */ -size_t WebRtcNs_num_freq(void); - -#ifdef __cplusplus -} -#endif - -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_H_
diff --git a/modules/audio_processing/legacy_ns/noise_suppression_x.c b/modules/audio_processing/legacy_ns/noise_suppression_x.c deleted file mode 100644 index faa866e..0000000 --- a/modules/audio_processing/legacy_ns/noise_suppression_x.c +++ /dev/null
@@ -1,60 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_processing/legacy_ns/noise_suppression_x.h" - -#include <stdlib.h> - -#include "common_audio/signal_processing/include/real_fft.h" -#include "modules/audio_processing/legacy_ns/nsx_core.h" -#include "modules/audio_processing/legacy_ns/nsx_defines.h" - -NsxHandle* WebRtcNsx_Create() { - NoiseSuppressionFixedC* self = malloc(sizeof(NoiseSuppressionFixedC)); - self->real_fft = NULL; - self->initFlag = 0; - return (NsxHandle*)self; -} - -void WebRtcNsx_Free(NsxHandle* nsxInst) { - WebRtcSpl_FreeRealFFT(((NoiseSuppressionFixedC*)nsxInst)->real_fft); - free(nsxInst); -} - -int WebRtcNsx_Init(NsxHandle* nsxInst, uint32_t fs) { - return WebRtcNsx_InitCore((NoiseSuppressionFixedC*)nsxInst, fs); -} - -int WebRtcNsx_set_policy(NsxHandle* nsxInst, int mode) { - return WebRtcNsx_set_policy_core((NoiseSuppressionFixedC*)nsxInst, mode); -} - -void WebRtcNsx_Process(NsxHandle* nsxInst, - const int16_t* const* speechFrame, - int num_bands, - int16_t* const* outFrame) { - WebRtcNsx_ProcessCore((NoiseSuppressionFixedC*)nsxInst, speechFrame, - num_bands, outFrame); -} - -const uint32_t* WebRtcNsx_noise_estimate(const NsxHandle* nsxInst, - int* q_noise) { - *q_noise = 11; - const NoiseSuppressionFixedC* self = (const NoiseSuppressionFixedC*)nsxInst; - if (nsxInst == NULL || self->initFlag == 0) { - return NULL; - } - *q_noise += self->prevQNoise; - return self->prevNoiseU32; -} - -size_t WebRtcNsx_num_freq() { - return HALF_ANAL_BLOCKL; -}
diff --git a/modules/audio_processing/legacy_ns/noise_suppression_x.h b/modules/audio_processing/legacy_ns/noise_suppression_x.h deleted file mode 100644 index 572db41..0000000 --- a/modules/audio_processing/legacy_ns/noise_suppression_x.h +++ /dev/null
@@ -1,112 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_X_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_X_H_ - -#include <stddef.h> -#include <stdint.h> - -typedef struct NsxHandleT NsxHandle; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This function creates an instance of the fixed point Noise Suppression. - */ -NsxHandle* WebRtcNsx_Create(void); - -/* - * This function frees the dynamic memory of a specified Noise Suppression - * instance. - * - * Input: - * - nsxInst : Pointer to NS instance that should be freed - */ -void WebRtcNsx_Free(NsxHandle* nsxInst); - -/* - * This function initializes a NS instance - * - * Input: - * - nsxInst : Instance that should be initialized - * - fs : sampling frequency - * - * Output: - * - nsxInst : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNsx_Init(NsxHandle* nsxInst, uint32_t fs); - -/* - * This changes the aggressiveness of the noise suppression method. - * - * Input: - * - nsxInst : Instance that should be initialized - * - mode : 0: Mild, 1: Medium , 2: Aggressive - * - * Output: - * - nsxInst : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNsx_set_policy(NsxHandle* nsxInst, int mode); - -/* - * This functions does noise suppression for the inserted speech frame. The - * input and output signals should always be 10ms (80 or 160 samples). - * - * Input - * - nsxInst : NSx instance. Needs to be initiated before call. - * - speechFrame : Pointer to speech frame buffer for each band - * - num_bands : Number of bands - * - * Output: - * - nsxInst : Updated NSx instance - * - outFrame : Pointer to output frame for each band - */ -void WebRtcNsx_Process(NsxHandle* nsxInst, - const int16_t* const* speechFrame, - int num_bands, - int16_t* const* outFrame); - -/* Returns a pointer to the noise estimate per frequency bin. The number of - * frequency bins can be provided using WebRtcNsx_num_freq(). - * - * Input - * - nsxInst : NSx instance. Needs to be initiated before call. - * - q_noise : Q value of the noise estimate, which is the number of - * bits that it needs to be right-shifted to be - * normalized. - * - * Return value : Pointer to the noise estimate per frequency bin. - * Returns NULL if the input is a NULL pointer or an - * uninitialized instance. - */ -const uint32_t* WebRtcNsx_noise_estimate(const NsxHandle* nsxInst, - int* q_noise); - -/* Returns the number of frequency bins, which is the length of the noise - * estimate for example. - * - * Return value : Number of frequency bins. - */ -size_t WebRtcNsx_num_freq(void); - -#ifdef __cplusplus -} -#endif - -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_X_H_
diff --git a/modules/audio_processing/legacy_ns/ns_core.c b/modules/audio_processing/legacy_ns/ns_core.c deleted file mode 100644 index b5dc829..0000000 --- a/modules/audio_processing/legacy_ns/ns_core.c +++ /dev/null
@@ -1,1420 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include <math.h> -#include <string.h> -#include <stdlib.h> - -#include "rtc_base/checks.h" -#include "common_audio/signal_processing/include/signal_processing_library.h" -#include "common_audio/third_party/fft4g/fft4g.h" -#include "modules/audio_processing/legacy_ns/noise_suppression.h" -#include "modules/audio_processing/legacy_ns/ns_core.h" -#include "modules/audio_processing/legacy_ns/windows_private.h" - -// Set Feature Extraction Parameters. -static void set_feature_extraction_parameters(NoiseSuppressionC* self) { - // Bin size of histogram. - self->featureExtractionParams.binSizeLrt = 0.1f; - self->featureExtractionParams.binSizeSpecFlat = 0.05f; - self->featureExtractionParams.binSizeSpecDiff = 0.1f; - - // Range of histogram over which LRT threshold is computed. - self->featureExtractionParams.rangeAvgHistLrt = 1.f; - - // Scale parameters: multiply dominant peaks of the histograms by scale factor - // to obtain thresholds for prior model. - // For LRT and spectral difference. - self->featureExtractionParams.factor1ModelPars = 1.2f; - // For spectral_flatness: used when noise is flatter than speech. - self->featureExtractionParams.factor2ModelPars = 0.9f; - - // Peak limit for spectral flatness (varies between 0 and 1). - self->featureExtractionParams.thresPosSpecFlat = 0.6f; - - // Limit on spacing of two highest peaks in histogram: spacing determined by - // bin size. - self->featureExtractionParams.limitPeakSpacingSpecFlat = - 2 * self->featureExtractionParams.binSizeSpecFlat; - self->featureExtractionParams.limitPeakSpacingSpecDiff = - 2 * self->featureExtractionParams.binSizeSpecDiff; - - // Limit on relevance of second peak. - self->featureExtractionParams.limitPeakWeightsSpecFlat = 0.5f; - self->featureExtractionParams.limitPeakWeightsSpecDiff = 0.5f; - - // Fluctuation limit of LRT feature. - self->featureExtractionParams.thresFluctLrt = 0.05f; - - // Limit on the max and min values for the feature thresholds. - self->featureExtractionParams.maxLrt = 1.f; - self->featureExtractionParams.minLrt = 0.2f; - - self->featureExtractionParams.maxSpecFlat = 0.95f; - self->featureExtractionParams.minSpecFlat = 0.1f; - - self->featureExtractionParams.maxSpecDiff = 1.f; - self->featureExtractionParams.minSpecDiff = 0.16f; - - // Criteria of weight of histogram peak to accept/reject feature. - self->featureExtractionParams.thresWeightSpecFlat = - (int)(0.3 * (self->modelUpdatePars[1])); // For spectral flatness. - self->featureExtractionParams.thresWeightSpecDiff = - (int)(0.3 * (self->modelUpdatePars[1])); // For spectral difference. -} - -// Initialize state. -int WebRtcNs_InitCore(NoiseSuppressionC* self, uint32_t fs) { - int i; - // Check for valid pointer. - if (self == NULL) { - return -1; - } - - // Initialization of struct. - if (fs == 8000 || fs == 16000 || fs == 32000 || fs == 48000) { - self->fs = fs; - } else { - return -1; - } - self->windShift = 0; - // We only support 10ms frames. - if (fs == 8000) { - self->blockLen = 80; - self->anaLen = 128; - self->window = kBlocks80w128; - } else { - self->blockLen = 160; - self->anaLen = 256; - self->window = kBlocks160w256; - } - self->magnLen = self->anaLen / 2 + 1; // Number of frequency bins. - - // Initialize FFT work arrays. - self->ip[0] = 0; // Setting this triggers initialization. - memset(self->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); - WebRtc_rdft(self->anaLen, 1, self->dataBuf, self->ip, self->wfft); - - memset(self->analyzeBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); - memset(self->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); - memset(self->syntBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); - - // For HB processing. - memset(self->dataBufHB, - 0, - sizeof(float) * NUM_HIGH_BANDS_MAX * ANAL_BLOCKL_MAX); - - // For quantile noise estimation. - memset(self->quantile, 0, sizeof(float) * HALF_ANAL_BLOCKL); - for (i = 0; i < SIMULT * HALF_ANAL_BLOCKL; i++) { - self->lquantile[i] = 8.f; - self->density[i] = 0.3f; - } - - for (i = 0; i < SIMULT; i++) { - self->counter[i] = - (int)floor((float)(END_STARTUP_LONG * (i + 1)) / (float)SIMULT); - } - - self->updates = 0; - - // Wiener filter initialization. - for (i = 0; i < HALF_ANAL_BLOCKL; i++) { - self->smooth[i] = 1.f; - } - - // Set the aggressiveness: default. - self->aggrMode = 0; - - // Initialize variables for new method. - self->priorSpeechProb = 0.5f; // Prior prob for speech/noise. - // Previous analyze mag spectrum. - memset(self->magnPrevAnalyze, 0, sizeof(float) * HALF_ANAL_BLOCKL); - // Previous process mag spectrum. - memset(self->magnPrevProcess, 0, sizeof(float) * HALF_ANAL_BLOCKL); - // Current noise-spectrum. - memset(self->noise, 0, sizeof(float) * HALF_ANAL_BLOCKL); - // Previous noise-spectrum. - memset(self->noisePrev, 0, sizeof(float) * HALF_ANAL_BLOCKL); - // Conservative noise spectrum estimate. - memset(self->magnAvgPause, 0, sizeof(float) * HALF_ANAL_BLOCKL); - // For estimation of HB in second pass. - memset(self->speechProb, 0, sizeof(float) * HALF_ANAL_BLOCKL); - // Initial average magnitude spectrum. - memset(self->initMagnEst, 0, sizeof(float) * HALF_ANAL_BLOCKL); - for (i = 0; i < HALF_ANAL_BLOCKL; i++) { - // Smooth LR (same as threshold). - self->logLrtTimeAvg[i] = LRT_FEATURE_THR; - } - - // Feature quantities. - // Spectral flatness (start on threshold). - self->featureData[0] = SF_FEATURE_THR; - self->featureData[1] = 0.f; // Spectral entropy: not used in this version. - self->featureData[2] = 0.f; // Spectral variance: not used in this version. - // Average LRT factor (start on threshold). - self->featureData[3] = LRT_FEATURE_THR; - // Spectral template diff (start on threshold). - self->featureData[4] = SF_FEATURE_THR; - self->featureData[5] = 0.f; // Normalization for spectral difference. - // Window time-average of input magnitude spectrum. - self->featureData[6] = 0.f; - - memset(self->parametricNoise, 0, sizeof(float) * HALF_ANAL_BLOCKL); - - // Histogram quantities: used to estimate/update thresholds for features. - memset(self->histLrt, 0, sizeof(int) * HIST_PAR_EST); - memset(self->histSpecFlat, 0, sizeof(int) * HIST_PAR_EST); - memset(self->histSpecDiff, 0, sizeof(int) * HIST_PAR_EST); - - - self->blockInd = -1; // Frame counter. - // Default threshold for LRT feature. - self->priorModelPars[0] = LRT_FEATURE_THR; - // Threshold for spectral flatness: determined on-line. - self->priorModelPars[1] = 0.5f; - // sgn_map par for spectral measure: 1 for flatness measure. - self->priorModelPars[2] = 1.f; - // Threshold for template-difference feature: determined on-line. - self->priorModelPars[3] = 0.5f; - // Default weighting parameter for LRT feature. - self->priorModelPars[4] = 1.f; - // Default weighting parameter for spectral flatness feature. - self->priorModelPars[5] = 0.f; - // Default weighting parameter for spectral difference feature. - self->priorModelPars[6] = 0.f; - - // Update flag for parameters: - // 0 no update, 1 = update once, 2 = update every window. - self->modelUpdatePars[0] = 2; - self->modelUpdatePars[1] = 500; // Window for update. - // Counter for update of conservative noise spectrum. - self->modelUpdatePars[2] = 0; - // Counter if the feature thresholds are updated during the sequence. - self->modelUpdatePars[3] = self->modelUpdatePars[1]; - - self->signalEnergy = 0.0; - self->sumMagn = 0.0; - self->whiteNoiseLevel = 0.0; - self->pinkNoiseNumerator = 0.0; - self->pinkNoiseExp = 0.0; - - set_feature_extraction_parameters(self); - - // Default mode. - WebRtcNs_set_policy_core(self, 0); - - self->initFlag = 1; - return 0; -} - -// Estimate noise. -static void NoiseEstimation(NoiseSuppressionC* self, - float* magn, - float* noise) { - size_t i, s, offset; - float lmagn[HALF_ANAL_BLOCKL], delta; - - if (self->updates < END_STARTUP_LONG) { - self->updates++; - } - - for (i = 0; i < self->magnLen; i++) { - lmagn[i] = (float)log(magn[i]); - } - - // Loop over simultaneous estimates. - for (s = 0; s < SIMULT; s++) { - offset = s * self->magnLen; - - // newquantest(...) - for (i = 0; i < self->magnLen; i++) { - // Compute delta. - if (self->density[offset + i] > 1.0) { - delta = FACTOR * 1.f / self->density[offset + i]; - } else { - delta = FACTOR; - } - - // Update log quantile estimate. - if (lmagn[i] > self->lquantile[offset + i]) { - self->lquantile[offset + i] += - QUANTILE * delta / (float)(self->counter[s] + 1); - } else { - self->lquantile[offset + i] -= - (1.f - QUANTILE) * delta / (float)(self->counter[s] + 1); - } - - // Update density estimate. - if (fabs(lmagn[i] - self->lquantile[offset + i]) < WIDTH) { - self->density[offset + i] = - ((float)self->counter[s] * self->density[offset + i] + - 1.f / (2.f * WIDTH)) / - (float)(self->counter[s] + 1); - } - } // End loop over magnitude spectrum. - - if (self->counter[s] >= END_STARTUP_LONG) { - self->counter[s] = 0; - if (self->updates >= END_STARTUP_LONG) { - for (i = 0; i < self->magnLen; i++) { - self->quantile[i] = (float)exp(self->lquantile[offset + i]); - } - } - } - - self->counter[s]++; - } // End loop over simultaneous estimates. - - // Sequentially update the noise during startup. - if (self->updates < END_STARTUP_LONG) { - // Use the last "s" to get noise during startup that differ from zero. - for (i = 0; i < self->magnLen; i++) { - self->quantile[i] = (float)exp(self->lquantile[offset + i]); - } - } - - for (i = 0; i < self->magnLen; i++) { - noise[i] = self->quantile[i]; - } -} - -// Extract thresholds for feature parameters. -// Histograms are computed over some window size (given by -// self->modelUpdatePars[1]). -// Thresholds and weights are extracted every window. -// |flag| = 0 updates histogram only, |flag| = 1 computes the threshold/weights. -// Threshold and weights are returned in: self->priorModelPars. -static void FeatureParameterExtraction(NoiseSuppressionC* self, int flag) { - int i, useFeatureSpecFlat, useFeatureSpecDiff, numHistLrt; - int maxPeak1, maxPeak2; - int weightPeak1SpecFlat, weightPeak2SpecFlat, weightPeak1SpecDiff, - weightPeak2SpecDiff; - - float binMid, featureSum; - float posPeak1SpecFlat, posPeak2SpecFlat, posPeak1SpecDiff, posPeak2SpecDiff; - float fluctLrt, avgHistLrt, avgSquareHistLrt, avgHistLrtCompl; - - // 3 features: LRT, flatness, difference. - // lrt_feature = self->featureData[3]; - // flat_feature = self->featureData[0]; - // diff_feature = self->featureData[4]; - - // Update histograms. - if (flag == 0) { - // LRT - if ((self->featureData[3] < - HIST_PAR_EST * self->featureExtractionParams.binSizeLrt) && - (self->featureData[3] >= 0.0)) { - i = (int)(self->featureData[3] / - self->featureExtractionParams.binSizeLrt); - self->histLrt[i]++; - } - // Spectral flatness. - if ((self->featureData[0] < - HIST_PAR_EST * self->featureExtractionParams.binSizeSpecFlat) && - (self->featureData[0] >= 0.0)) { - i = (int)(self->featureData[0] / - self->featureExtractionParams.binSizeSpecFlat); - self->histSpecFlat[i]++; - } - // Spectral difference. - if ((self->featureData[4] < - HIST_PAR_EST * self->featureExtractionParams.binSizeSpecDiff) && - (self->featureData[4] >= 0.0)) { - i = (int)(self->featureData[4] / - self->featureExtractionParams.binSizeSpecDiff); - self->histSpecDiff[i]++; - } - } - - // Extract parameters for speech/noise probability. - if (flag == 1) { - // LRT feature: compute the average over - // self->featureExtractionParams.rangeAvgHistLrt. - avgHistLrt = 0.0; - avgHistLrtCompl = 0.0; - avgSquareHistLrt = 0.0; - numHistLrt = 0; - for (i = 0; i < HIST_PAR_EST; i++) { - binMid = ((float)i + 0.5f) * self->featureExtractionParams.binSizeLrt; - if (binMid <= self->featureExtractionParams.rangeAvgHistLrt) { - avgHistLrt += self->histLrt[i] * binMid; - numHistLrt += self->histLrt[i]; - } - avgSquareHistLrt += self->histLrt[i] * binMid * binMid; - avgHistLrtCompl += self->histLrt[i] * binMid; - } - if (numHistLrt > 0) { - avgHistLrt = avgHistLrt / ((float)numHistLrt); - } - avgHistLrtCompl = avgHistLrtCompl / ((float)self->modelUpdatePars[1]); - avgSquareHistLrt = avgSquareHistLrt / ((float)self->modelUpdatePars[1]); - fluctLrt = avgSquareHistLrt - avgHistLrt * avgHistLrtCompl; - // Get threshold for LRT feature. - if (fluctLrt < self->featureExtractionParams.thresFluctLrt) { - // Very low fluctuation, so likely noise. - self->priorModelPars[0] = self->featureExtractionParams.maxLrt; - } else { - self->priorModelPars[0] = - self->featureExtractionParams.factor1ModelPars * avgHistLrt; - // Check if value is within min/max range. - if (self->priorModelPars[0] < self->featureExtractionParams.minLrt) { - self->priorModelPars[0] = self->featureExtractionParams.minLrt; - } - if (self->priorModelPars[0] > self->featureExtractionParams.maxLrt) { - self->priorModelPars[0] = self->featureExtractionParams.maxLrt; - } - } - // Done with LRT feature. - - // For spectral flatness and spectral difference: compute the main peaks of - // histogram. - maxPeak1 = 0; - maxPeak2 = 0; - posPeak1SpecFlat = 0.0; - posPeak2SpecFlat = 0.0; - weightPeak1SpecFlat = 0; - weightPeak2SpecFlat = 0; - - // Peaks for flatness. - for (i = 0; i < HIST_PAR_EST; i++) { - binMid = - (i + 0.5f) * self->featureExtractionParams.binSizeSpecFlat; - if (self->histSpecFlat[i] > maxPeak1) { - // Found new "first" peak. - maxPeak2 = maxPeak1; - weightPeak2SpecFlat = weightPeak1SpecFlat; - posPeak2SpecFlat = posPeak1SpecFlat; - - maxPeak1 = self->histSpecFlat[i]; - weightPeak1SpecFlat = self->histSpecFlat[i]; - posPeak1SpecFlat = binMid; - } else if (self->histSpecFlat[i] > maxPeak2) { - // Found new "second" peak. - maxPeak2 = self->histSpecFlat[i]; - weightPeak2SpecFlat = self->histSpecFlat[i]; - posPeak2SpecFlat = binMid; - } - } - - // Compute two peaks for spectral difference. - maxPeak1 = 0; - maxPeak2 = 0; - posPeak1SpecDiff = 0.0; - posPeak2SpecDiff = 0.0; - weightPeak1SpecDiff = 0; - weightPeak2SpecDiff = 0; - // Peaks for spectral difference. - for (i = 0; i < HIST_PAR_EST; i++) { - binMid = - ((float)i + 0.5f) * self->featureExtractionParams.binSizeSpecDiff; - if (self->histSpecDiff[i] > maxPeak1) { - // Found new "first" peak. - maxPeak2 = maxPeak1; - weightPeak2SpecDiff = weightPeak1SpecDiff; - posPeak2SpecDiff = posPeak1SpecDiff; - - maxPeak1 = self->histSpecDiff[i]; - weightPeak1SpecDiff = self->histSpecDiff[i]; - posPeak1SpecDiff = binMid; - } else if (self->histSpecDiff[i] > maxPeak2) { - // Found new "second" peak. - maxPeak2 = self->histSpecDiff[i]; - weightPeak2SpecDiff = self->histSpecDiff[i]; - posPeak2SpecDiff = binMid; - } - } - - // For spectrum flatness feature. - useFeatureSpecFlat = 1; - // Merge the two peaks if they are close. - if ((fabs(posPeak2SpecFlat - posPeak1SpecFlat) < - self->featureExtractionParams.limitPeakSpacingSpecFlat) && - (weightPeak2SpecFlat > - self->featureExtractionParams.limitPeakWeightsSpecFlat * - weightPeak1SpecFlat)) { - weightPeak1SpecFlat += weightPeak2SpecFlat; - posPeak1SpecFlat = 0.5f * (posPeak1SpecFlat + posPeak2SpecFlat); - } - // Reject if weight of peaks is not large enough, or peak value too small. - if (weightPeak1SpecFlat < - self->featureExtractionParams.thresWeightSpecFlat || - posPeak1SpecFlat < self->featureExtractionParams.thresPosSpecFlat) { - useFeatureSpecFlat = 0; - } - // If selected, get the threshold. - if (useFeatureSpecFlat == 1) { - // Compute the threshold. - self->priorModelPars[1] = - self->featureExtractionParams.factor2ModelPars * posPeak1SpecFlat; - // Check if value is within min/max range. - if (self->priorModelPars[1] < self->featureExtractionParams.minSpecFlat) { - self->priorModelPars[1] = self->featureExtractionParams.minSpecFlat; - } - if (self->priorModelPars[1] > self->featureExtractionParams.maxSpecFlat) { - self->priorModelPars[1] = self->featureExtractionParams.maxSpecFlat; - } - } - // Done with flatness feature. - - // For template feature. - useFeatureSpecDiff = 1; - // Merge the two peaks if they are close. - if ((fabs(posPeak2SpecDiff - posPeak1SpecDiff) < - self->featureExtractionParams.limitPeakSpacingSpecDiff) && - (weightPeak2SpecDiff > - self->featureExtractionParams.limitPeakWeightsSpecDiff * - weightPeak1SpecDiff)) { - weightPeak1SpecDiff += weightPeak2SpecDiff; - posPeak1SpecDiff = 0.5f * (posPeak1SpecDiff + posPeak2SpecDiff); - } - // Get the threshold value. - self->priorModelPars[3] = - self->featureExtractionParams.factor1ModelPars * posPeak1SpecDiff; - // Reject if weight of peaks is not large enough. - if (weightPeak1SpecDiff < - self->featureExtractionParams.thresWeightSpecDiff) { - useFeatureSpecDiff = 0; - } - // Check if value is within min/max range. - if (self->priorModelPars[3] < self->featureExtractionParams.minSpecDiff) { - self->priorModelPars[3] = self->featureExtractionParams.minSpecDiff; - } - if (self->priorModelPars[3] > self->featureExtractionParams.maxSpecDiff) { - self->priorModelPars[3] = self->featureExtractionParams.maxSpecDiff; - } - // Done with spectral difference feature. - - // Don't use template feature if fluctuation of LRT feature is very low: - // most likely just noise state. - if (fluctLrt < self->featureExtractionParams.thresFluctLrt) { - useFeatureSpecDiff = 0; - } - - // Select the weights between the features. - // self->priorModelPars[4] is weight for LRT: always selected. - // self->priorModelPars[5] is weight for spectral flatness. - // self->priorModelPars[6] is weight for spectral difference. - featureSum = (float)(1 + useFeatureSpecFlat + useFeatureSpecDiff); - self->priorModelPars[4] = 1.f / featureSum; - self->priorModelPars[5] = ((float)useFeatureSpecFlat) / featureSum; - self->priorModelPars[6] = ((float)useFeatureSpecDiff) / featureSum; - - // Set hists to zero for next update. - if (self->modelUpdatePars[0] >= 1) { - for (i = 0; i < HIST_PAR_EST; i++) { - self->histLrt[i] = 0; - self->histSpecFlat[i] = 0; - self->histSpecDiff[i] = 0; - } - } - } // End of flag == 1. -} - -// Compute spectral flatness on input spectrum. -// |magnIn| is the magnitude spectrum. -// Spectral flatness is returned in self->featureData[0]. -static void ComputeSpectralFlatness(NoiseSuppressionC* self, - const float* magnIn) { - size_t i; - size_t shiftLP = 1; // Option to remove first bin(s) from spectral measures. - float avgSpectralFlatnessNum, avgSpectralFlatnessDen, spectralTmp; - - // Compute spectral measures. - // For flatness. - avgSpectralFlatnessNum = 0.0; - avgSpectralFlatnessDen = self->sumMagn; - for (i = 0; i < shiftLP; i++) { - avgSpectralFlatnessDen -= magnIn[i]; - } - // Compute log of ratio of the geometric to arithmetic mean: check for log(0) - // case. - for (i = shiftLP; i < self->magnLen; i++) { - if (magnIn[i] > 0.0) { - avgSpectralFlatnessNum += (float)log(magnIn[i]); - } else { - self->featureData[0] -= SPECT_FL_TAVG * self->featureData[0]; - return; - } - } - // Normalize. - avgSpectralFlatnessDen = avgSpectralFlatnessDen / self->magnLen; - avgSpectralFlatnessNum = avgSpectralFlatnessNum / self->magnLen; - - // Ratio and inverse log: check for case of log(0). - spectralTmp = (float)exp(avgSpectralFlatnessNum) / avgSpectralFlatnessDen; - - // Time-avg update of spectral flatness feature. - self->featureData[0] += SPECT_FL_TAVG * (spectralTmp - self->featureData[0]); - // Done with flatness feature. -} - -// Compute prior and post SNR based on quantile noise estimation. -// Compute DD estimate of prior SNR. -// Inputs: -// * |magn| is the signal magnitude spectrum estimate. -// * |noise| is the magnitude noise spectrum estimate. -// Outputs: -// * |snrLocPrior| is the computed prior SNR. -// * |snrLocPost| is the computed post SNR. -static void ComputeSnr(const NoiseSuppressionC* self, - const float* magn, - const float* noise, - float* snrLocPrior, - float* snrLocPost) { - size_t i; - - for (i = 0; i < self->magnLen; i++) { - // Previous post SNR. - // Previous estimate: based on previous frame with gain filter. - float previousEstimateStsa = self->magnPrevAnalyze[i] / - (self->noisePrev[i] + 0.0001f) * self->smooth[i]; - // Post SNR. - snrLocPost[i] = 0.f; - if (magn[i] > noise[i]) { - snrLocPost[i] = magn[i] / (noise[i] + 0.0001f) - 1.f; - } - // DD estimate is sum of two terms: current estimate and previous estimate. - // Directed decision update of snrPrior. - snrLocPrior[i] = - DD_PR_SNR * previousEstimateStsa + (1.f - DD_PR_SNR) * snrLocPost[i]; - } // End of loop over frequencies. -} - -// Compute the difference measure between input spectrum and a template/learned -// noise spectrum. -// |magnIn| is the input spectrum. -// The reference/template spectrum is self->magnAvgPause[i]. -// Returns (normalized) spectral difference in self->featureData[4]. -static void ComputeSpectralDifference(NoiseSuppressionC* self, - const float* magnIn) { - // avgDiffNormMagn = var(magnIn) - cov(magnIn, magnAvgPause)^2 / - // var(magnAvgPause) - size_t i; - float avgPause, avgMagn, covMagnPause, varPause, varMagn, avgDiffNormMagn; - - avgPause = 0.0; - avgMagn = self->sumMagn; - // Compute average quantities. - for (i = 0; i < self->magnLen; i++) { - // Conservative smooth noise spectrum from pause frames. - avgPause += self->magnAvgPause[i]; - } - avgPause /= self->magnLen; - avgMagn /= self->magnLen; - - covMagnPause = 0.0; - varPause = 0.0; - varMagn = 0.0; - // Compute variance and covariance quantities. - for (i = 0; i < self->magnLen; i++) { - covMagnPause += (magnIn[i] - avgMagn) * (self->magnAvgPause[i] - avgPause); - varPause += - (self->magnAvgPause[i] - avgPause) * (self->magnAvgPause[i] - avgPause); - varMagn += (magnIn[i] - avgMagn) * (magnIn[i] - avgMagn); - } - covMagnPause /= self->magnLen; - varPause /= self->magnLen; - varMagn /= self->magnLen; - // Update of average magnitude spectrum. - self->featureData[6] += self->signalEnergy; - - avgDiffNormMagn = - varMagn - (covMagnPause * covMagnPause) / (varPause + 0.0001f); - // Normalize and compute time-avg update of difference feature. - avgDiffNormMagn = (float)(avgDiffNormMagn / (self->featureData[5] + 0.0001f)); - self->featureData[4] += - SPECT_DIFF_TAVG * (avgDiffNormMagn - self->featureData[4]); -} - -// Compute speech/noise probability. -// Speech/noise probability is returned in |probSpeechFinal|. -// |magn| is the input magnitude spectrum. -// |noise| is the noise spectrum. -// |snrLocPrior| is the prior SNR for each frequency. -// |snrLocPost| is the post SNR for each frequency. -static void SpeechNoiseProb(NoiseSuppressionC* self, - float* probSpeechFinal, - const float* snrLocPrior, - const float* snrLocPost) { - size_t i; - int sgnMap; - float invLrt, gainPrior, indPrior; - float logLrtTimeAvgKsum, besselTmp; - float indicator0, indicator1, indicator2; - float tmpFloat1, tmpFloat2; - float weightIndPrior0, weightIndPrior1, weightIndPrior2; - float threshPrior0, threshPrior1, threshPrior2; - float widthPrior, widthPrior0, widthPrior1, widthPrior2; - - widthPrior0 = WIDTH_PR_MAP; - // Width for pause region: lower range, so increase width in tanh map. - widthPrior1 = 2.f * WIDTH_PR_MAP; - widthPrior2 = 2.f * WIDTH_PR_MAP; // For spectral-difference measure. - - // Threshold parameters for features. - threshPrior0 = self->priorModelPars[0]; - threshPrior1 = self->priorModelPars[1]; - threshPrior2 = self->priorModelPars[3]; - - // Sign for flatness feature. - sgnMap = (int)(self->priorModelPars[2]); - - // Weight parameters for features. - weightIndPrior0 = self->priorModelPars[4]; - weightIndPrior1 = self->priorModelPars[5]; - weightIndPrior2 = self->priorModelPars[6]; - - // Compute feature based on average LR factor. - // This is the average over all frequencies of the smooth log LRT. - logLrtTimeAvgKsum = 0.0; - for (i = 0; i < self->magnLen; i++) { - tmpFloat1 = 1.f + 2.f * snrLocPrior[i]; - tmpFloat2 = 2.f * snrLocPrior[i] / (tmpFloat1 + 0.0001f); - besselTmp = (snrLocPost[i] + 1.f) * tmpFloat2; - self->logLrtTimeAvg[i] += - LRT_TAVG * (besselTmp - (float)log(tmpFloat1) - self->logLrtTimeAvg[i]); - logLrtTimeAvgKsum += self->logLrtTimeAvg[i]; - } - logLrtTimeAvgKsum = (float)logLrtTimeAvgKsum / (self->magnLen); - self->featureData[3] = logLrtTimeAvgKsum; - // Done with computation of LR factor. - - // Compute the indicator functions. - // Average LRT feature. - widthPrior = widthPrior0; - // Use larger width in tanh map for pause regions. - if (logLrtTimeAvgKsum < threshPrior0) { - widthPrior = widthPrior1; - } - // Compute indicator function: sigmoid map. - indicator0 = - 0.5f * - ((float)tanh(widthPrior * (logLrtTimeAvgKsum - threshPrior0)) + 1.f); - - // Spectral flatness feature. - tmpFloat1 = self->featureData[0]; - widthPrior = widthPrior0; - // Use larger width in tanh map for pause regions. - if (sgnMap == 1 && (tmpFloat1 > threshPrior1)) { - widthPrior = widthPrior1; - } - if (sgnMap == -1 && (tmpFloat1 < threshPrior1)) { - widthPrior = widthPrior1; - } - // Compute indicator function: sigmoid map. - indicator1 = - 0.5f * - ((float)tanh((float)sgnMap * widthPrior * (threshPrior1 - tmpFloat1)) + - 1.f); - - // For template spectrum-difference. - tmpFloat1 = self->featureData[4]; - widthPrior = widthPrior0; - // Use larger width in tanh map for pause regions. - if (tmpFloat1 < threshPrior2) { - widthPrior = widthPrior2; - } - // Compute indicator function: sigmoid map. - indicator2 = - 0.5f * ((float)tanh(widthPrior * (tmpFloat1 - threshPrior2)) + 1.f); - - // Combine the indicator function with the feature weights. - indPrior = weightIndPrior0 * indicator0 + weightIndPrior1 * indicator1 + - weightIndPrior2 * indicator2; - // Done with computing indicator function. - - // Compute the prior probability. - self->priorSpeechProb += PRIOR_UPDATE * (indPrior - self->priorSpeechProb); - // Make sure probabilities are within range: keep floor to 0.01. - if (self->priorSpeechProb > 1.f) { - self->priorSpeechProb = 1.f; - } - if (self->priorSpeechProb < 0.01f) { - self->priorSpeechProb = 0.01f; - } - - // Final speech probability: combine prior model with LR factor:. - gainPrior = (1.f - self->priorSpeechProb) / (self->priorSpeechProb + 0.0001f); - for (i = 0; i < self->magnLen; i++) { - invLrt = (float)exp(-self->logLrtTimeAvg[i]); - invLrt = (float)gainPrior * invLrt; - probSpeechFinal[i] = 1.f / (1.f + invLrt); - } -} - -// Update the noise features. -// Inputs: -// * |magn| is the signal magnitude spectrum estimate. -// * |updateParsFlag| is an update flag for parameters. -static void FeatureUpdate(NoiseSuppressionC* self, - const float* magn, - int updateParsFlag) { - // Compute spectral flatness on input spectrum. - ComputeSpectralFlatness(self, magn); - // Compute difference of input spectrum with learned/estimated noise spectrum. - ComputeSpectralDifference(self, magn); - // Compute histograms for parameter decisions (thresholds and weights for - // features). - // Parameters are extracted once every window time. - // (=self->modelUpdatePars[1]) - if (updateParsFlag >= 1) { - // Counter update. - self->modelUpdatePars[3]--; - // Update histogram. - if (self->modelUpdatePars[3] > 0) { - FeatureParameterExtraction(self, 0); - } - // Compute model parameters. - if (self->modelUpdatePars[3] == 0) { - FeatureParameterExtraction(self, 1); - self->modelUpdatePars[3] = self->modelUpdatePars[1]; - // If wish to update only once, set flag to zero. - if (updateParsFlag == 1) { - self->modelUpdatePars[0] = 0; - } else { - // Update every window: - // Get normalization for spectral difference for next window estimate. - self->featureData[6] = - self->featureData[6] / ((float)self->modelUpdatePars[1]); - self->featureData[5] = - 0.5f * (self->featureData[6] + self->featureData[5]); - self->featureData[6] = 0.f; - } - } - } -} - -// Update the noise estimate. -// Inputs: -// * |magn| is the signal magnitude spectrum estimate. -// * |snrLocPrior| is the prior SNR. -// * |snrLocPost| is the post SNR. -// Output: -// * |noise| is the updated noise magnitude spectrum estimate. -static void UpdateNoiseEstimate(NoiseSuppressionC* self, - const float* magn, - const float* snrLocPrior, - const float* snrLocPost, - float* noise) { - size_t i; - float probSpeech, probNonSpeech; - // Time-avg parameter for noise update. - float gammaNoiseTmp = NOISE_UPDATE; - float gammaNoiseOld; - float noiseUpdateTmp; - - for (i = 0; i < self->magnLen; i++) { - probSpeech = self->speechProb[i]; - probNonSpeech = 1.f - probSpeech; - // Temporary noise update: - // Use it for speech frames if update value is less than previous. - noiseUpdateTmp = gammaNoiseTmp * self->noisePrev[i] + - (1.f - gammaNoiseTmp) * (probNonSpeech * magn[i] + - probSpeech * self->noisePrev[i]); - // Time-constant based on speech/noise state. - gammaNoiseOld = gammaNoiseTmp; - gammaNoiseTmp = NOISE_UPDATE; - // Increase gamma (i.e., less noise update) for frame likely to be speech. - if (probSpeech > PROB_RANGE) { - gammaNoiseTmp = SPEECH_UPDATE; - } - // Conservative noise update. - if (probSpeech < PROB_RANGE) { - self->magnAvgPause[i] += GAMMA_PAUSE * (magn[i] - self->magnAvgPause[i]); - } - // Noise update. - if (gammaNoiseTmp == gammaNoiseOld) { - noise[i] = noiseUpdateTmp; - } else { - noise[i] = gammaNoiseTmp * self->noisePrev[i] + - (1.f - gammaNoiseTmp) * (probNonSpeech * magn[i] + - probSpeech * self->noisePrev[i]); - // Allow for noise update downwards: - // If noise update decreases the noise, it is safe, so allow it to - // happen. - if (noiseUpdateTmp < noise[i]) { - noise[i] = noiseUpdateTmp; - } - } - } // End of freq loop. -} - -// Updates |buffer| with a new |frame|. -// Inputs: -// * |frame| is a new speech frame or NULL for setting to zero. -// * |frame_length| is the length of the new frame. -// * |buffer_length| is the length of the buffer. -// Output: -// * |buffer| is the updated buffer. -static void UpdateBuffer(const float* frame, - size_t frame_length, - size_t buffer_length, - float* buffer) { - RTC_DCHECK_LT(buffer_length, 2 * frame_length); - - memcpy(buffer, - buffer + frame_length, - sizeof(*buffer) * (buffer_length - frame_length)); - if (frame) { - memcpy(buffer + buffer_length - frame_length, - frame, - sizeof(*buffer) * frame_length); - } else { - memset(buffer + buffer_length - frame_length, - 0, - sizeof(*buffer) * frame_length); - } -} - -// Transforms the signal from time to frequency domain. -// Inputs: -// * |time_data| is the signal in the time domain. -// * |time_data_length| is the length of the analysis buffer. -// * |magnitude_length| is the length of the spectrum magnitude, which equals -// the length of both |real| and |imag| (time_data_length / 2 + 1). -// Outputs: -// * |time_data| is the signal in the frequency domain. -// * |real| is the real part of the frequency domain. -// * |imag| is the imaginary part of the frequency domain. -// * |magn| is the calculated signal magnitude in the frequency domain. -static void FFT(NoiseSuppressionC* self, - float* time_data, - size_t time_data_length, - size_t magnitude_length, - float* real, - float* imag, - float* magn) { - size_t i; - - RTC_DCHECK_EQ(magnitude_length, time_data_length / 2 + 1); - - WebRtc_rdft(time_data_length, 1, time_data, self->ip, self->wfft); - - imag[0] = 0; - real[0] = time_data[0]; - magn[0] = fabsf(real[0]) + 1.f; - imag[magnitude_length - 1] = 0; - real[magnitude_length - 1] = time_data[1]; - magn[magnitude_length - 1] = fabsf(real[magnitude_length - 1]) + 1.f; - for (i = 1; i < magnitude_length - 1; ++i) { - real[i] = time_data[2 * i]; - imag[i] = time_data[2 * i + 1]; - // Magnitude spectrum. - magn[i] = sqrtf(real[i] * real[i] + imag[i] * imag[i]) + 1.f; - } -} - -// Transforms the signal from frequency to time domain. -// Inputs: -// * |real| is the real part of the frequency domain. -// * |imag| is the imaginary part of the frequency domain. -// * |magnitude_length| is the length of the spectrum magnitude, which equals -// the length of both |real| and |imag|. -// * |time_data_length| is the length of the analysis buffer -// (2 * (magnitude_length - 1)). -// Output: -// * |time_data| is the signal in the time domain. -static void IFFT(NoiseSuppressionC* self, - const float* real, - const float* imag, - size_t magnitude_length, - size_t time_data_length, - float* time_data) { - size_t i; - - RTC_DCHECK_EQ(time_data_length, 2 * (magnitude_length - 1)); - - time_data[0] = real[0]; - time_data[1] = real[magnitude_length - 1]; - for (i = 1; i < magnitude_length - 1; ++i) { - time_data[2 * i] = real[i]; - time_data[2 * i + 1] = imag[i]; - } - WebRtc_rdft(time_data_length, -1, time_data, self->ip, self->wfft); - - for (i = 0; i < time_data_length; ++i) { - time_data[i] *= 2.f / time_data_length; // FFT scaling. - } -} - -// Calculates the energy of a buffer. -// Inputs: -// * |buffer| is the buffer over which the energy is calculated. -// * |length| is the length of the buffer. -// Returns the calculated energy. -static float Energy(const float* buffer, size_t length) { - size_t i; - float energy = 0.f; - - for (i = 0; i < length; ++i) { - energy += buffer[i] * buffer[i]; - } - - return energy; -} - -// Windows a buffer. -// Inputs: -// * |window| is the window by which to multiply. -// * |data| is the data without windowing. -// * |length| is the length of the window and data. -// Output: -// * |data_windowed| is the windowed data. -static void Windowing(const float* window, - const float* data, - size_t length, - float* data_windowed) { - size_t i; - - for (i = 0; i < length; ++i) { - data_windowed[i] = window[i] * data[i]; - } -} - -// Estimate prior SNR decision-directed and compute DD based Wiener Filter. -// Input: -// * |magn| is the signal magnitude spectrum estimate. -// Output: -// * |theFilter| is the frequency response of the computed Wiener filter. -static void ComputeDdBasedWienerFilter(const NoiseSuppressionC* self, - const float* magn, - float* theFilter) { - size_t i; - float snrPrior, previousEstimateStsa, currentEstimateStsa; - - for (i = 0; i < self->magnLen; i++) { - // Previous estimate: based on previous frame with gain filter. - previousEstimateStsa = self->magnPrevProcess[i] / - (self->noisePrev[i] + 0.0001f) * self->smooth[i]; - // Post and prior SNR. - currentEstimateStsa = 0.f; - if (magn[i] > self->noise[i]) { - currentEstimateStsa = magn[i] / (self->noise[i] + 0.0001f) - 1.f; - } - // DD estimate is sum of two terms: current estimate and previous estimate. - // Directed decision update of |snrPrior|. - snrPrior = DD_PR_SNR * previousEstimateStsa + - (1.f - DD_PR_SNR) * currentEstimateStsa; - // Gain filter. - theFilter[i] = snrPrior / (self->overdrive + snrPrior); - } // End of loop over frequencies. -} - -// Changes the aggressiveness of the noise suppression method. -// |mode| = 0 is mild (6dB), |mode| = 1 is medium (10dB) and |mode| = 2 is -// aggressive (15dB). -// Returns 0 on success and -1 otherwise. -int WebRtcNs_set_policy_core(NoiseSuppressionC* self, int mode) { - // Allow for modes: 0, 1, 2, 3. - if (mode < 0 || mode > 3) { - return (-1); - } - - self->aggrMode = mode; - if (mode == 0) { - self->overdrive = 1.f; - self->denoiseBound = 0.5f; - self->gainmap = 0; - } else if (mode == 1) { - // self->overdrive = 1.25f; - self->overdrive = 1.f; - self->denoiseBound = 0.25f; - self->gainmap = 1; - } else if (mode == 2) { - // self->overdrive = 1.25f; - self->overdrive = 1.1f; - self->denoiseBound = 0.125f; - self->gainmap = 1; - } else if (mode == 3) { - // self->overdrive = 1.3f; - self->overdrive = 1.25f; - self->denoiseBound = 0.09f; - self->gainmap = 1; - } - return 0; -} - -void WebRtcNs_AnalyzeCore(NoiseSuppressionC* self, const float* speechFrame) { - size_t i; - const size_t kStartBand = 5; // Skip first frequency bins during estimation. - int updateParsFlag; - float energy; - float signalEnergy = 0.f; - float sumMagn = 0.f; - float tmpFloat1, tmpFloat2, tmpFloat3; - float winData[ANAL_BLOCKL_MAX]; - float magn[HALF_ANAL_BLOCKL], noise[HALF_ANAL_BLOCKL]; - float snrLocPost[HALF_ANAL_BLOCKL], snrLocPrior[HALF_ANAL_BLOCKL]; - float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL]; - // Variables during startup. - float sum_log_i = 0.0; - float sum_log_i_square = 0.0; - float sum_log_magn = 0.0; - float sum_log_i_log_magn = 0.0; - float parametric_exp = 0.0; - float parametric_num = 0.0; - - // Check that initiation has been done. - RTC_DCHECK_EQ(1, self->initFlag); - updateParsFlag = self->modelUpdatePars[0]; - - // Update analysis buffer for L band. - UpdateBuffer(speechFrame, self->blockLen, self->anaLen, self->analyzeBuf); - - Windowing(self->window, self->analyzeBuf, self->anaLen, winData); - energy = Energy(winData, self->anaLen); - if (energy == 0.0) { - // We want to avoid updating statistics in this case: - // Updating feature statistics when we have zeros only will cause - // thresholds to move towards zero signal situations. This in turn has the - // effect that once the signal is "turned on" (non-zero values) everything - // will be treated as speech and there is no noise suppression effect. - // Depending on the duration of the inactive signal it takes a - // considerable amount of time for the system to learn what is noise and - // what is speech. - self->signalEnergy = 0; - return; - } - - self->blockInd++; // Update the block index only when we process a block. - - FFT(self, winData, self->anaLen, self->magnLen, real, imag, magn); - - for (i = 0; i < self->magnLen; i++) { - signalEnergy += real[i] * real[i] + imag[i] * imag[i]; - sumMagn += magn[i]; - if (self->blockInd < END_STARTUP_SHORT) { - if (i >= kStartBand) { - tmpFloat2 = logf((float)i); - sum_log_i += tmpFloat2; - sum_log_i_square += tmpFloat2 * tmpFloat2; - tmpFloat1 = logf(magn[i]); - sum_log_magn += tmpFloat1; - sum_log_i_log_magn += tmpFloat2 * tmpFloat1; - } - } - } - signalEnergy /= self->magnLen; - self->signalEnergy = signalEnergy; - self->sumMagn = sumMagn; - - // Quantile noise estimate. - NoiseEstimation(self, magn, noise); - // Compute simplified noise model during startup. - if (self->blockInd < END_STARTUP_SHORT) { - // Estimate White noise. - self->whiteNoiseLevel += sumMagn / self->magnLen * self->overdrive; - // Estimate Pink noise parameters. - tmpFloat1 = sum_log_i_square * (self->magnLen - kStartBand); - tmpFloat1 -= (sum_log_i * sum_log_i); - tmpFloat2 = - (sum_log_i_square * sum_log_magn - sum_log_i * sum_log_i_log_magn); - tmpFloat3 = tmpFloat2 / tmpFloat1; - // Constrain the estimated spectrum to be positive. - if (tmpFloat3 < 0.f) { - tmpFloat3 = 0.f; - } - self->pinkNoiseNumerator += tmpFloat3; - tmpFloat2 = (sum_log_i * sum_log_magn); - tmpFloat2 -= (self->magnLen - kStartBand) * sum_log_i_log_magn; - tmpFloat3 = tmpFloat2 / tmpFloat1; - // Constrain the pink noise power to be in the interval [0, 1]. - if (tmpFloat3 < 0.f) { - tmpFloat3 = 0.f; - } - if (tmpFloat3 > 1.f) { - tmpFloat3 = 1.f; - } - self->pinkNoiseExp += tmpFloat3; - - // Calculate frequency independent parts of parametric noise estimate. - if (self->pinkNoiseExp > 0.f) { - // Use pink noise estimate. - parametric_num = - expf(self->pinkNoiseNumerator / (float)(self->blockInd + 1)); - parametric_num *= (float)(self->blockInd + 1); - parametric_exp = self->pinkNoiseExp / (float)(self->blockInd + 1); - } - for (i = 0; i < self->magnLen; i++) { - // Estimate the background noise using the white and pink noise - // parameters. - if (self->pinkNoiseExp == 0.f) { - // Use white noise estimate. - self->parametricNoise[i] = self->whiteNoiseLevel; - } else { - // Use pink noise estimate. - float use_band = (float)(i < kStartBand ? kStartBand : i); - self->parametricNoise[i] = - parametric_num / powf(use_band, parametric_exp); - } - // Weight quantile noise with modeled noise. - noise[i] *= (self->blockInd); - tmpFloat2 = - self->parametricNoise[i] * (END_STARTUP_SHORT - self->blockInd); - noise[i] += (tmpFloat2 / (float)(self->blockInd + 1)); - noise[i] /= END_STARTUP_SHORT; - } - } - // Compute average signal during END_STARTUP_LONG time: - // used to normalize spectral difference measure. - if (self->blockInd < END_STARTUP_LONG) { - self->featureData[5] *= self->blockInd; - self->featureData[5] += signalEnergy; - self->featureData[5] /= (self->blockInd + 1); - } - - // Post and prior SNR needed for SpeechNoiseProb. - ComputeSnr(self, magn, noise, snrLocPrior, snrLocPost); - - FeatureUpdate(self, magn, updateParsFlag); - SpeechNoiseProb(self, self->speechProb, snrLocPrior, snrLocPost); - UpdateNoiseEstimate(self, magn, snrLocPrior, snrLocPost, noise); - - // Keep track of noise spectrum for next frame. - memcpy(self->noise, noise, sizeof(*noise) * self->magnLen); - memcpy(self->magnPrevAnalyze, magn, sizeof(*magn) * self->magnLen); -} - -void WebRtcNs_ProcessCore(NoiseSuppressionC* self, - const float* const* speechFrame, - size_t num_bands, - float* const* outFrame) { - // Main routine for noise reduction. - int flagHB = 0; - size_t i, j; - - float energy1, energy2, gain, factor, factor1, factor2; - float fout[BLOCKL_MAX]; - float winData[ANAL_BLOCKL_MAX]; - float magn[HALF_ANAL_BLOCKL]; - float theFilter[HALF_ANAL_BLOCKL], theFilterTmp[HALF_ANAL_BLOCKL]; - float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL]; - - // SWB variables. - int deltaBweHB = 1; - int deltaGainHB = 1; - float decayBweHB = 1.0; - float gainMapParHB = 1.0; - float gainTimeDomainHB = 1.0; - float avgProbSpeechHB, avgProbSpeechHBTmp, avgFilterGainHB, gainModHB; - float sumMagnAnalyze, sumMagnProcess; - - // Check that initiation has been done. - RTC_DCHECK_EQ(1, self->initFlag); - RTC_DCHECK_LE(num_bands - 1, NUM_HIGH_BANDS_MAX); - - const float* const* speechFrameHB = NULL; - float* const* outFrameHB = NULL; - size_t num_high_bands = 0; - if (num_bands > 1) { - speechFrameHB = &speechFrame[1]; - outFrameHB = &outFrame[1]; - num_high_bands = num_bands - 1; - flagHB = 1; - // Range for averaging low band quantities for H band gain. - deltaBweHB = (int)self->magnLen / 4; - deltaGainHB = deltaBweHB; - } - - // Update analysis buffer for L band. - UpdateBuffer(speechFrame[0], self->blockLen, self->anaLen, self->dataBuf); - - if (flagHB == 1) { - // Update analysis buffer for H bands. - for (i = 0; i < num_high_bands; ++i) { - UpdateBuffer(speechFrameHB[i], - self->blockLen, - self->anaLen, - self->dataBufHB[i]); - } - } - - Windowing(self->window, self->dataBuf, self->anaLen, winData); - energy1 = Energy(winData, self->anaLen); - if (energy1 == 0.0 || self->signalEnergy == 0) { - // Synthesize the special case of zero input. - // Read out fully processed segment. - for (i = self->windShift; i < self->blockLen + self->windShift; i++) { - fout[i - self->windShift] = self->syntBuf[i]; - } - // Update synthesis buffer. - UpdateBuffer(NULL, self->blockLen, self->anaLen, self->syntBuf); - - for (i = 0; i < self->blockLen; ++i) - outFrame[0][i] = - WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, fout[i], WEBRTC_SPL_WORD16_MIN); - - // For time-domain gain of HB. - if (flagHB == 1) { - for (i = 0; i < num_high_bands; ++i) { - for (j = 0; j < self->blockLen; ++j) { - outFrameHB[i][j] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, - self->dataBufHB[i][j], - WEBRTC_SPL_WORD16_MIN); - } - } - } - - return; - } - - FFT(self, winData, self->anaLen, self->magnLen, real, imag, magn); - - if (self->blockInd < END_STARTUP_SHORT) { - for (i = 0; i < self->magnLen; i++) { - self->initMagnEst[i] += magn[i]; - } - } - - ComputeDdBasedWienerFilter(self, magn, theFilter); - - for (i = 0; i < self->magnLen; i++) { - // Flooring bottom. - if (theFilter[i] < self->denoiseBound) { - theFilter[i] = self->denoiseBound; - } - // Flooring top. - if (theFilter[i] > 1.f) { - theFilter[i] = 1.f; - } - if (self->blockInd < END_STARTUP_SHORT) { - theFilterTmp[i] = - (self->initMagnEst[i] - self->overdrive * self->parametricNoise[i]); - theFilterTmp[i] /= (self->initMagnEst[i] + 0.0001f); - // Flooring bottom. - if (theFilterTmp[i] < self->denoiseBound) { - theFilterTmp[i] = self->denoiseBound; - } - // Flooring top. - if (theFilterTmp[i] > 1.f) { - theFilterTmp[i] = 1.f; - } - // Weight the two suppression filters. - theFilter[i] *= (self->blockInd); - theFilterTmp[i] *= (END_STARTUP_SHORT - self->blockInd); - theFilter[i] += theFilterTmp[i]; - theFilter[i] /= (END_STARTUP_SHORT); - } - - self->smooth[i] = theFilter[i]; - real[i] *= self->smooth[i]; - imag[i] *= self->smooth[i]; - } - // Keep track of |magn| spectrum for next frame. - memcpy(self->magnPrevProcess, magn, sizeof(*magn) * self->magnLen); - memcpy(self->noisePrev, self->noise, sizeof(self->noise[0]) * self->magnLen); - // Back to time domain. - IFFT(self, real, imag, self->magnLen, self->anaLen, winData); - - // Scale factor: only do it after END_STARTUP_LONG time. - factor = 1.f; - if (self->gainmap == 1 && self->blockInd > END_STARTUP_LONG) { - factor1 = 1.f; - factor2 = 1.f; - - energy2 = Energy(winData, self->anaLen); - gain = (float)sqrt(energy2 / (energy1 + 1.f)); - - // Scaling for new version. - if (gain > B_LIM) { - factor1 = 1.f + 1.3f * (gain - B_LIM); - if (gain * factor1 > 1.f) { - factor1 = 1.f / gain; - } - } - if (gain < B_LIM) { - // Don't reduce scale too much for pause regions: - // attenuation here should be controlled by flooring. - if (gain <= self->denoiseBound) { - gain = self->denoiseBound; - } - factor2 = 1.f - 0.3f * (B_LIM - gain); - } - // Combine both scales with speech/noise prob: - // note prior (priorSpeechProb) is not frequency dependent. - factor = self->priorSpeechProb * factor1 + - (1.f - self->priorSpeechProb) * factor2; - } // Out of self->gainmap == 1. - - Windowing(self->window, winData, self->anaLen, winData); - - // Synthesis. - for (i = 0; i < self->anaLen; i++) { - self->syntBuf[i] += factor * winData[i]; - } - // Read out fully processed segment. - for (i = self->windShift; i < self->blockLen + self->windShift; i++) { - fout[i - self->windShift] = self->syntBuf[i]; - } - // Update synthesis buffer. - UpdateBuffer(NULL, self->blockLen, self->anaLen, self->syntBuf); - - for (i = 0; i < self->blockLen; ++i) - outFrame[0][i] = - WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, fout[i], WEBRTC_SPL_WORD16_MIN); - - // For time-domain gain of HB. - if (flagHB == 1) { - // Average speech prob from low band. - // Average over second half (i.e., 4->8kHz) of frequencies spectrum. - avgProbSpeechHB = 0.0; - for (i = self->magnLen - deltaBweHB - 1; i < self->magnLen - 1; i++) { - avgProbSpeechHB += self->speechProb[i]; - } - avgProbSpeechHB = avgProbSpeechHB / ((float)deltaBweHB); - // If the speech was suppressed by a component between Analyze and - // Process, for example the AEC, then it should not be considered speech - // for high band suppression purposes. - sumMagnAnalyze = 0; - sumMagnProcess = 0; - for (i = 0; i < self->magnLen; ++i) { - sumMagnAnalyze += self->magnPrevAnalyze[i]; - sumMagnProcess += self->magnPrevProcess[i]; - } - RTC_DCHECK_GT(sumMagnAnalyze, 0); - avgProbSpeechHB *= sumMagnProcess / sumMagnAnalyze; - // Average filter gain from low band. - // Average over second half (i.e., 4->8kHz) of frequencies spectrum. - avgFilterGainHB = 0.0; - for (i = self->magnLen - deltaGainHB - 1; i < self->magnLen - 1; i++) { - avgFilterGainHB += self->smooth[i]; - } - avgFilterGainHB = avgFilterGainHB / ((float)(deltaGainHB)); - avgProbSpeechHBTmp = 2.f * avgProbSpeechHB - 1.f; - // Gain based on speech probability. - gainModHB = 0.5f * (1.f + (float)tanh(gainMapParHB * avgProbSpeechHBTmp)); - // Combine gain with low band gain. - gainTimeDomainHB = 0.5f * gainModHB + 0.5f * avgFilterGainHB; - if (avgProbSpeechHB >= 0.5f) { - gainTimeDomainHB = 0.25f * gainModHB + 0.75f * avgFilterGainHB; - } - gainTimeDomainHB = gainTimeDomainHB * decayBweHB; - // Make sure gain is within flooring range. - // Flooring bottom. - if (gainTimeDomainHB < self->denoiseBound) { - gainTimeDomainHB = self->denoiseBound; - } - // Flooring top. - if (gainTimeDomainHB > 1.f) { - gainTimeDomainHB = 1.f; - } - // Apply gain. - for (i = 0; i < num_high_bands; ++i) { - for (j = 0; j < self->blockLen; j++) { - outFrameHB[i][j] = - WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, - gainTimeDomainHB * self->dataBufHB[i][j], - WEBRTC_SPL_WORD16_MIN); - } - } - } // End of H band gain computation. -}
diff --git a/modules/audio_processing/legacy_ns/ns_core.h b/modules/audio_processing/legacy_ns/ns_core.h deleted file mode 100644 index 7a3b0a4..0000000 --- a/modules/audio_processing/legacy_ns/ns_core.h +++ /dev/null
@@ -1,188 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NS_CORE_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NS_CORE_H_ - -#include "modules/audio_processing/legacy_ns/defines.h" - -typedef struct NSParaExtract_ { - // Bin size of histogram. - float binSizeLrt; - float binSizeSpecFlat; - float binSizeSpecDiff; - // Range of histogram over which LRT threshold is computed. - float rangeAvgHistLrt; - // Scale parameters: multiply dominant peaks of the histograms by scale factor - // to obtain thresholds for prior model. - float factor1ModelPars; // For LRT and spectral difference. - float factor2ModelPars; // For spectral_flatness: used when noise is flatter - // than speech. - // Peak limit for spectral flatness (varies between 0 and 1). - float thresPosSpecFlat; - // Limit on spacing of two highest peaks in histogram: spacing determined by - // bin size. - float limitPeakSpacingSpecFlat; - float limitPeakSpacingSpecDiff; - // Limit on relevance of second peak. - float limitPeakWeightsSpecFlat; - float limitPeakWeightsSpecDiff; - // Limit on fluctuation of LRT feature. - float thresFluctLrt; - // Limit on the max and min values for the feature thresholds. - float maxLrt; - float minLrt; - float maxSpecFlat; - float minSpecFlat; - float maxSpecDiff; - float minSpecDiff; - // Criteria of weight of histogram peak to accept/reject feature. - int thresWeightSpecFlat; - int thresWeightSpecDiff; -} NSParaExtract; - -typedef struct NoiseSuppressionC_ { - uint32_t fs; - size_t blockLen; - size_t windShift; - size_t anaLen; - size_t magnLen; - int aggrMode; - const float* window; - float analyzeBuf[ANAL_BLOCKL_MAX]; - float dataBuf[ANAL_BLOCKL_MAX]; - float syntBuf[ANAL_BLOCKL_MAX]; - - int initFlag; - // Parameters for quantile noise estimation. - float density[SIMULT * HALF_ANAL_BLOCKL]; - float lquantile[SIMULT * HALF_ANAL_BLOCKL]; - float quantile[HALF_ANAL_BLOCKL]; - int counter[SIMULT]; - int updates; - // Parameters for Wiener filter. - float smooth[HALF_ANAL_BLOCKL]; - float overdrive; - float denoiseBound; - int gainmap; - // FFT work arrays. - size_t ip[IP_LENGTH]; - float wfft[W_LENGTH]; - - // Parameters for new method: some not needed, will reduce/cleanup later. - int32_t blockInd; // Frame index counter. - int modelUpdatePars[4]; // Parameters for updating or estimating. - // Thresholds/weights for prior model. - float priorModelPars[7]; // Parameters for prior model. - float noise[HALF_ANAL_BLOCKL]; // Noise spectrum from current frame. - float noisePrev[HALF_ANAL_BLOCKL]; // Noise spectrum from previous frame. - // Magnitude spectrum of previous analyze frame. - float magnPrevAnalyze[HALF_ANAL_BLOCKL]; - // Magnitude spectrum of previous process frame. - float magnPrevProcess[HALF_ANAL_BLOCKL]; - float logLrtTimeAvg[HALF_ANAL_BLOCKL]; // Log LRT factor with time-smoothing. - float priorSpeechProb; // Prior speech/noise probability. - float featureData[7]; - // Conservative noise spectrum estimate. - float magnAvgPause[HALF_ANAL_BLOCKL]; - float signalEnergy; // Energy of |magn|. - float sumMagn; - float whiteNoiseLevel; // Initial noise estimate. - float initMagnEst[HALF_ANAL_BLOCKL]; // Initial magnitude spectrum estimate. - float pinkNoiseNumerator; // Pink noise parameter: numerator. - float pinkNoiseExp; // Pink noise parameter: power of frequencies. - float parametricNoise[HALF_ANAL_BLOCKL]; - // Parameters for feature extraction. - NSParaExtract featureExtractionParams; - // Histograms for parameter estimation. - int histLrt[HIST_PAR_EST]; - int histSpecFlat[HIST_PAR_EST]; - int histSpecDiff[HIST_PAR_EST]; - // Quantities for high band estimate. - float speechProb[HALF_ANAL_BLOCKL]; // Final speech/noise prob: prior + LRT. - // Buffering data for HB. - float dataBufHB[NUM_HIGH_BANDS_MAX][ANAL_BLOCKL_MAX]; -} NoiseSuppressionC; - -#ifdef __cplusplus -extern "C" { -#endif - -/**************************************************************************** - * WebRtcNs_InitCore(...) - * - * This function initializes a noise suppression instance - * - * Input: - * - self : Instance that should be initialized - * - fs : Sampling frequency - * - * Output: - * - self : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNs_InitCore(NoiseSuppressionC* self, uint32_t fs); - -/**************************************************************************** - * WebRtcNs_set_policy_core(...) - * - * This changes the aggressiveness of the noise suppression method. - * - * Input: - * - self : Instance that should be initialized - * - mode : 0: Mild (6dB), 1: Medium (10dB), 2: Aggressive (15dB) - * - * Output: - * - self : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNs_set_policy_core(NoiseSuppressionC* self, int mode); - -/**************************************************************************** - * WebRtcNs_AnalyzeCore - * - * Estimate the background noise. - * - * Input: - * - self : Instance that should be initialized - * - speechFrame : Input speech frame for lower band - * - * Output: - * - self : Updated instance - */ -void WebRtcNs_AnalyzeCore(NoiseSuppressionC* self, const float* speechFrame); - -/**************************************************************************** - * WebRtcNs_ProcessCore - * - * Do noise suppression. - * - * Input: - * - self : Instance that should be initialized - * - inFrame : Input speech frame for each band - * - num_bands : Number of bands - * - * Output: - * - self : Updated instance - * - outFrame : Output speech frame for each band - */ -void WebRtcNs_ProcessCore(NoiseSuppressionC* self, - const float* const* inFrame, - size_t num_bands, - float* const* outFrame); - -#ifdef __cplusplus -} -#endif -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NS_CORE_H_
diff --git a/modules/audio_processing/legacy_ns/nsx_core.c b/modules/audio_processing/legacy_ns/nsx_core.c deleted file mode 100644 index aa1e73b..0000000 --- a/modules/audio_processing/legacy_ns/nsx_core.c +++ /dev/null
@@ -1,2154 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_processing/legacy_ns/noise_suppression_x.h" - -#include <math.h> -#include <stdlib.h> -#include <string.h> - -#include "common_audio/signal_processing/include/real_fft.h" -#include "modules/audio_processing/legacy_ns/nsx_core.h" -#include "rtc_base/checks.h" -#include "system_wrappers/include/cpu_features_wrapper.h" - -#if defined(WEBRTC_HAS_NEON) -/* Tables are defined in ARM assembly files. */ -extern const int16_t WebRtcNsx_kLogTable[9]; -extern const int16_t WebRtcNsx_kCounterDiv[201]; -extern const int16_t WebRtcNsx_kLogTableFrac[256]; -#else -static const int16_t WebRtcNsx_kLogTable[9] = {0, 177, 355, 532, 710, - 887, 1065, 1242, 1420}; - -static const int16_t WebRtcNsx_kCounterDiv[201] = { - 32767, 16384, 10923, 8192, 6554, 5461, 4681, 4096, 3641, 3277, 2979, 2731, - 2521, 2341, 2185, 2048, 1928, 1820, 1725, 1638, 1560, 1489, 1425, 1365, - 1311, 1260, 1214, 1170, 1130, 1092, 1057, 1024, 993, 964, 936, 910, - 886, 862, 840, 819, 799, 780, 762, 745, 728, 712, 697, 683, - 669, 655, 643, 630, 618, 607, 596, 585, 575, 565, 555, 546, - 537, 529, 520, 512, 504, 496, 489, 482, 475, 468, 462, 455, - 449, 443, 437, 431, 426, 420, 415, 410, 405, 400, 395, 390, - 386, 381, 377, 372, 368, 364, 360, 356, 352, 349, 345, 341, - 338, 334, 331, 328, 324, 321, 318, 315, 312, 309, 306, 303, - 301, 298, 295, 293, 290, 287, 285, 282, 280, 278, 275, 273, - 271, 269, 266, 264, 262, 260, 258, 256, 254, 252, 250, 248, - 246, 245, 243, 241, 239, 237, 236, 234, 232, 231, 229, 228, - 226, 224, 223, 221, 220, 218, 217, 216, 214, 213, 211, 210, - 209, 207, 206, 205, 204, 202, 201, 200, 199, 197, 196, 195, - 194, 193, 192, 191, 189, 188, 187, 186, 185, 184, 183, 182, - 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 172, 171, - 170, 169, 168, 167, 166, 165, 165, 164, 163}; - -static const int16_t WebRtcNsx_kLogTableFrac[256] = { - 0, 1, 3, 4, 6, 7, 9, 10, 11, 13, 14, 16, 17, 18, 20, - 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, - 41, 42, 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 57, 59, - 60, 61, 62, 63, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 77, - 78, 79, 80, 81, 82, 84, 85, 86, 87, 88, 89, 90, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 178, 179, 180, 181, 182, 183, - 184, 185, 185, 186, 187, 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, - 197, 198, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, 207, 208, 208, - 209, 210, 211, 212, 212, 213, 214, 215, 216, 216, 217, 218, 219, 220, 220, - 221, 222, 223, 224, 224, 225, 226, 227, 228, 228, 229, 230, 231, 231, 232, - 233, 234, 234, 235, 236, 237, 238, 238, 239, 240, 241, 241, 242, 243, 244, - 244, 245, 246, 247, 247, 248, 249, 249, 250, 251, 252, 252, 253, 254, 255, - 255}; -#endif // WEBRTC_HAS_NEON - -// Skip first frequency bins during estimation. (0 <= value < 64) -static const size_t kStartBand = 5; - -// hybrib Hanning & flat window -static const int16_t kBlocks80w128x[128] = { - 0, 536, 1072, 1606, 2139, 2669, 3196, 3720, 4240, 4756, 5266, - 5771, 6270, 6762, 7246, 7723, 8192, 8652, 9102, 9543, 9974, 10394, - 10803, 11200, 11585, 11958, 12318, 12665, 12998, 13318, 13623, 13913, 14189, - 14449, 14694, 14924, 15137, 15334, 15515, 15679, 15826, 15956, 16069, 16165, - 16244, 16305, 16349, 16375, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16375, 16349, 16305, 16244, 16165, 16069, 15956, - 15826, 15679, 15515, 15334, 15137, 14924, 14694, 14449, 14189, 13913, 13623, - 13318, 12998, 12665, 12318, 11958, 11585, 11200, 10803, 10394, 9974, 9543, - 9102, 8652, 8192, 7723, 7246, 6762, 6270, 5771, 5266, 4756, 4240, - 3720, 3196, 2669, 2139, 1606, 1072, 536}; - -// hybrib Hanning & flat window -static const int16_t kBlocks160w256x[256] = { - 0, 268, 536, 804, 1072, 1339, 1606, 1872, 2139, 2404, 2669, - 2933, 3196, 3459, 3720, 3981, 4240, 4499, 4756, 5012, 5266, 5520, - 5771, 6021, 6270, 6517, 6762, 7005, 7246, 7486, 7723, 7959, 8192, - 8423, 8652, 8878, 9102, 9324, 9543, 9760, 9974, 10185, 10394, 10600, - 10803, 11003, 11200, 11394, 11585, 11773, 11958, 12140, 12318, 12493, 12665, - 12833, 12998, 13160, 13318, 13472, 13623, 13770, 13913, 14053, 14189, 14321, - 14449, 14574, 14694, 14811, 14924, 15032, 15137, 15237, 15334, 15426, 15515, - 15599, 15679, 15754, 15826, 15893, 15956, 16015, 16069, 16119, 16165, 16207, - 16244, 16277, 16305, 16329, 16349, 16364, 16375, 16382, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, - 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16382, 16375, 16364, 16349, - 16329, 16305, 16277, 16244, 16207, 16165, 16119, 16069, 16015, 15956, 15893, - 15826, 15754, 15679, 15599, 15515, 15426, 15334, 15237, 15137, 15032, 14924, - 14811, 14694, 14574, 14449, 14321, 14189, 14053, 13913, 13770, 13623, 13472, - 13318, 13160, 12998, 12833, 12665, 12493, 12318, 12140, 11958, 11773, 11585, - 11394, 11200, 11003, 10803, 10600, 10394, 10185, 9974, 9760, 9543, 9324, - 9102, 8878, 8652, 8423, 8192, 7959, 7723, 7486, 7246, 7005, 6762, - 6517, 6270, 6021, 5771, 5520, 5266, 5012, 4756, 4499, 4240, 3981, - 3720, 3459, 3196, 2933, 2669, 2404, 2139, 1872, 1606, 1339, 1072, - 804, 536, 268}; - -// Gain factor1 table: Input value in Q8 and output value in Q13 -// original floating point code -// if (gain > blim) { -// factor1 = 1.0 + 1.3 * (gain - blim); -// if (gain * factor1 > 1.0) { -// factor1 = 1.0 / gain; -// } -// } else { -// factor1 = 1.0; -// } -static const int16_t kFactor1Table[257] = { - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8233, - 8274, 8315, 8355, 8396, 8436, 8475, 8515, 8554, 8592, 8631, 8669, - 8707, 8745, 8783, 8820, 8857, 8894, 8931, 8967, 9003, 9039, 9075, - 9111, 9146, 9181, 9216, 9251, 9286, 9320, 9354, 9388, 9422, 9456, - 9489, 9523, 9556, 9589, 9622, 9655, 9687, 9719, 9752, 9784, 9816, - 9848, 9879, 9911, 9942, 9973, 10004, 10035, 10066, 10097, 10128, 10158, - 10188, 10218, 10249, 10279, 10308, 10338, 10368, 10397, 10426, 10456, 10485, - 10514, 10543, 10572, 10600, 10629, 10657, 10686, 10714, 10742, 10770, 10798, - 10826, 10854, 10882, 10847, 10810, 10774, 10737, 10701, 10666, 10631, 10596, - 10562, 10527, 10494, 10460, 10427, 10394, 10362, 10329, 10297, 10266, 10235, - 10203, 10173, 10142, 10112, 10082, 10052, 10023, 9994, 9965, 9936, 9908, - 9879, 9851, 9824, 9796, 9769, 9742, 9715, 9689, 9662, 9636, 9610, - 9584, 9559, 9534, 9508, 9484, 9459, 9434, 9410, 9386, 9362, 9338, - 9314, 9291, 9268, 9245, 9222, 9199, 9176, 9154, 9132, 9110, 9088, - 9066, 9044, 9023, 9002, 8980, 8959, 8939, 8918, 8897, 8877, 8857, - 8836, 8816, 8796, 8777, 8757, 8738, 8718, 8699, 8680, 8661, 8642, - 8623, 8605, 8586, 8568, 8550, 8532, 8514, 8496, 8478, 8460, 8443, - 8425, 8408, 8391, 8373, 8356, 8339, 8323, 8306, 8289, 8273, 8256, - 8240, 8224, 8208, 8192}; - -// For Factor2 tables -// original floating point code -// if (gain > blim) { -// factor2 = 1.0; -// } else { -// factor2 = 1.0 - 0.3 * (blim - gain); -// if (gain <= inst->denoiseBound) { -// factor2 = 1.0 - 0.3 * (blim - inst->denoiseBound); -// } -// } -// -// Gain factor table: Input value in Q8 and output value in Q13 -static const int16_t kFactor2Aggressiveness1[257] = { - 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, - 7577, 7577, 7577, 7577, 7577, 7596, 7614, 7632, 7650, 7667, 7683, 7699, - 7715, 7731, 7746, 7761, 7775, 7790, 7804, 7818, 7832, 7845, 7858, 7871, - 7884, 7897, 7910, 7922, 7934, 7946, 7958, 7970, 7982, 7993, 8004, 8016, - 8027, 8038, 8049, 8060, 8070, 8081, 8091, 8102, 8112, 8122, 8132, 8143, - 8152, 8162, 8172, 8182, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192}; - -// Gain factor table: Input value in Q8 and output value in Q13 -static const int16_t kFactor2Aggressiveness2[257] = { - 7270, 7270, 7270, 7270, 7270, 7306, 7339, 7369, 7397, 7424, 7448, 7472, - 7495, 7517, 7537, 7558, 7577, 7596, 7614, 7632, 7650, 7667, 7683, 7699, - 7715, 7731, 7746, 7761, 7775, 7790, 7804, 7818, 7832, 7845, 7858, 7871, - 7884, 7897, 7910, 7922, 7934, 7946, 7958, 7970, 7982, 7993, 8004, 8016, - 8027, 8038, 8049, 8060, 8070, 8081, 8091, 8102, 8112, 8122, 8132, 8143, - 8152, 8162, 8172, 8182, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192}; - -// Gain factor table: Input value in Q8 and output value in Q13 -static const int16_t kFactor2Aggressiveness3[257] = { - 7184, 7184, 7184, 7229, 7270, 7306, 7339, 7369, 7397, 7424, 7448, 7472, - 7495, 7517, 7537, 7558, 7577, 7596, 7614, 7632, 7650, 7667, 7683, 7699, - 7715, 7731, 7746, 7761, 7775, 7790, 7804, 7818, 7832, 7845, 7858, 7871, - 7884, 7897, 7910, 7922, 7934, 7946, 7958, 7970, 7982, 7993, 8004, 8016, - 8027, 8038, 8049, 8060, 8070, 8081, 8091, 8102, 8112, 8122, 8132, 8143, - 8152, 8162, 8172, 8182, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, - 8192, 8192, 8192, 8192, 8192}; - -// sum of log2(i) from table index to inst->anaLen2 in Q5 -// Note that the first table value is invalid, since log2(0) = -infinity -static const int16_t kSumLogIndex[66] = { - 0, 22917, 22917, 22885, 22834, 22770, 22696, 22613, 22524, 22428, - 22326, 22220, 22109, 21994, 21876, 21754, 21629, 21501, 21370, 21237, - 21101, 20963, 20822, 20679, 20535, 20388, 20239, 20089, 19937, 19783, - 19628, 19470, 19312, 19152, 18991, 18828, 18664, 18498, 18331, 18164, - 17994, 17824, 17653, 17480, 17306, 17132, 16956, 16779, 16602, 16423, - 16243, 16063, 15881, 15699, 15515, 15331, 15146, 14960, 14774, 14586, - 14398, 14209, 14019, 13829, 13637, 13445}; - -// sum of log2(i)^2 from table index to inst->anaLen2 in Q2 -// Note that the first table value is invalid, since log2(0) = -infinity -static const int16_t kSumSquareLogIndex[66] = { - 0, 16959, 16959, 16955, 16945, 16929, 16908, 16881, 16850, 16814, - 16773, 16729, 16681, 16630, 16575, 16517, 16456, 16392, 16325, 16256, - 16184, 16109, 16032, 15952, 15870, 15786, 15700, 15612, 15521, 15429, - 15334, 15238, 15140, 15040, 14938, 14834, 14729, 14622, 14514, 14404, - 14292, 14179, 14064, 13947, 13830, 13710, 13590, 13468, 13344, 13220, - 13094, 12966, 12837, 12707, 12576, 12444, 12310, 12175, 12039, 11902, - 11763, 11624, 11483, 11341, 11198, 11054}; - -// log2(table index) in Q12 -// Note that the first table value is invalid, since log2(0) = -infinity -static const int16_t kLogIndex[129] = { - 0, 0, 4096, 6492, 8192, 9511, 10588, 11499, 12288, 12984, 13607, - 14170, 14684, 15157, 15595, 16003, 16384, 16742, 17080, 17400, 17703, 17991, - 18266, 18529, 18780, 19021, 19253, 19476, 19691, 19898, 20099, 20292, 20480, - 20662, 20838, 21010, 21176, 21338, 21496, 21649, 21799, 21945, 22087, 22226, - 22362, 22495, 22625, 22752, 22876, 22998, 23117, 23234, 23349, 23462, 23572, - 23680, 23787, 23892, 23994, 24095, 24195, 24292, 24388, 24483, 24576, 24668, - 24758, 24847, 24934, 25021, 25106, 25189, 25272, 25354, 25434, 25513, 25592, - 25669, 25745, 25820, 25895, 25968, 26041, 26112, 26183, 26253, 26322, 26390, - 26458, 26525, 26591, 26656, 26721, 26784, 26848, 26910, 26972, 27033, 27094, - 27154, 27213, 27272, 27330, 27388, 27445, 27502, 27558, 27613, 27668, 27722, - 27776, 27830, 27883, 27935, 27988, 28039, 28090, 28141, 28191, 28241, 28291, - 28340, 28388, 28437, 28484, 28532, 28579, 28626, 28672}; - -// determinant of estimation matrix in Q0 corresponding to the log2 tables above -// Note that the first table value is invalid, since log2(0) = -infinity -static const int16_t kDeterminantEstMatrix[66] = { - 0, 29814, 25574, 22640, 20351, 18469, 16873, 15491, 14277, 13199, 12233, - 11362, 10571, 9851, 9192, 8587, 8030, 7515, 7038, 6596, 6186, 5804, - 5448, 5115, 4805, 4514, 4242, 3988, 3749, 3524, 3314, 3116, 2930, - 2755, 2590, 2435, 2289, 2152, 2022, 1900, 1785, 1677, 1575, 1478, - 1388, 1302, 1221, 1145, 1073, 1005, 942, 881, 825, 771, 721, - 674, 629, 587, 547, 510, 475, 442, 411, 382, 355, 330}; - -// Update the noise estimation information. -static void UpdateNoiseEstimate(NoiseSuppressionFixedC* inst, int offset) { - int32_t tmp32no1 = 0; - int32_t tmp32no2 = 0; - int16_t tmp16 = 0; - const int16_t kExp2Const = 11819; // Q13 - - size_t i = 0; - - tmp16 = - WebRtcSpl_MaxValueW16(inst->noiseEstLogQuantile + offset, inst->magnLen); - // Guarantee a Q-domain as high as possible and still fit in int16 - inst->qNoise = - 14 - (int)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2Const, tmp16, 21); - for (i = 0; i < inst->magnLen; i++) { - // inst->quantile[i]=exp(inst->lquantile[offset+i]); - // in Q21 - tmp32no2 = kExp2Const * inst->noiseEstLogQuantile[offset + i]; - tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac - tmp16 = (int16_t)(tmp32no2 >> 21); - tmp16 -= 21; // shift 21 to get result in Q0 - tmp16 += (int16_t)inst->qNoise; // shift to get result in Q(qNoise) - if (tmp16 < 0) { - tmp32no1 >>= -tmp16; - } else { - tmp32no1 <<= tmp16; - } - inst->noiseEstQuantile[i] = WebRtcSpl_SatW32ToW16(tmp32no1); - } -} - -// Noise Estimation -static void NoiseEstimationC(NoiseSuppressionFixedC* inst, - uint16_t* magn, - uint32_t* noise, - int16_t* q_noise) { - int16_t lmagn[HALF_ANAL_BLOCKL], counter, countDiv; - int16_t countProd, delta, zeros, frac; - int16_t log2, tabind, logval, tmp16, tmp16no1, tmp16no2; - const int16_t log2_const = 22713; // Q15 - const int16_t width_factor = 21845; - - size_t i, s, offset; - - tabind = inst->stages - inst->normData; - RTC_DCHECK_LT(tabind, 9); - RTC_DCHECK_GT(tabind, -9); - if (tabind < 0) { - logval = -WebRtcNsx_kLogTable[-tabind]; - } else { - logval = WebRtcNsx_kLogTable[tabind]; - } - - // lmagn(i)=log(magn(i))=log(2)*log2(magn(i)) - // magn is in Q(-stages), and the real lmagn values are: - // real_lmagn(i)=log(magn(i)*2^stages)=log(magn(i))+log(2^stages) - // lmagn in Q8 - for (i = 0; i < inst->magnLen; i++) { - if (magn[i]) { - zeros = WebRtcSpl_NormU32((uint32_t)magn[i]); - frac = (int16_t)((((uint32_t)magn[i] << zeros) & 0x7FFFFFFF) >> 23); - // log2(magn(i)) - RTC_DCHECK_LT(frac, 256); - log2 = (int16_t)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); - // log2(magn(i))*log(2) - lmagn[i] = (int16_t)((log2 * log2_const) >> 15); - // + log(2^stages) - lmagn[i] += logval; - } else { - lmagn[i] = logval; // 0; - } - } - - // loop over simultaneous estimates - for (s = 0; s < SIMULT; s++) { - offset = s * inst->magnLen; - - // Get counter values from state - counter = inst->noiseEstCounter[s]; - RTC_DCHECK_LT(counter, 201); - countDiv = WebRtcNsx_kCounterDiv[counter]; - countProd = (int16_t)(counter * countDiv); - - // quant_est(...) - for (i = 0; i < inst->magnLen; i++) { - // compute delta - if (inst->noiseEstDensity[offset + i] > 512) { - // Get the value for delta by shifting intead of dividing. - int factor = WebRtcSpl_NormW16(inst->noiseEstDensity[offset + i]); - delta = (int16_t)(FACTOR_Q16 >> (14 - factor)); - } else { - delta = FACTOR_Q7; - if (inst->blockIndex < END_STARTUP_LONG) { - // Smaller step size during startup. This prevents from using - // unrealistic values causing overflow. - delta = FACTOR_Q7_STARTUP; - } - } - - // update log quantile estimate - tmp16 = (int16_t)((delta * countDiv) >> 14); - if (lmagn[i] > inst->noiseEstLogQuantile[offset + i]) { - // +=QUANTILE*delta/(inst->counter[s]+1) QUANTILE=0.25, =1 in Q2 - // CounterDiv=1/(inst->counter[s]+1) in Q15 - tmp16 += 2; - inst->noiseEstLogQuantile[offset + i] += tmp16 / 4; - } else { - tmp16 += 1; - // *(1-QUANTILE), in Q2 QUANTILE=0.25, 1-0.25=0.75=3 in Q2 - // TODO(bjornv): investigate why we need to truncate twice. - tmp16no2 = (int16_t)((tmp16 / 2) * 3 / 2); - inst->noiseEstLogQuantile[offset + i] -= tmp16no2; - if (inst->noiseEstLogQuantile[offset + i] < logval) { - // This is the smallest fixed point representation we can - // have, hence we limit the output. - inst->noiseEstLogQuantile[offset + i] = logval; - } - } - - // update density estimate - if (WEBRTC_SPL_ABS_W16(lmagn[i] - inst->noiseEstLogQuantile[offset + i]) < - WIDTH_Q8) { - tmp16no1 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( - inst->noiseEstDensity[offset + i], countProd, 15); - tmp16no2 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(width_factor, - countDiv, 15); - inst->noiseEstDensity[offset + i] = tmp16no1 + tmp16no2; - } - } // end loop over magnitude spectrum - - if (counter >= END_STARTUP_LONG) { - inst->noiseEstCounter[s] = 0; - if (inst->blockIndex >= END_STARTUP_LONG) { - UpdateNoiseEstimate(inst, offset); - } - } - inst->noiseEstCounter[s]++; - - } // end loop over simultaneous estimates - - // Sequentially update the noise during startup - if (inst->blockIndex < END_STARTUP_LONG) { - UpdateNoiseEstimate(inst, offset); - } - - for (i = 0; i < inst->magnLen; i++) { - noise[i] = (uint32_t)(inst->noiseEstQuantile[i]); // Q(qNoise) - } - (*q_noise) = (int16_t)inst->qNoise; -} - -// Filter the data in the frequency domain, and create spectrum. -static void PrepareSpectrumC(NoiseSuppressionFixedC* inst, int16_t* freq_buf) { - size_t i = 0, j = 0; - - for (i = 0; i < inst->magnLen; i++) { - inst->real[i] = - (int16_t)((inst->real[i] * (int16_t)(inst->noiseSupFilter[i])) >> - 14); // Q(normData-stages) - inst->imag[i] = - (int16_t)((inst->imag[i] * (int16_t)(inst->noiseSupFilter[i])) >> - 14); // Q(normData-stages) - } - - freq_buf[0] = inst->real[0]; - freq_buf[1] = -inst->imag[0]; - for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { - freq_buf[j] = inst->real[i]; - freq_buf[j + 1] = -inst->imag[i]; - } - freq_buf[inst->anaLen] = inst->real[inst->anaLen2]; - freq_buf[inst->anaLen + 1] = -inst->imag[inst->anaLen2]; -} - -// Denormalize the real-valued signal |in|, the output from inverse FFT. -static void DenormalizeC(NoiseSuppressionFixedC* inst, - int16_t* in, - int factor) { - size_t i = 0; - int32_t tmp32 = 0; - for (i = 0; i < inst->anaLen; i += 1) { - tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t)in[i], factor - inst->normData); - inst->real[i] = WebRtcSpl_SatW32ToW16(tmp32); // Q0 - } -} - -// For the noise supression process, synthesis, read out fully processed -// segment, and update synthesis buffer. -static void SynthesisUpdateC(NoiseSuppressionFixedC* inst, - int16_t* out_frame, - int16_t gain_factor) { - size_t i = 0; - int16_t tmp16a = 0; - int16_t tmp16b = 0; - int32_t tmp32 = 0; - - // synthesis - for (i = 0; i < inst->anaLen; i++) { - tmp16a = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( - inst->window[i], inst->real[i], 14); // Q0, window in Q14 - tmp32 = - WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(tmp16a, gain_factor, 13); // Q0 - // Down shift with rounding - tmp16b = WebRtcSpl_SatW32ToW16(tmp32); // Q0 - inst->synthesisBuffer[i] = WebRtcSpl_AddSatW16(inst->synthesisBuffer[i], - tmp16b); // Q0 - } - - // read out fully processed segment - for (i = 0; i < inst->blockLen10ms; i++) { - out_frame[i] = inst->synthesisBuffer[i]; // Q0 - } - - // update synthesis buffer - memcpy(inst->synthesisBuffer, inst->synthesisBuffer + inst->blockLen10ms, - (inst->anaLen - inst->blockLen10ms) * sizeof(*inst->synthesisBuffer)); - WebRtcSpl_ZerosArrayW16( - inst->synthesisBuffer + inst->anaLen - inst->blockLen10ms, - inst->blockLen10ms); -} - -// Update analysis buffer for lower band, and window data before FFT. -static void AnalysisUpdateC(NoiseSuppressionFixedC* inst, - int16_t* out, - int16_t* new_speech) { - size_t i = 0; - - // For lower band update analysis buffer. - memcpy(inst->analysisBuffer, inst->analysisBuffer + inst->blockLen10ms, - (inst->anaLen - inst->blockLen10ms) * sizeof(*inst->analysisBuffer)); - memcpy(inst->analysisBuffer + inst->anaLen - inst->blockLen10ms, new_speech, - inst->blockLen10ms * sizeof(*inst->analysisBuffer)); - - // Window data before FFT. - for (i = 0; i < inst->anaLen; i++) { - out[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( - inst->window[i], inst->analysisBuffer[i], 14); // Q0 - } -} - -// Normalize the real-valued signal |in|, the input to forward FFT. -static void NormalizeRealBufferC(NoiseSuppressionFixedC* inst, - const int16_t* in, - int16_t* out) { - size_t i = 0; - RTC_DCHECK_GE(inst->normData, 0); - for (i = 0; i < inst->anaLen; ++i) { - out[i] = in[i] << inst->normData; // Q(normData) - } -} - -// Declare function pointers. -NoiseEstimation WebRtcNsx_NoiseEstimation; -PrepareSpectrum WebRtcNsx_PrepareSpectrum; -SynthesisUpdate WebRtcNsx_SynthesisUpdate; -AnalysisUpdate WebRtcNsx_AnalysisUpdate; -Denormalize WebRtcNsx_Denormalize; -NormalizeRealBuffer WebRtcNsx_NormalizeRealBuffer; - -#if defined(WEBRTC_HAS_NEON) -// Initialize function pointers for ARM Neon platform. -static void WebRtcNsx_InitNeon(void) { - WebRtcNsx_NoiseEstimation = WebRtcNsx_NoiseEstimationNeon; - WebRtcNsx_PrepareSpectrum = WebRtcNsx_PrepareSpectrumNeon; - WebRtcNsx_SynthesisUpdate = WebRtcNsx_SynthesisUpdateNeon; - WebRtcNsx_AnalysisUpdate = WebRtcNsx_AnalysisUpdateNeon; -} -#endif - -#if defined(MIPS32_LE) -// Initialize function pointers for MIPS platform. -static void WebRtcNsx_InitMips(void) { - WebRtcNsx_PrepareSpectrum = WebRtcNsx_PrepareSpectrum_mips; - WebRtcNsx_SynthesisUpdate = WebRtcNsx_SynthesisUpdate_mips; - WebRtcNsx_AnalysisUpdate = WebRtcNsx_AnalysisUpdate_mips; - WebRtcNsx_NormalizeRealBuffer = WebRtcNsx_NormalizeRealBuffer_mips; -#if defined(MIPS_DSP_R1_LE) - WebRtcNsx_Denormalize = WebRtcNsx_Denormalize_mips; -#endif -} -#endif - -void WebRtcNsx_CalcParametricNoiseEstimate(NoiseSuppressionFixedC* inst, - int16_t pink_noise_exp_avg, - int32_t pink_noise_num_avg, - int freq_index, - uint32_t* noise_estimate, - uint32_t* noise_estimate_avg) { - int32_t tmp32no1 = 0; - int32_t tmp32no2 = 0; - - int16_t int_part = 0; - int16_t frac_part = 0; - - // Use pink noise estimate - // noise_estimate = 2^(pinkNoiseNumerator + pinkNoiseExp * log2(j)) - RTC_DCHECK_GE(freq_index, 0); - RTC_DCHECK_LT(freq_index, 129); - tmp32no2 = (pink_noise_exp_avg * kLogIndex[freq_index]) >> 15; // Q11 - tmp32no1 = pink_noise_num_avg - tmp32no2; // Q11 - - // Calculate output: 2^tmp32no1 - // Output in Q(minNorm-stages) - tmp32no1 += (inst->minNorm - inst->stages) << 11; - if (tmp32no1 > 0) { - int_part = (int16_t)(tmp32no1 >> 11); - frac_part = (int16_t)(tmp32no1 & 0x000007ff); // Q11 - // Piecewise linear approximation of 'b' in - // 2^(int_part+frac_part) = 2^int_part * (1 + b) - // 'b' is given in Q11 and below stored in frac_part. - if (frac_part >> 10) { - // Upper fractional part - tmp32no2 = (2048 - frac_part) * 1244; // Q21 - tmp32no2 = 2048 - (tmp32no2 >> 10); - } else { - // Lower fractional part - tmp32no2 = (frac_part * 804) >> 10; - } - // Shift fractional part to Q(minNorm-stages) - tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, int_part - 11); - *noise_estimate_avg = (1 << int_part) + (uint32_t)tmp32no2; - // Scale up to initMagnEst, which is not block averaged - *noise_estimate = (*noise_estimate_avg) * (uint32_t)(inst->blockIndex + 1); - } -} - -// Initialize state -int32_t WebRtcNsx_InitCore(NoiseSuppressionFixedC* inst, uint32_t fs) { - int i; - - // check for valid pointer - if (inst == NULL) { - return -1; - } - // - - // Initialization of struct - if (fs == 8000 || fs == 16000 || fs == 32000 || fs == 48000) { - inst->fs = fs; - } else { - return -1; - } - - if (fs == 8000) { - inst->blockLen10ms = 80; - inst->anaLen = 128; - inst->stages = 7; - inst->window = kBlocks80w128x; - inst->thresholdLogLrt = 131072; // default threshold for LRT feature - inst->maxLrt = 0x0040000; - inst->minLrt = 52429; - } else { - inst->blockLen10ms = 160; - inst->anaLen = 256; - inst->stages = 8; - inst->window = kBlocks160w256x; - inst->thresholdLogLrt = 212644; // default threshold for LRT feature - inst->maxLrt = 0x0080000; - inst->minLrt = 104858; - } - inst->anaLen2 = inst->anaLen / 2; - inst->magnLen = inst->anaLen2 + 1; - - if (inst->real_fft != NULL) { - WebRtcSpl_FreeRealFFT(inst->real_fft); - } - inst->real_fft = WebRtcSpl_CreateRealFFT(inst->stages); - if (inst->real_fft == NULL) { - return -1; - } - - WebRtcSpl_ZerosArrayW16(inst->analysisBuffer, ANAL_BLOCKL_MAX); - WebRtcSpl_ZerosArrayW16(inst->synthesisBuffer, ANAL_BLOCKL_MAX); - - // for HB processing - WebRtcSpl_ZerosArrayW16(inst->dataBufHBFX[0], - NUM_HIGH_BANDS_MAX * ANAL_BLOCKL_MAX); - // for quantile noise estimation - WebRtcSpl_ZerosArrayW16(inst->noiseEstQuantile, HALF_ANAL_BLOCKL); - for (i = 0; i < SIMULT * HALF_ANAL_BLOCKL; i++) { - inst->noiseEstLogQuantile[i] = 2048; // Q8 - inst->noiseEstDensity[i] = 153; // Q9 - } - for (i = 0; i < SIMULT; i++) { - inst->noiseEstCounter[i] = (int16_t)(END_STARTUP_LONG * (i + 1)) / SIMULT; - } - - // Initialize suppression filter with ones - WebRtcSpl_MemSetW16((int16_t*)inst->noiseSupFilter, 16384, HALF_ANAL_BLOCKL); - - // Set the aggressiveness: default - inst->aggrMode = 0; - - // initialize variables for new method - inst->priorNonSpeechProb = - 8192; // Q14(0.5) prior probability for speech/noise - for (i = 0; i < HALF_ANAL_BLOCKL; i++) { - inst->prevMagnU16[i] = 0; - inst->prevNoiseU32[i] = 0; // previous noise-spectrum - inst->logLrtTimeAvgW32[i] = 0; // smooth LR ratio - inst->avgMagnPause[i] = 0; // conservative noise spectrum estimate - inst->initMagnEst[i] = 0; // initial average magnitude spectrum - } - - // feature quantities - inst->thresholdSpecDiff = - 50; // threshold for difference feature: determined on-line - inst->thresholdSpecFlat = 20480; // threshold for flatness: determined - // on-line - inst->featureLogLrt = - inst->thresholdLogLrt; // average LRT factor (= threshold) - inst->featureSpecFlat = - inst->thresholdSpecFlat; // spectral flatness (= threshold) - inst->featureSpecDiff = - inst->thresholdSpecDiff; // spectral difference (= threshold) - inst->weightLogLrt = 6; // default weighting par for LRT feature - inst->weightSpecFlat = - 0; // default weighting par for spectral flatness feature - inst->weightSpecDiff = - 0; // default weighting par for spectral difference feature - - inst->curAvgMagnEnergy = 0; // window time-average of input magnitude - // spectrum - inst->timeAvgMagnEnergy = 0; // normalization for spectral difference - inst->timeAvgMagnEnergyTmp = 0; // normalization for spectral difference - - // histogram quantities: used to estimate/update thresholds for features - WebRtcSpl_ZerosArrayW16(inst->histLrt, HIST_PAR_EST); - WebRtcSpl_ZerosArrayW16(inst->histSpecDiff, HIST_PAR_EST); - WebRtcSpl_ZerosArrayW16(inst->histSpecFlat, HIST_PAR_EST); - - inst->blockIndex = -1; // frame counter - - // inst->modelUpdate = 500; //window for update - inst->modelUpdate = (1 << STAT_UPDATES); // window for update - inst->cntThresUpdate = 0; // counter feature thresholds updates - - inst->sumMagn = 0; - inst->magnEnergy = 0; - inst->prevQMagn = 0; - inst->qNoise = 0; - inst->prevQNoise = 0; - - inst->energyIn = 0; - inst->scaleEnergyIn = 0; - - inst->whiteNoiseLevel = 0; - inst->pinkNoiseNumerator = 0; - inst->pinkNoiseExp = 0; - inst->minNorm = 15; // Start with full scale - inst->zeroInputSignal = 0; - - // default mode - WebRtcNsx_set_policy_core(inst, 0); - -#ifdef NS_FILEDEBUG - inst->infile = fopen("indebug.pcm", "wb"); - inst->outfile = fopen("outdebug.pcm", "wb"); - inst->file1 = fopen("file1.pcm", "wb"); - inst->file2 = fopen("file2.pcm", "wb"); - inst->file3 = fopen("file3.pcm", "wb"); - inst->file4 = fopen("file4.pcm", "wb"); - inst->file5 = fopen("file5.pcm", "wb"); -#endif - - // Initialize function pointers. - WebRtcNsx_NoiseEstimation = NoiseEstimationC; - WebRtcNsx_PrepareSpectrum = PrepareSpectrumC; - WebRtcNsx_SynthesisUpdate = SynthesisUpdateC; - WebRtcNsx_AnalysisUpdate = AnalysisUpdateC; - WebRtcNsx_Denormalize = DenormalizeC; - WebRtcNsx_NormalizeRealBuffer = NormalizeRealBufferC; - -#if defined(WEBRTC_HAS_NEON) - WebRtcNsx_InitNeon(); -#endif - -#if defined(MIPS32_LE) - WebRtcNsx_InitMips(); -#endif - - inst->initFlag = 1; - - return 0; -} - -int WebRtcNsx_set_policy_core(NoiseSuppressionFixedC* inst, int mode) { - // allow for modes:0,1,2,3 - if (mode < 0 || mode > 3) { - return -1; - } - - inst->aggrMode = mode; - if (mode == 0) { - inst->overdrive = 256; // Q8(1.0) - inst->denoiseBound = 8192; // Q14(0.5) - inst->gainMap = 0; // No gain compensation - } else if (mode == 1) { - inst->overdrive = 256; // Q8(1.0) - inst->denoiseBound = 4096; // Q14(0.25) - inst->factor2Table = kFactor2Aggressiveness1; - inst->gainMap = 1; - } else if (mode == 2) { - inst->overdrive = 282; // ~= Q8(1.1) - inst->denoiseBound = 2048; // Q14(0.125) - inst->factor2Table = kFactor2Aggressiveness2; - inst->gainMap = 1; - } else if (mode == 3) { - inst->overdrive = 320; // Q8(1.25) - inst->denoiseBound = 1475; // ~= Q14(0.09) - inst->factor2Table = kFactor2Aggressiveness3; - inst->gainMap = 1; - } - return 0; -} - -// Extract thresholds for feature parameters -// histograms are computed over some window_size (given by window_pars) -// thresholds and weights are extracted every window -// flag 0 means update histogram only, flag 1 means compute the -// thresholds/weights threshold and weights are returned in: -// inst->priorModelPars -void WebRtcNsx_FeatureParameterExtraction(NoiseSuppressionFixedC* inst, - int flag) { - uint32_t tmpU32; - uint32_t histIndex; - uint32_t posPeak1SpecFlatFX, posPeak2SpecFlatFX; - uint32_t posPeak1SpecDiffFX, posPeak2SpecDiffFX; - - int32_t tmp32; - int32_t fluctLrtFX, thresFluctLrtFX; - int32_t avgHistLrtFX, avgSquareHistLrtFX, avgHistLrtComplFX; - - int16_t j; - int16_t numHistLrt; - - int i; - int useFeatureSpecFlat, useFeatureSpecDiff, featureSum; - int maxPeak1, maxPeak2; - int weightPeak1SpecFlat, weightPeak2SpecFlat; - int weightPeak1SpecDiff, weightPeak2SpecDiff; - - // update histograms - if (!flag) { - // LRT - // Type casting to UWord32 is safe since negative values will not be wrapped - // to larger values than HIST_PAR_EST - histIndex = (uint32_t)(inst->featureLogLrt); - if (histIndex < HIST_PAR_EST) { - inst->histLrt[histIndex]++; - } - // Spectral flatness - // (inst->featureSpecFlat*20)>>10 = (inst->featureSpecFlat*5)>>8 - histIndex = (inst->featureSpecFlat * 5) >> 8; - if (histIndex < HIST_PAR_EST) { - inst->histSpecFlat[histIndex]++; - } - // Spectral difference - histIndex = HIST_PAR_EST; - if (inst->timeAvgMagnEnergy > 0) { - // Guard against division by zero - // If timeAvgMagnEnergy == 0 we have no normalizing statistics and - // therefore can't update the histogram - histIndex = ((inst->featureSpecDiff * 5) >> inst->stages) / - inst->timeAvgMagnEnergy; - } - if (histIndex < HIST_PAR_EST) { - inst->histSpecDiff[histIndex]++; - } - } - - // extract parameters for speech/noise probability - if (flag) { - useFeatureSpecDiff = 1; - // for LRT feature: - // compute the average over inst->featureExtractionParams.rangeAvgHistLrt - avgHistLrtFX = 0; - avgSquareHistLrtFX = 0; - numHistLrt = 0; - for (i = 0; i < BIN_SIZE_LRT; i++) { - j = (2 * i + 1); - tmp32 = inst->histLrt[i] * j; - avgHistLrtFX += tmp32; - numHistLrt += inst->histLrt[i]; - avgSquareHistLrtFX += tmp32 * j; - } - avgHistLrtComplFX = avgHistLrtFX; - for (; i < HIST_PAR_EST; i++) { - j = (2 * i + 1); - tmp32 = inst->histLrt[i] * j; - avgHistLrtComplFX += tmp32; - avgSquareHistLrtFX += tmp32 * j; - } - fluctLrtFX = - avgSquareHistLrtFX * numHistLrt - avgHistLrtFX * avgHistLrtComplFX; - thresFluctLrtFX = THRES_FLUCT_LRT * numHistLrt; - // get threshold for LRT feature: - tmpU32 = (FACTOR_1_LRT_DIFF * (uint32_t)avgHistLrtFX); - if ((fluctLrtFX < thresFluctLrtFX) || (numHistLrt == 0) || - (tmpU32 > (uint32_t)(100 * numHistLrt))) { - // very low fluctuation, so likely noise - inst->thresholdLogLrt = inst->maxLrt; - } else { - tmp32 = (int32_t)((tmpU32 << (9 + inst->stages)) / numHistLrt / 25); - // check if value is within min/max range - inst->thresholdLogLrt = WEBRTC_SPL_SAT(inst->maxLrt, tmp32, inst->minLrt); - } - if (fluctLrtFX < thresFluctLrtFX) { - // Do not use difference feature if fluctuation of LRT feature is very - // low: most likely just noise state - useFeatureSpecDiff = 0; - } - - // for spectral flatness and spectral difference: compute the main peaks of - // histogram - maxPeak1 = 0; - maxPeak2 = 0; - posPeak1SpecFlatFX = 0; - posPeak2SpecFlatFX = 0; - weightPeak1SpecFlat = 0; - weightPeak2SpecFlat = 0; - - // peaks for flatness - for (i = 0; i < HIST_PAR_EST; i++) { - if (inst->histSpecFlat[i] > maxPeak1) { - // Found new "first" peak - maxPeak2 = maxPeak1; - weightPeak2SpecFlat = weightPeak1SpecFlat; - posPeak2SpecFlatFX = posPeak1SpecFlatFX; - - maxPeak1 = inst->histSpecFlat[i]; - weightPeak1SpecFlat = inst->histSpecFlat[i]; - posPeak1SpecFlatFX = (uint32_t)(2 * i + 1); - } else if (inst->histSpecFlat[i] > maxPeak2) { - // Found new "second" peak - maxPeak2 = inst->histSpecFlat[i]; - weightPeak2SpecFlat = inst->histSpecFlat[i]; - posPeak2SpecFlatFX = (uint32_t)(2 * i + 1); - } - } - - // for spectral flatness feature - useFeatureSpecFlat = 1; - // merge the two peaks if they are close - if ((posPeak1SpecFlatFX - posPeak2SpecFlatFX < LIM_PEAK_SPACE_FLAT_DIFF) && - (weightPeak2SpecFlat * LIM_PEAK_WEIGHT_FLAT_DIFF > - weightPeak1SpecFlat)) { - weightPeak1SpecFlat += weightPeak2SpecFlat; - posPeak1SpecFlatFX = (posPeak1SpecFlatFX + posPeak2SpecFlatFX) >> 1; - } - // reject if weight of peaks is not large enough, or peak value too small - if (weightPeak1SpecFlat < THRES_WEIGHT_FLAT_DIFF || - posPeak1SpecFlatFX < THRES_PEAK_FLAT) { - useFeatureSpecFlat = 0; - } else { // if selected, get the threshold - // compute the threshold and check if value is within min/max range - inst->thresholdSpecFlat = - WEBRTC_SPL_SAT(MAX_FLAT_Q10, FACTOR_2_FLAT_Q10 * posPeak1SpecFlatFX, - MIN_FLAT_Q10); // Q10 - } - // done with flatness feature - - if (useFeatureSpecDiff) { - // compute two peaks for spectral difference - maxPeak1 = 0; - maxPeak2 = 0; - posPeak1SpecDiffFX = 0; - posPeak2SpecDiffFX = 0; - weightPeak1SpecDiff = 0; - weightPeak2SpecDiff = 0; - // peaks for spectral difference - for (i = 0; i < HIST_PAR_EST; i++) { - if (inst->histSpecDiff[i] > maxPeak1) { - // Found new "first" peak - maxPeak2 = maxPeak1; - weightPeak2SpecDiff = weightPeak1SpecDiff; - posPeak2SpecDiffFX = posPeak1SpecDiffFX; - - maxPeak1 = inst->histSpecDiff[i]; - weightPeak1SpecDiff = inst->histSpecDiff[i]; - posPeak1SpecDiffFX = (uint32_t)(2 * i + 1); - } else if (inst->histSpecDiff[i] > maxPeak2) { - // Found new "second" peak - maxPeak2 = inst->histSpecDiff[i]; - weightPeak2SpecDiff = inst->histSpecDiff[i]; - posPeak2SpecDiffFX = (uint32_t)(2 * i + 1); - } - } - - // merge the two peaks if they are close - if ((posPeak1SpecDiffFX - posPeak2SpecDiffFX < - LIM_PEAK_SPACE_FLAT_DIFF) && - (weightPeak2SpecDiff * LIM_PEAK_WEIGHT_FLAT_DIFF > - weightPeak1SpecDiff)) { - weightPeak1SpecDiff += weightPeak2SpecDiff; - posPeak1SpecDiffFX = (posPeak1SpecDiffFX + posPeak2SpecDiffFX) >> 1; - } - // get the threshold value and check if value is within min/max range - inst->thresholdSpecDiff = - WEBRTC_SPL_SAT(MAX_DIFF, FACTOR_1_LRT_DIFF * posPeak1SpecDiffFX, - MIN_DIFF); // 5x bigger - // reject if weight of peaks is not large enough - if (weightPeak1SpecDiff < THRES_WEIGHT_FLAT_DIFF) { - useFeatureSpecDiff = 0; - } - // done with spectral difference feature - } - - // select the weights between the features - // inst->priorModelPars[4] is weight for LRT: always selected - featureSum = 6 / (1 + useFeatureSpecFlat + useFeatureSpecDiff); - inst->weightLogLrt = featureSum; - inst->weightSpecFlat = useFeatureSpecFlat * featureSum; - inst->weightSpecDiff = useFeatureSpecDiff * featureSum; - - // set histograms to zero for next update - WebRtcSpl_ZerosArrayW16(inst->histLrt, HIST_PAR_EST); - WebRtcSpl_ZerosArrayW16(inst->histSpecDiff, HIST_PAR_EST); - WebRtcSpl_ZerosArrayW16(inst->histSpecFlat, HIST_PAR_EST); - } // end of flag == 1 -} - -// Compute spectral flatness on input spectrum -// magn is the magnitude spectrum -// spectral flatness is returned in inst->featureSpecFlat -void WebRtcNsx_ComputeSpectralFlatness(NoiseSuppressionFixedC* inst, - uint16_t* magn) { - uint32_t tmpU32; - uint32_t avgSpectralFlatnessNum, avgSpectralFlatnessDen; - - int32_t tmp32; - int32_t currentSpectralFlatness, logCurSpectralFlatness; - - int16_t zeros, frac, intPart; - - size_t i; - - // for flatness - avgSpectralFlatnessNum = 0; - avgSpectralFlatnessDen = - inst->sumMagn - (uint32_t)magn[0]; // Q(normData-stages) - - // compute log of ratio of the geometric to arithmetic mean: check for log(0) - // case flatness = exp( sum(log(magn[i]))/N - log(sum(magn[i])/N) ) - // = exp( sum(log(magn[i]))/N ) * N / sum(magn[i]) - // = 2^( sum(log2(magn[i]))/N - (log2(sum(magn[i])) - log2(N)) ) - // [This is used] - for (i = 1; i < inst->magnLen; i++) { - // First bin is excluded from spectrum measures. Number of bins is now a - // power of 2 - if (magn[i]) { - zeros = WebRtcSpl_NormU32((uint32_t)magn[i]); - frac = (int16_t)( - ((uint32_t)((uint32_t)(magn[i]) << zeros) & 0x7FFFFFFF) >> 23); - // log2(magn(i)) - RTC_DCHECK_LT(frac, 256); - tmpU32 = (uint32_t)(((31 - zeros) << 8) + - WebRtcNsx_kLogTableFrac[frac]); // Q8 - avgSpectralFlatnessNum += tmpU32; // Q8 - } else { - // if at least one frequency component is zero, treat separately - tmpU32 = WEBRTC_SPL_UMUL_32_16(inst->featureSpecFlat, - SPECT_FLAT_TAVG_Q14); // Q24 - inst->featureSpecFlat -= tmpU32 >> 14; // Q10 - return; - } - } - // ratio and inverse log: check for case of log(0) - zeros = WebRtcSpl_NormU32(avgSpectralFlatnessDen); - frac = (int16_t)(((avgSpectralFlatnessDen << zeros) & 0x7FFFFFFF) >> 23); - // log2(avgSpectralFlatnessDen) - RTC_DCHECK_LT(frac, 256); - tmp32 = (int32_t)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); // Q8 - logCurSpectralFlatness = (int32_t)avgSpectralFlatnessNum; - logCurSpectralFlatness += - ((int32_t)(inst->stages - 1) << (inst->stages + 7)); // Q(8+stages-1) - logCurSpectralFlatness -= (tmp32 << (inst->stages - 1)); - logCurSpectralFlatness <<= (10 - inst->stages); // Q17 - tmp32 = (int32_t)(0x00020000 | (WEBRTC_SPL_ABS_W32(logCurSpectralFlatness) & - 0x0001FFFF)); // Q17 - intPart = 7 - (logCurSpectralFlatness >> 17); // Add 7 for output in Q10. - if (intPart > 0) { - currentSpectralFlatness = tmp32 >> intPart; - } else { - currentSpectralFlatness = tmp32 << -intPart; - } - - // time average update of spectral flatness feature - tmp32 = currentSpectralFlatness - (int32_t)inst->featureSpecFlat; // Q10 - tmp32 *= SPECT_FLAT_TAVG_Q14; // Q24 - inst->featureSpecFlat += tmp32 >> 14; // Q10 - // done with flatness feature -} - -// Compute the difference measure between input spectrum and a template/learned -// noise spectrum magn_tmp is the input spectrum the reference/template spectrum -// is inst->magn_avg_pause[i] returns (normalized) spectral difference in -// inst->featureSpecDiff -void WebRtcNsx_ComputeSpectralDifference(NoiseSuppressionFixedC* inst, - uint16_t* magnIn) { - // This is to be calculated: - // avgDiffNormMagn = var(magnIn) - cov(magnIn, magnAvgPause)^2 / - // var(magnAvgPause) - - uint32_t tmpU32no1, tmpU32no2; - uint32_t varMagnUFX, varPauseUFX, avgDiffNormMagnUFX; - - int32_t tmp32no1, tmp32no2; - int32_t avgPauseFX, avgMagnFX, covMagnPauseFX; - int32_t maxPause, minPause; - - int16_t tmp16no1; - - size_t i; - int norm32, nShifts; - - avgPauseFX = 0; - maxPause = 0; - minPause = inst->avgMagnPause[0]; // Q(prevQMagn) - // compute average quantities - for (i = 0; i < inst->magnLen; i++) { - // Compute mean of magn_pause - avgPauseFX += inst->avgMagnPause[i]; // in Q(prevQMagn) - maxPause = WEBRTC_SPL_MAX(maxPause, inst->avgMagnPause[i]); - minPause = WEBRTC_SPL_MIN(minPause, inst->avgMagnPause[i]); - } - // normalize by replacing div of "inst->magnLen" with "inst->stages-1" shifts - avgPauseFX >>= inst->stages - 1; - avgMagnFX = inst->sumMagn >> (inst->stages - 1); - // Largest possible deviation in magnPause for (co)var calculations - tmp32no1 = WEBRTC_SPL_MAX(maxPause - avgPauseFX, avgPauseFX - minPause); - // Get number of shifts to make sure we don't get wrap around in varPause - nShifts = WEBRTC_SPL_MAX(0, 10 + inst->stages - WebRtcSpl_NormW32(tmp32no1)); - - varMagnUFX = 0; - varPauseUFX = 0; - covMagnPauseFX = 0; - for (i = 0; i < inst->magnLen; i++) { - // Compute var and cov of magn and magn_pause - tmp16no1 = (int16_t)((int32_t)magnIn[i] - avgMagnFX); - tmp32no2 = inst->avgMagnPause[i] - avgPauseFX; - varMagnUFX += (uint32_t)(tmp16no1 * tmp16no1); // Q(2*qMagn) - tmp32no1 = tmp32no2 * tmp16no1; // Q(prevQMagn+qMagn) - covMagnPauseFX += tmp32no1; // Q(prevQMagn+qMagn) - tmp32no1 = tmp32no2 >> nShifts; // Q(prevQMagn-minPause). - varPauseUFX += tmp32no1 * tmp32no1; // Q(2*(prevQMagn-minPause)) - } - // update of average magnitude spectrum: Q(-2*stages) and averaging replaced - // by shifts - inst->curAvgMagnEnergy += - inst->magnEnergy >> (2 * inst->normData + inst->stages - 1); - - avgDiffNormMagnUFX = varMagnUFX; // Q(2*qMagn) - if ((varPauseUFX) && (covMagnPauseFX)) { - tmpU32no1 = - (uint32_t)WEBRTC_SPL_ABS_W32(covMagnPauseFX); // Q(prevQMagn+qMagn) - norm32 = WebRtcSpl_NormU32(tmpU32no1) - 16; - if (norm32 > 0) { - tmpU32no1 <<= norm32; // Q(prevQMagn+qMagn+norm32) - } else { - tmpU32no1 >>= -norm32; // Q(prevQMagn+qMagn+norm32) - } - tmpU32no2 = - WEBRTC_SPL_UMUL(tmpU32no1, tmpU32no1); // Q(2*(prevQMagn+qMagn-norm32)) - - nShifts += norm32; - nShifts <<= 1; - if (nShifts < 0) { - varPauseUFX >>= (-nShifts); // Q(2*(qMagn+norm32+minPause)) - nShifts = 0; - } - if (varPauseUFX > 0) { - // Q(2*(qMagn+norm32-16+minPause)) - tmpU32no1 = tmpU32no2 / varPauseUFX; - tmpU32no1 >>= nShifts; - - // Q(2*qMagn) - avgDiffNormMagnUFX -= WEBRTC_SPL_MIN(avgDiffNormMagnUFX, tmpU32no1); - } else { - avgDiffNormMagnUFX = 0; - } - } - // normalize and compute time average update of difference feature - tmpU32no1 = avgDiffNormMagnUFX >> (2 * inst->normData); - if (inst->featureSpecDiff > tmpU32no1) { - tmpU32no2 = WEBRTC_SPL_UMUL_32_16(inst->featureSpecDiff - tmpU32no1, - SPECT_DIFF_TAVG_Q8); // Q(8-2*stages) - inst->featureSpecDiff -= tmpU32no2 >> 8; // Q(-2*stages) - } else { - tmpU32no2 = WEBRTC_SPL_UMUL_32_16(tmpU32no1 - inst->featureSpecDiff, - SPECT_DIFF_TAVG_Q8); // Q(8-2*stages) - inst->featureSpecDiff += tmpU32no2 >> 8; // Q(-2*stages) - } -} - -// Transform input (speechFrame) to frequency domain magnitude (magnU16) -void WebRtcNsx_DataAnalysis(NoiseSuppressionFixedC* inst, - short* speechFrame, - uint16_t* magnU16) { - uint32_t tmpU32no1; - - int32_t tmp_1_w32 = 0; - int32_t tmp_2_w32 = 0; - int32_t sum_log_magn = 0; - int32_t sum_log_i_log_magn = 0; - - uint16_t sum_log_magn_u16 = 0; - uint16_t tmp_u16 = 0; - - int16_t sum_log_i = 0; - int16_t sum_log_i_square = 0; - int16_t frac = 0; - int16_t log2 = 0; - int16_t matrix_determinant = 0; - int16_t maxWinData; - - size_t i, j; - int zeros; - int net_norm = 0; - int right_shifts_in_magnU16 = 0; - int right_shifts_in_initMagnEst = 0; - - int16_t winData_buff[ANAL_BLOCKL_MAX * 2 + 16]; - int16_t realImag_buff[ANAL_BLOCKL_MAX * 2 + 16]; - - // Align the structures to 32-byte boundary for the FFT function. - int16_t* winData = (int16_t*)(((uintptr_t)winData_buff + 31) & ~31); - int16_t* realImag = (int16_t*)(((uintptr_t)realImag_buff + 31) & ~31); - - // Update analysis buffer for lower band, and window data before FFT. - WebRtcNsx_AnalysisUpdate(inst, winData, speechFrame); - - // Get input energy - inst->energyIn = - WebRtcSpl_Energy(winData, inst->anaLen, &inst->scaleEnergyIn); - - // Reset zero input flag - inst->zeroInputSignal = 0; - // Acquire norm for winData - maxWinData = WebRtcSpl_MaxAbsValueW16(winData, inst->anaLen); - inst->normData = WebRtcSpl_NormW16(maxWinData); - if (maxWinData == 0) { - // Treat zero input separately. - inst->zeroInputSignal = 1; - return; - } - - // Determine the net normalization in the frequency domain - net_norm = inst->stages - inst->normData; - // Track lowest normalization factor and use it to prevent wrap around in - // shifting - right_shifts_in_magnU16 = inst->normData - inst->minNorm; - right_shifts_in_initMagnEst = WEBRTC_SPL_MAX(-right_shifts_in_magnU16, 0); - inst->minNorm -= right_shifts_in_initMagnEst; - right_shifts_in_magnU16 = WEBRTC_SPL_MAX(right_shifts_in_magnU16, 0); - - // create realImag as winData interleaved with zeros (= imag. part), normalize - // it - WebRtcNsx_NormalizeRealBuffer(inst, winData, realImag); - - // FFT output will be in winData[]. - WebRtcSpl_RealForwardFFT(inst->real_fft, realImag, winData); - - inst->imag[0] = 0; // Q(normData-stages) - inst->imag[inst->anaLen2] = 0; - inst->real[0] = winData[0]; // Q(normData-stages) - inst->real[inst->anaLen2] = winData[inst->anaLen]; - // Q(2*(normData-stages)) - inst->magnEnergy = (uint32_t)(inst->real[0] * inst->real[0]); - inst->magnEnergy += - (uint32_t)(inst->real[inst->anaLen2] * inst->real[inst->anaLen2]); - magnU16[0] = - (uint16_t)WEBRTC_SPL_ABS_W16(inst->real[0]); // Q(normData-stages) - magnU16[inst->anaLen2] = - (uint16_t)WEBRTC_SPL_ABS_W16(inst->real[inst->anaLen2]); - inst->sumMagn = (uint32_t)magnU16[0]; // Q(normData-stages) - inst->sumMagn += (uint32_t)magnU16[inst->anaLen2]; - - if (inst->blockIndex >= END_STARTUP_SHORT) { - for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { - inst->real[i] = winData[j]; - inst->imag[i] = -winData[j + 1]; - // magnitude spectrum - // energy in Q(2*(normData-stages)) - tmpU32no1 = (uint32_t)(winData[j] * winData[j]); - tmpU32no1 += (uint32_t)(winData[j + 1] * winData[j + 1]); - inst->magnEnergy += tmpU32no1; // Q(2*(normData-stages)) - - magnU16[i] = - (uint16_t)WebRtcSpl_SqrtFloor(tmpU32no1); // Q(normData-stages) - inst->sumMagn += (uint32_t)magnU16[i]; // Q(normData-stages) - } - } else { - // - // Gather information during startup for noise parameter estimation - // - - // Switch initMagnEst to Q(minNorm-stages) - inst->initMagnEst[0] >>= right_shifts_in_initMagnEst; - inst->initMagnEst[inst->anaLen2] >>= right_shifts_in_initMagnEst; - - // Update initMagnEst with magnU16 in Q(minNorm-stages). - inst->initMagnEst[0] += magnU16[0] >> right_shifts_in_magnU16; - inst->initMagnEst[inst->anaLen2] += - magnU16[inst->anaLen2] >> right_shifts_in_magnU16; - - log2 = 0; - if (magnU16[inst->anaLen2]) { - // Calculate log2(magnU16[inst->anaLen2]) - zeros = WebRtcSpl_NormU32((uint32_t)magnU16[inst->anaLen2]); - frac = (int16_t)( - (((uint32_t)magnU16[inst->anaLen2] << zeros) & 0x7FFFFFFF) >> - 23); // Q8 - // log2(magnU16(i)) in Q8 - RTC_DCHECK_LT(frac, 256); - log2 = (int16_t)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); - } - - sum_log_magn = (int32_t)log2; // Q8 - // sum_log_i_log_magn in Q17 - sum_log_i_log_magn = (kLogIndex[inst->anaLen2] * log2) >> 3; - - for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { - inst->real[i] = winData[j]; - inst->imag[i] = -winData[j + 1]; - // magnitude spectrum - // energy in Q(2*(normData-stages)) - tmpU32no1 = (uint32_t)(winData[j] * winData[j]); - tmpU32no1 += (uint32_t)(winData[j + 1] * winData[j + 1]); - inst->magnEnergy += tmpU32no1; // Q(2*(normData-stages)) - - magnU16[i] = - (uint16_t)WebRtcSpl_SqrtFloor(tmpU32no1); // Q(normData-stages) - inst->sumMagn += (uint32_t)magnU16[i]; // Q(normData-stages) - - // Switch initMagnEst to Q(minNorm-stages) - inst->initMagnEst[i] >>= right_shifts_in_initMagnEst; - - // Update initMagnEst with magnU16 in Q(minNorm-stages). - inst->initMagnEst[i] += magnU16[i] >> right_shifts_in_magnU16; - - if (i >= kStartBand) { - // For pink noise estimation. Collect data neglecting lower frequency - // band - log2 = 0; - if (magnU16[i]) { - zeros = WebRtcSpl_NormU32((uint32_t)magnU16[i]); - frac = - (int16_t)((((uint32_t)magnU16[i] << zeros) & 0x7FFFFFFF) >> 23); - // log2(magnU16(i)) in Q8 - RTC_DCHECK_LT(frac, 256); - log2 = (int16_t)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); - } - sum_log_magn += (int32_t)log2; // Q8 - // sum_log_i_log_magn in Q17 - sum_log_i_log_magn += (kLogIndex[i] * log2) >> 3; - } - } - - // - // compute simplified noise model during startup - // - - // Estimate White noise - - // Switch whiteNoiseLevel to Q(minNorm-stages) - inst->whiteNoiseLevel >>= right_shifts_in_initMagnEst; - - // Update the average magnitude spectrum, used as noise estimate. - tmpU32no1 = WEBRTC_SPL_UMUL_32_16(inst->sumMagn, inst->overdrive); - tmpU32no1 >>= inst->stages + 8; - - // Replacing division above with 'stages' shifts - // Shift to same Q-domain as whiteNoiseLevel - tmpU32no1 >>= right_shifts_in_magnU16; - // This operation is safe from wrap around as long as END_STARTUP_SHORT < - // 128 - RTC_DCHECK_LT(END_STARTUP_SHORT, 128); - inst->whiteNoiseLevel += tmpU32no1; // Q(minNorm-stages) - - // Estimate Pink noise parameters - // Denominator used in both parameter estimates. - // The value is only dependent on the size of the frequency band - // (kStartBand) and to reduce computational complexity stored in a table - // (kDeterminantEstMatrix[]) - RTC_DCHECK_LT(kStartBand, 66); - matrix_determinant = kDeterminantEstMatrix[kStartBand]; // Q0 - sum_log_i = kSumLogIndex[kStartBand]; // Q5 - sum_log_i_square = kSumSquareLogIndex[kStartBand]; // Q2 - if (inst->fs == 8000) { - // Adjust values to shorter blocks in narrow band. - tmp_1_w32 = (int32_t)matrix_determinant; - tmp_1_w32 += (kSumLogIndex[65] * sum_log_i) >> 9; - tmp_1_w32 -= (kSumLogIndex[65] * kSumLogIndex[65]) >> 10; - tmp_1_w32 -= (int32_t)sum_log_i_square << 4; - tmp_1_w32 -= ((inst->magnLen - kStartBand) * kSumSquareLogIndex[65]) >> 2; - matrix_determinant = (int16_t)tmp_1_w32; - sum_log_i -= kSumLogIndex[65]; // Q5 - sum_log_i_square -= kSumSquareLogIndex[65]; // Q2 - } - - // Necessary number of shifts to fit sum_log_magn in a word16 - zeros = 16 - WebRtcSpl_NormW32(sum_log_magn); - if (zeros < 0) { - zeros = 0; - } - tmp_1_w32 = sum_log_magn << 1; // Q9 - sum_log_magn_u16 = (uint16_t)(tmp_1_w32 >> zeros); // Q(9-zeros). - - // Calculate and update pinkNoiseNumerator. Result in Q11. - tmp_2_w32 = WEBRTC_SPL_MUL_16_U16(sum_log_i_square, - sum_log_magn_u16); // Q(11-zeros) - tmpU32no1 = sum_log_i_log_magn >> 12; // Q5 - - // Shift the largest value of sum_log_i and tmp32no3 before multiplication - tmp_u16 = ((uint16_t)sum_log_i << 1); // Q6 - if ((uint32_t)sum_log_i > tmpU32no1) { - tmp_u16 >>= zeros; - } else { - tmpU32no1 >>= zeros; - } - tmp_2_w32 -= - (int32_t)WEBRTC_SPL_UMUL_32_16(tmpU32no1, tmp_u16); // Q(11-zeros) - matrix_determinant >>= zeros; // Q(-zeros) - tmp_2_w32 = WebRtcSpl_DivW32W16(tmp_2_w32, matrix_determinant); // Q11 - tmp_2_w32 += (int32_t)net_norm << 11; // Q11 - if (tmp_2_w32 < 0) { - tmp_2_w32 = 0; - } - inst->pinkNoiseNumerator += tmp_2_w32; // Q11 - - // Calculate and update pinkNoiseExp. Result in Q14. - tmp_2_w32 = - WEBRTC_SPL_MUL_16_U16(sum_log_i, sum_log_magn_u16); // Q(14-zeros) - tmp_1_w32 = sum_log_i_log_magn >> (3 + zeros); - tmp_1_w32 *= inst->magnLen - kStartBand; - tmp_2_w32 -= tmp_1_w32; // Q(14-zeros) - if (tmp_2_w32 > 0) { - // If the exponential parameter is negative force it to zero, which means - // a flat spectrum. - tmp_1_w32 = WebRtcSpl_DivW32W16(tmp_2_w32, matrix_determinant); // Q14 - inst->pinkNoiseExp += WEBRTC_SPL_SAT(16384, tmp_1_w32, 0); // Q14 - } - } -} - -void WebRtcNsx_DataSynthesis(NoiseSuppressionFixedC* inst, short* outFrame) { - int32_t energyOut; - - int16_t realImag_buff[ANAL_BLOCKL_MAX * 2 + 16]; - int16_t rfft_out_buff[ANAL_BLOCKL_MAX * 2 + 16]; - - // Align the structures to 32-byte boundary for the FFT function. - int16_t* realImag = (int16_t*)(((uintptr_t)realImag_buff + 31) & ~31); - int16_t* rfft_out = (int16_t*)(((uintptr_t)rfft_out_buff + 31) & ~31); - - int16_t tmp16no1, tmp16no2; - int16_t energyRatio; - int16_t gainFactor, gainFactor1, gainFactor2; - - size_t i; - int outCIFFT; - int scaleEnergyOut = 0; - - if (inst->zeroInputSignal) { - // synthesize the special case of zero input - // read out fully processed segment - for (i = 0; i < inst->blockLen10ms; i++) { - outFrame[i] = inst->synthesisBuffer[i]; // Q0 - } - // update synthesis buffer - memcpy( - inst->synthesisBuffer, inst->synthesisBuffer + inst->blockLen10ms, - (inst->anaLen - inst->blockLen10ms) * sizeof(*inst->synthesisBuffer)); - WebRtcSpl_ZerosArrayW16( - inst->synthesisBuffer + inst->anaLen - inst->blockLen10ms, - inst->blockLen10ms); - return; - } - - // Filter the data in the frequency domain, and create spectrum. - WebRtcNsx_PrepareSpectrum(inst, realImag); - - // Inverse FFT output will be in rfft_out[]. - outCIFFT = WebRtcSpl_RealInverseFFT(inst->real_fft, realImag, rfft_out); - - WebRtcNsx_Denormalize(inst, rfft_out, outCIFFT); - - // scale factor: only do it after END_STARTUP_LONG time - gainFactor = 8192; // 8192 = Q13(1.0) - if (inst->gainMap == 1 && inst->blockIndex > END_STARTUP_LONG && - inst->energyIn > 0) { - // Q(-scaleEnergyOut) - energyOut = WebRtcSpl_Energy(inst->real, inst->anaLen, &scaleEnergyOut); - if (scaleEnergyOut == 0 && !(energyOut & 0x7f800000)) { - energyOut = WEBRTC_SPL_SHIFT_W32( - energyOut, 8 + scaleEnergyOut - inst->scaleEnergyIn); - } else { - // |energyIn| is currently in Q(|scaleEnergyIn|), but to later on end up - // with an |energyRatio| in Q8 we need to change the Q-domain to - // Q(-8-scaleEnergyOut). - inst->energyIn >>= 8 + scaleEnergyOut - inst->scaleEnergyIn; - } - - RTC_DCHECK_GT(inst->energyIn, 0); - energyRatio = (energyOut + inst->energyIn / 2) / inst->energyIn; // Q8 - // Limit the ratio to [0, 1] in Q8, i.e., [0, 256] - energyRatio = WEBRTC_SPL_SAT(256, energyRatio, 0); - - // all done in lookup tables now - RTC_DCHECK_LT(energyRatio, 257); - gainFactor1 = kFactor1Table[energyRatio]; // Q8 - gainFactor2 = inst->factor2Table[energyRatio]; // Q8 - - // combine both scales with speech/noise prob: note prior (priorSpeechProb) - // is not frequency dependent - - // factor = inst->priorSpeechProb*factor1 + - // (1.0-inst->priorSpeechProb)*factor2; // original code - tmp16no1 = (int16_t)(((16384 - inst->priorNonSpeechProb) * gainFactor1) >> - 14); // in Q13, where 16384 = Q14(1.0) - tmp16no2 = (int16_t)((inst->priorNonSpeechProb * gainFactor2) >> 14); - gainFactor = tmp16no1 + tmp16no2; // Q13 - } // out of flag_gain_map==1 - - // Synthesis, read out fully processed segment, and update synthesis buffer. - WebRtcNsx_SynthesisUpdate(inst, outFrame, gainFactor); -} - -void WebRtcNsx_ProcessCore(NoiseSuppressionFixedC* inst, - const int16_t* const* speechFrame, - int num_bands, - int16_t* const* outFrame) { - // main routine for noise suppression - - uint32_t tmpU32no1, tmpU32no2, tmpU32no3; - uint32_t satMax, maxNoiseU32; - uint32_t tmpMagnU32, tmpNoiseU32; - uint32_t nearMagnEst; - uint32_t noiseUpdateU32; - uint32_t noiseU32[HALF_ANAL_BLOCKL]; - uint32_t postLocSnr[HALF_ANAL_BLOCKL]; - uint32_t priorLocSnr[HALF_ANAL_BLOCKL]; - uint32_t prevNearSnr[HALF_ANAL_BLOCKL]; - uint32_t curNearSnr; - uint32_t priorSnr; - uint32_t noise_estimate = 0; - uint32_t noise_estimate_avg = 0; - uint32_t numerator = 0; - - int32_t tmp32no1, tmp32no2; - int32_t pink_noise_num_avg = 0; - - uint16_t tmpU16no1; - uint16_t magnU16[HALF_ANAL_BLOCKL]; - uint16_t prevNoiseU16[HALF_ANAL_BLOCKL]; - uint16_t nonSpeechProbFinal[HALF_ANAL_BLOCKL]; - uint16_t gammaNoise, prevGammaNoise; - uint16_t noiseSupFilterTmp[HALF_ANAL_BLOCKL]; - - int16_t qMagn, qNoise; - int16_t avgProbSpeechHB, gainModHB, avgFilterGainHB, gainTimeDomainHB; - int16_t pink_noise_exp_avg = 0; - - size_t i, j; - int nShifts, postShifts; - int norm32no1, norm32no2; - int flag, sign; - int q_domain_to_use = 0; - - // Code for ARMv7-Neon platform assumes the following: - RTC_DCHECK_GT(inst->anaLen, 0); - RTC_DCHECK_GT(inst->anaLen2, 0); - RTC_DCHECK_EQ(0, inst->anaLen % 16); - RTC_DCHECK_EQ(0, inst->anaLen2 % 8); - RTC_DCHECK_GT(inst->blockLen10ms, 0); - RTC_DCHECK_EQ(0, inst->blockLen10ms % 16); - RTC_DCHECK_EQ(inst->magnLen, inst->anaLen2 + 1); - -#ifdef NS_FILEDEBUG - if (fwrite(spframe, sizeof(short), inst->blockLen10ms, inst->infile) != - inst->blockLen10ms) { - RTC_NOTREACHED(); - } -#endif - - // Check that initialization has been done - RTC_DCHECK_EQ(1, inst->initFlag); - RTC_DCHECK_LE(num_bands - 1, NUM_HIGH_BANDS_MAX); - - const int16_t* const* speechFrameHB = NULL; - int16_t* const* outFrameHB = NULL; - size_t num_high_bands = 0; - if (num_bands > 1) { - speechFrameHB = &speechFrame[1]; - outFrameHB = &outFrame[1]; - num_high_bands = (size_t)(num_bands - 1); - } - - // Store speechFrame and transform to frequency domain - WebRtcNsx_DataAnalysis(inst, (int16_t*)speechFrame[0], magnU16); - - if (inst->zeroInputSignal) { - WebRtcNsx_DataSynthesis(inst, outFrame[0]); - - if (num_bands > 1) { - // update analysis buffer for H band - // append new data to buffer FX - for (i = 0; i < num_high_bands; ++i) { - int block_shift = inst->anaLen - inst->blockLen10ms; - memcpy(inst->dataBufHBFX[i], inst->dataBufHBFX[i] + inst->blockLen10ms, - block_shift * sizeof(*inst->dataBufHBFX[i])); - memcpy(inst->dataBufHBFX[i] + block_shift, speechFrameHB[i], - inst->blockLen10ms * sizeof(*inst->dataBufHBFX[i])); - for (j = 0; j < inst->blockLen10ms; j++) { - outFrameHB[i][j] = inst->dataBufHBFX[i][j]; // Q0 - } - } - } // end of H band gain computation - return; - } - - // Update block index when we have something to process - inst->blockIndex++; - // - - // Norm of magn - qMagn = inst->normData - inst->stages; - - // Compute spectral flatness on input spectrum - WebRtcNsx_ComputeSpectralFlatness(inst, magnU16); - - // quantile noise estimate - WebRtcNsx_NoiseEstimation(inst, magnU16, noiseU32, &qNoise); - - // noise estimate from previous frame - for (i = 0; i < inst->magnLen; i++) { - prevNoiseU16[i] = (uint16_t)(inst->prevNoiseU32[i] >> 11); // Q(prevQNoise) - } - - if (inst->blockIndex < END_STARTUP_SHORT) { - // Noise Q-domain to be used later; see description at end of section. - q_domain_to_use = WEBRTC_SPL_MIN((int)qNoise, inst->minNorm - inst->stages); - - // Calculate frequency independent parts in parametric noise estimate and - // calculate the estimate for the lower frequency band (same values for all - // frequency bins) - if (inst->pinkNoiseExp) { - pink_noise_exp_avg = - (int16_t)WebRtcSpl_DivW32W16(inst->pinkNoiseExp, - (int16_t)(inst->blockIndex + 1)); // Q14 - pink_noise_num_avg = - WebRtcSpl_DivW32W16(inst->pinkNoiseNumerator, - (int16_t)(inst->blockIndex + 1)); // Q11 - WebRtcNsx_CalcParametricNoiseEstimate( - inst, pink_noise_exp_avg, pink_noise_num_avg, kStartBand, - &noise_estimate, &noise_estimate_avg); - } else { - // Use white noise estimate if we have poor pink noise parameter estimates - noise_estimate = inst->whiteNoiseLevel; // Q(minNorm-stages) - noise_estimate_avg = - noise_estimate / (inst->blockIndex + 1); // Q(minNorm-stages) - } - for (i = 0; i < inst->magnLen; i++) { - // Estimate the background noise using the pink noise parameters if - // permitted - if ((inst->pinkNoiseExp) && (i >= kStartBand)) { - // Reset noise_estimate - noise_estimate = 0; - noise_estimate_avg = 0; - // Calculate the parametric noise estimate for current frequency bin - WebRtcNsx_CalcParametricNoiseEstimate( - inst, pink_noise_exp_avg, pink_noise_num_avg, i, &noise_estimate, - &noise_estimate_avg); - } - // Calculate parametric Wiener filter - noiseSupFilterTmp[i] = inst->denoiseBound; - if (inst->initMagnEst[i]) { - // numerator = (initMagnEst - noise_estimate * overdrive) - // Result in Q(8+minNorm-stages) - tmpU32no1 = WEBRTC_SPL_UMUL_32_16(noise_estimate, inst->overdrive); - numerator = inst->initMagnEst[i] << 8; - if (numerator > tmpU32no1) { - // Suppression filter coefficient larger than zero, so calculate. - numerator -= tmpU32no1; - - // Determine number of left shifts in numerator for best accuracy - // after division - nShifts = WebRtcSpl_NormU32(numerator); - nShifts = WEBRTC_SPL_SAT(6, nShifts, 0); - - // Shift numerator to Q(nShifts+8+minNorm-stages) - numerator <<= nShifts; - - // Shift denominator to Q(nShifts-6+minNorm-stages) - tmpU32no1 = inst->initMagnEst[i] >> (6 - nShifts); - if (tmpU32no1 == 0) { - // This is only possible if numerator = 0, in which case - // we don't need any division. - tmpU32no1 = 1; - } - tmpU32no2 = numerator / tmpU32no1; // Q14 - noiseSupFilterTmp[i] = - (uint16_t)WEBRTC_SPL_SAT(16384, tmpU32no2, - (uint32_t)(inst->denoiseBound)); // Q14 - } - } - // Weight quantile noise 'noiseU32' with modeled noise - // 'noise_estimate_avg' 'noiseU32 is in Q(qNoise) and 'noise_estimate' in - // Q(minNorm-stages) To guarantee that we do not get wrap around when - // shifting to the same domain we use the lowest one. Furthermore, we need - // to save 6 bits for the weighting. 'noise_estimate_avg' can handle this - // operation by construction, but 'noiseU32' may not. - - // Shift 'noiseU32' to 'q_domain_to_use' - tmpU32no1 = noiseU32[i] >> (qNoise - q_domain_to_use); - // Shift 'noise_estimate_avg' to 'q_domain_to_use' - tmpU32no2 = noise_estimate_avg >> - (inst->minNorm - inst->stages - q_domain_to_use); - // Make a simple check to see if we have enough room for weighting - // 'tmpU32no1' without wrap around - nShifts = 0; - if (tmpU32no1 & 0xfc000000) { - tmpU32no1 >>= 6; - tmpU32no2 >>= 6; - nShifts = 6; - } - tmpU32no1 *= inst->blockIndex; - tmpU32no2 *= (END_STARTUP_SHORT - inst->blockIndex); - // Add them together and divide by startup length - noiseU32[i] = - WebRtcSpl_DivU32U16(tmpU32no1 + tmpU32no2, END_STARTUP_SHORT); - // Shift back if necessary - noiseU32[i] <<= nShifts; - } - // Update new Q-domain for 'noiseU32' - qNoise = q_domain_to_use; - } - // compute average signal during END_STARTUP_LONG time: - // used to normalize spectral difference measure - if (inst->blockIndex < END_STARTUP_LONG) { - // substituting division with shift ending up in Q(-2*stages) - inst->timeAvgMagnEnergyTmp += - inst->magnEnergy >> (2 * inst->normData + inst->stages - 1); - inst->timeAvgMagnEnergy = - WebRtcSpl_DivU32U16(inst->timeAvgMagnEnergyTmp, inst->blockIndex + 1); - } - - // start processing at frames == converged+1 - // STEP 1: compute prior and post SNR based on quantile noise estimates - - // compute direct decision (DD) estimate of prior SNR: needed for new method - satMax = (uint32_t)1048575; // Largest possible value without getting - // overflow despite shifting 12 steps - postShifts = 6 + qMagn - qNoise; - nShifts = 5 - inst->prevQMagn + inst->prevQNoise; - for (i = 0; i < inst->magnLen; i++) { - // FLOAT: - // post SNR - // postLocSnr[i] = 0.0; - // if (magn[i] > noise[i]) - // { - // postLocSnr[i] = magn[i] / (noise[i] + 0.0001); - // } - // // previous post SNR - // // previous estimate: based on previous frame with gain filter (smooth is - // previous filter) - // - // prevNearSnr[i] = inst->prevMagnU16[i] / (inst->noisePrev[i] + 0.0001) * - // (inst->smooth[i]); - // - // // DD estimate is sum of two terms: current estimate and previous - // estimate - // // directed decision update of priorSnr (or we actually store - // [2*priorSnr+1]) - // - // priorLocSnr[i] = DD_PR_SNR * prevNearSnr[i] + (1.0 - DD_PR_SNR) * - // (postLocSnr[i] - 1.0); - - // calculate post SNR: output in Q11 - postLocSnr[i] = 2048; // 1.0 in Q11 - tmpU32no1 = (uint32_t)magnU16[i] << 6; // Q(6+qMagn) - if (postShifts < 0) { - tmpU32no2 = noiseU32[i] >> -postShifts; // Q(6+qMagn) - } else { - tmpU32no2 = noiseU32[i] << postShifts; // Q(6+qMagn) - } - if (tmpU32no1 > tmpU32no2) { - // Current magnitude larger than noise - tmpU32no1 <<= 11; // Q(17+qMagn) - if (tmpU32no2 > 0) { - tmpU32no1 /= tmpU32no2; // Q11 - postLocSnr[i] = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 - } else { - postLocSnr[i] = satMax; - } - } - - // calculate prevNearSnr[i] and save for later instead of recalculating it - // later |nearMagnEst| in Q(prevQMagn + 14) - nearMagnEst = inst->prevMagnU16[i] * inst->noiseSupFilter[i]; - tmpU32no1 = nearMagnEst << 3; // Q(prevQMagn+17) - tmpU32no2 = inst->prevNoiseU32[i] >> nShifts; // Q(prevQMagn+6) - - if (tmpU32no2 > 0) { - tmpU32no1 /= tmpU32no2; // Q11 - tmpU32no1 = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 - } else { - tmpU32no1 = satMax; // Q11 - } - prevNearSnr[i] = tmpU32no1; // Q11 - - // directed decision update of priorSnr - tmpU32no1 = WEBRTC_SPL_UMUL_32_16(prevNearSnr[i], DD_PR_SNR_Q11); // Q22 - tmpU32no2 = WEBRTC_SPL_UMUL_32_16(postLocSnr[i] - 2048, - ONE_MINUS_DD_PR_SNR_Q11); // Q22 - priorSnr = tmpU32no1 + tmpU32no2 + 512; // Q22 (added 512 for rounding) - // priorLocSnr = 1 + 2*priorSnr - priorLocSnr[i] = 2048 + (priorSnr >> 10); // Q11 - } // end of loop over frequencies - // done with step 1: DD computation of prior and post SNR - - // STEP 2: compute speech/noise likelihood - - // compute difference of input spectrum with learned/estimated noise spectrum - WebRtcNsx_ComputeSpectralDifference(inst, magnU16); - // compute histograms for determination of parameters (thresholds and weights - // for features) parameters are extracted once every window time - // (=inst->modelUpdate) counter update - inst->cntThresUpdate++; - flag = (int)(inst->cntThresUpdate == inst->modelUpdate); - // update histogram - WebRtcNsx_FeatureParameterExtraction(inst, flag); - // compute model parameters - if (flag) { - inst->cntThresUpdate = 0; // Reset counter - // update every window: - // get normalization for spectral difference for next window estimate - - // Shift to Q(-2*stages) - inst->curAvgMagnEnergy >>= STAT_UPDATES; - - tmpU32no1 = (inst->curAvgMagnEnergy + inst->timeAvgMagnEnergy + 1) >> - 1; // Q(-2*stages) - // Update featureSpecDiff - if ((tmpU32no1 != inst->timeAvgMagnEnergy) && (inst->featureSpecDiff) && - (inst->timeAvgMagnEnergy > 0)) { - norm32no1 = 0; - tmpU32no3 = tmpU32no1; - while (0xFFFF0000 & tmpU32no3) { - tmpU32no3 >>= 1; - norm32no1++; - } - tmpU32no2 = inst->featureSpecDiff; - while (0xFFFF0000 & tmpU32no2) { - tmpU32no2 >>= 1; - norm32no1++; - } - tmpU32no3 = WEBRTC_SPL_UMUL(tmpU32no3, tmpU32no2); - tmpU32no3 /= inst->timeAvgMagnEnergy; - if (WebRtcSpl_NormU32(tmpU32no3) < norm32no1) { - inst->featureSpecDiff = 0x007FFFFF; - } else { - inst->featureSpecDiff = - WEBRTC_SPL_MIN(0x007FFFFF, tmpU32no3 << norm32no1); - } - } - - inst->timeAvgMagnEnergy = tmpU32no1; // Q(-2*stages) - inst->curAvgMagnEnergy = 0; - } - - // compute speech/noise probability - WebRtcNsx_SpeechNoiseProb(inst, nonSpeechProbFinal, priorLocSnr, postLocSnr); - - // time-avg parameter for noise update - gammaNoise = NOISE_UPDATE_Q8; // Q8 - - maxNoiseU32 = 0; - postShifts = inst->prevQNoise - qMagn; - nShifts = inst->prevQMagn - qMagn; - for (i = 0; i < inst->magnLen; i++) { - // temporary noise update: use it for speech frames if update value is less - // than previous the formula has been rewritten into: noiseUpdate = - // noisePrev[i] + (1 - gammaNoise) * nonSpeechProb * (magn[i] - - // noisePrev[i]) - - if (postShifts < 0) { - tmpU32no2 = magnU16[i] >> -postShifts; // Q(prevQNoise) - } else { - tmpU32no2 = (uint32_t)magnU16[i] << postShifts; // Q(prevQNoise) - } - if (prevNoiseU16[i] > tmpU32no2) { - sign = -1; - tmpU32no1 = prevNoiseU16[i] - tmpU32no2; - } else { - sign = 1; - tmpU32no1 = tmpU32no2 - prevNoiseU16[i]; - } - noiseUpdateU32 = inst->prevNoiseU32[i]; // Q(prevQNoise+11) - tmpU32no3 = 0; - if ((tmpU32no1) && (nonSpeechProbFinal[i])) { - // This value will be used later, if gammaNoise changes - tmpU32no3 = WEBRTC_SPL_UMUL_32_16( - tmpU32no1, nonSpeechProbFinal[i]); // Q(prevQNoise+8) - if (0x7c000000 & tmpU32no3) { - // Shifting required before multiplication - tmpU32no2 = (tmpU32no3 >> 5) * gammaNoise; // Q(prevQNoise+11) - } else { - // We can do shifting after multiplication - tmpU32no2 = (tmpU32no3 * gammaNoise) >> 5; // Q(prevQNoise+11) - } - if (sign > 0) { - noiseUpdateU32 += tmpU32no2; // Q(prevQNoise+11) - } else { - // This operation is safe. We can never get wrap around, since worst - // case scenario means magnU16 = 0 - noiseUpdateU32 -= tmpU32no2; // Q(prevQNoise+11) - } - } - - // increase gamma (i.e., less noise update) for frame likely to be speech - prevGammaNoise = gammaNoise; - gammaNoise = NOISE_UPDATE_Q8; - // time-constant based on speech/noise state - // increase gamma (i.e., less noise update) for frames likely to be speech - if (nonSpeechProbFinal[i] < ONE_MINUS_PROB_RANGE_Q8) { - gammaNoise = GAMMA_NOISE_TRANS_AND_SPEECH_Q8; - } - - if (prevGammaNoise != gammaNoise) { - // new noise update - // this line is the same as above, only that the result is stored in a - // different variable and the gammaNoise has changed - // - // noiseUpdate = noisePrev[i] + (1 - gammaNoise) * nonSpeechProb * - // (magn[i] - noisePrev[i]) - - if (0x7c000000 & tmpU32no3) { - // Shifting required before multiplication - tmpU32no2 = (tmpU32no3 >> 5) * gammaNoise; // Q(prevQNoise+11) - } else { - // We can do shifting after multiplication - tmpU32no2 = (tmpU32no3 * gammaNoise) >> 5; // Q(prevQNoise+11) - } - if (sign > 0) { - tmpU32no1 = inst->prevNoiseU32[i] + tmpU32no2; // Q(prevQNoise+11) - } else { - tmpU32no1 = inst->prevNoiseU32[i] - tmpU32no2; // Q(prevQNoise+11) - } - if (noiseUpdateU32 > tmpU32no1) { - noiseUpdateU32 = tmpU32no1; // Q(prevQNoise+11) - } - } - noiseU32[i] = noiseUpdateU32; // Q(prevQNoise+11) - if (noiseUpdateU32 > maxNoiseU32) { - maxNoiseU32 = noiseUpdateU32; - } - - // conservative noise update - // // original FLOAT code - // if (prob_speech < PROB_RANGE) { - // inst->avgMagnPause[i] = inst->avgMagnPause[i] + (1.0 - - // gamma_pause)*(magn[i] - inst->avgMagnPause[i]); - // } - - tmp32no2 = WEBRTC_SPL_SHIFT_W32(inst->avgMagnPause[i], -nShifts); - if (nonSpeechProbFinal[i] > ONE_MINUS_PROB_RANGE_Q8) { - if (nShifts < 0) { - tmp32no1 = (int32_t)magnU16[i] - tmp32no2; // Q(qMagn) - tmp32no1 *= ONE_MINUS_GAMMA_PAUSE_Q8; // Q(8+prevQMagn+nShifts) - tmp32no1 = (tmp32no1 + 128) >> 8; // Q(qMagn). - } else { - // In Q(qMagn+nShifts) - tmp32no1 = ((int32_t)magnU16[i] << nShifts) - inst->avgMagnPause[i]; - tmp32no1 *= ONE_MINUS_GAMMA_PAUSE_Q8; // Q(8+prevQMagn+nShifts) - tmp32no1 = (tmp32no1 + (128 << nShifts)) >> (8 + nShifts); // Q(qMagn). - } - tmp32no2 += tmp32no1; // Q(qMagn) - } - inst->avgMagnPause[i] = tmp32no2; - } // end of frequency loop - - norm32no1 = WebRtcSpl_NormU32(maxNoiseU32); - qNoise = inst->prevQNoise + norm32no1 - 5; - // done with step 2: noise update - - // STEP 3: compute dd update of prior snr and post snr based on new noise - // estimate - nShifts = inst->prevQNoise + 11 - qMagn; - for (i = 0; i < inst->magnLen; i++) { - // FLOAT code - // // post and prior SNR - // curNearSnr = 0.0; - // if (magn[i] > noise[i]) - // { - // curNearSnr = magn[i] / (noise[i] + 0.0001) - 1.0; - // } - // // DD estimate is sum of two terms: current estimate and previous - // estimate - // // directed decision update of snrPrior - // snrPrior = DD_PR_SNR * prevNearSnr[i] + (1.0 - DD_PR_SNR) * curNearSnr; - // // gain filter - // tmpFloat1 = inst->overdrive + snrPrior; - // tmpFloat2 = snrPrior / tmpFloat1; - // theFilter[i] = tmpFloat2; - - // calculate curNearSnr again, this is necessary because a new noise - // estimate has been made since then. for the original - curNearSnr = 0; // Q11 - if (nShifts < 0) { - // This case is equivalent with magn < noise which implies curNearSnr = 0; - tmpMagnU32 = (uint32_t)magnU16[i]; // Q(qMagn) - tmpNoiseU32 = noiseU32[i] << -nShifts; // Q(qMagn) - } else if (nShifts > 17) { - tmpMagnU32 = (uint32_t)magnU16[i] << 17; // Q(qMagn+17) - tmpNoiseU32 = noiseU32[i] >> (nShifts - 17); // Q(qMagn+17) - } else { - tmpMagnU32 = (uint32_t)magnU16[i] << nShifts; // Q(qNoise_prev+11) - tmpNoiseU32 = noiseU32[i]; // Q(qNoise_prev+11) - } - if (tmpMagnU32 > tmpNoiseU32) { - tmpU32no1 = tmpMagnU32 - tmpNoiseU32; // Q(qCur) - norm32no2 = WEBRTC_SPL_MIN(11, WebRtcSpl_NormU32(tmpU32no1)); - tmpU32no1 <<= norm32no2; // Q(qCur+norm32no2) - tmpU32no2 = tmpNoiseU32 >> (11 - norm32no2); // Q(qCur+norm32no2-11) - if (tmpU32no2 > 0) { - tmpU32no1 /= tmpU32no2; // Q11 - } - curNearSnr = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 - } - - // directed decision update of priorSnr - // FLOAT - // priorSnr = DD_PR_SNR * prevNearSnr + (1.0-DD_PR_SNR) * curNearSnr; - - tmpU32no1 = WEBRTC_SPL_UMUL_32_16(prevNearSnr[i], DD_PR_SNR_Q11); // Q22 - tmpU32no2 = - WEBRTC_SPL_UMUL_32_16(curNearSnr, ONE_MINUS_DD_PR_SNR_Q11); // Q22 - priorSnr = tmpU32no1 + tmpU32no2; // Q22 - - // gain filter - tmpU32no1 = inst->overdrive + ((priorSnr + 8192) >> 14); // Q8 - RTC_DCHECK_GT(inst->overdrive, 0); - tmpU16no1 = (priorSnr + tmpU32no1 / 2) / tmpU32no1; // Q14 - inst->noiseSupFilter[i] = WEBRTC_SPL_SAT( - 16384, tmpU16no1, inst->denoiseBound); // 16384 = Q14(1.0) // Q14 - - // Weight in the parametric Wiener filter during startup - if (inst->blockIndex < END_STARTUP_SHORT) { - // Weight the two suppression filters - tmpU32no1 = inst->noiseSupFilter[i] * inst->blockIndex; - tmpU32no2 = noiseSupFilterTmp[i] * (END_STARTUP_SHORT - inst->blockIndex); - tmpU32no1 += tmpU32no2; - inst->noiseSupFilter[i] = - (uint16_t)WebRtcSpl_DivU32U16(tmpU32no1, END_STARTUP_SHORT); - } - } // end of loop over frequencies - // done with step3 - - // save noise and magnitude spectrum for next frame - inst->prevQNoise = qNoise; - inst->prevQMagn = qMagn; - if (norm32no1 > 5) { - for (i = 0; i < inst->magnLen; i++) { - inst->prevNoiseU32[i] = noiseU32[i] << (norm32no1 - 5); // Q(qNoise+11) - inst->prevMagnU16[i] = magnU16[i]; // Q(qMagn) - } - } else { - for (i = 0; i < inst->magnLen; i++) { - inst->prevNoiseU32[i] = noiseU32[i] >> (5 - norm32no1); // Q(qNoise+11) - inst->prevMagnU16[i] = magnU16[i]; // Q(qMagn) - } - } - - WebRtcNsx_DataSynthesis(inst, outFrame[0]); -#ifdef NS_FILEDEBUG - if (fwrite(outframe, sizeof(short), inst->blockLen10ms, inst->outfile) != - inst->blockLen10ms) { - RTC_NOTREACHED(); - } -#endif - - // for H band: - // only update data buffer, then apply time-domain gain is applied derived - // from L band - if (num_bands > 1) { - // update analysis buffer for H band - // append new data to buffer FX - for (i = 0; i < num_high_bands; ++i) { - memcpy( - inst->dataBufHBFX[i], inst->dataBufHBFX[i] + inst->blockLen10ms, - (inst->anaLen - inst->blockLen10ms) * sizeof(*inst->dataBufHBFX[i])); - memcpy(inst->dataBufHBFX[i] + inst->anaLen - inst->blockLen10ms, - speechFrameHB[i], - inst->blockLen10ms * sizeof(*inst->dataBufHBFX[i])); - } - // range for averaging low band quantities for H band gain - - gainTimeDomainHB = 16384; // 16384 = Q14(1.0) - // average speech prob from low band - // average filter gain from low band - // avg over second half (i.e., 4->8kHz) of freq. spectrum - tmpU32no1 = 0; // Q12 - tmpU16no1 = 0; // Q8 - for (i = inst->anaLen2 - (inst->anaLen2 >> 2); i < inst->anaLen2; i++) { - tmpU16no1 += nonSpeechProbFinal[i]; // Q8 - tmpU32no1 += (uint32_t)(inst->noiseSupFilter[i]); // Q14 - } - RTC_DCHECK_GE(inst->stages, 7); - avgProbSpeechHB = (4096 - (tmpU16no1 >> (inst->stages - 7))); // Q12 - avgFilterGainHB = (int16_t)(tmpU32no1 >> (inst->stages - 3)); // Q14 - - // // original FLOAT code - // // gain based on speech probability: - // avg_prob_speech_tt=(float)2.0*avg_prob_speech-(float)1.0; - // gain_mod=(float)0.5*((float)1.0+(float)tanh(avg_prob_speech_tt)); // - // between 0 and 1 - - // gain based on speech probability: - // original expression: "0.5 * (1 + tanh(2x-1))" - // avgProbSpeechHB has been anyway saturated to a value between 0 and 1 so - // the other cases don't have to be dealt with avgProbSpeechHB and gainModHB - // are in Q12, 3607 = Q12(0.880615234375) which is a zero point of |0.5 * (1 - // + tanh(2x-1)) - x| - |0.5 * (1 + tanh(2x-1)) - 0.880615234375| meaning - // that from that point the error of approximating the expression with f(x) - // = x would be greater than the error of approximating the expression with - // f(x) = 0.880615234375 error: "|0.5 * (1 + tanh(2x-1)) - x| from x=0 to - // 0.880615234375" -> - // http://www.wolframalpha.com/input/?i=|0.5+*+(1+%2B+tanh(2x-1))+-+x|+from+x%3D0+to+0.880615234375 - // and: "|0.5 * (1 + tanh(2x-1)) - 0.880615234375| from x=0.880615234375 to - // 1" -> - // http://www.wolframalpha.com/input/?i=+|0.5+*+(1+%2B+tanh(2x-1))+-+0.880615234375|+from+x%3D0.880615234375+to+1 - gainModHB = WEBRTC_SPL_MIN(avgProbSpeechHB, 3607); - - // // original FLOAT code - // //combine gain with low band gain - // if (avg_prob_speech < (float)0.5) { - // gain_time_domain_HB=(float)0.5*gain_mod+(float)0.5*avg_filter_gain; - // } - // else { - // gain_time_domain_HB=(float)0.25*gain_mod+(float)0.75*avg_filter_gain; - // } - - // combine gain with low band gain - if (avgProbSpeechHB < 2048) { - // 2048 = Q12(0.5) - // the next two lines in float are "gain_time_domain = 0.5 * gain_mod + - // 0.5 * avg_filter_gain"; Q2(0.5) = 2 equals one left shift - gainTimeDomainHB = (gainModHB << 1) + (avgFilterGainHB >> 1); // Q14 - } else { - // "gain_time_domain = 0.25 * gain_mod + 0.75 * agv_filter_gain;" - gainTimeDomainHB = (int16_t)((3 * avgFilterGainHB) >> 2); // 3 = Q2(0.75) - gainTimeDomainHB += gainModHB; // Q14 - } - // make sure gain is within flooring range - gainTimeDomainHB = - WEBRTC_SPL_SAT(16384, gainTimeDomainHB, - (int16_t)(inst->denoiseBound)); // 16384 = Q14(1.0) - - // apply gain - for (i = 0; i < num_high_bands; ++i) { - for (j = 0; j < inst->blockLen10ms; j++) { - outFrameHB[i][j] = (int16_t)( - (gainTimeDomainHB * inst->dataBufHBFX[i][j]) >> 14); // Q0 - } - } - } // end of H band gain computation -}
diff --git a/modules/audio_processing/legacy_ns/nsx_core.h b/modules/audio_processing/legacy_ns/nsx_core.h deleted file mode 100644 index a3f224a..0000000 --- a/modules/audio_processing/legacy_ns/nsx_core.h +++ /dev/null
@@ -1,261 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_CORE_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_CORE_H_ - -#ifdef NS_FILEDEBUG -#include <stdio.h> -#endif - -#include "common_audio/signal_processing/include/signal_processing_library.h" -#include "modules/audio_processing/legacy_ns/nsx_defines.h" - -typedef struct NoiseSuppressionFixedC_ { - uint32_t fs; - - const int16_t* window; - int16_t analysisBuffer[ANAL_BLOCKL_MAX]; - int16_t synthesisBuffer[ANAL_BLOCKL_MAX]; - uint16_t noiseSupFilter[HALF_ANAL_BLOCKL]; - uint16_t overdrive; /* Q8 */ - uint16_t denoiseBound; /* Q14 */ - const int16_t* factor2Table; - int16_t noiseEstLogQuantile[SIMULT * HALF_ANAL_BLOCKL]; - int16_t noiseEstDensity[SIMULT * HALF_ANAL_BLOCKL]; - int16_t noiseEstCounter[SIMULT]; - int16_t noiseEstQuantile[HALF_ANAL_BLOCKL]; - - size_t anaLen; - size_t anaLen2; - size_t magnLen; - int aggrMode; - int stages; - int initFlag; - int gainMap; - - int32_t maxLrt; - int32_t minLrt; - // Log LRT factor with time-smoothing in Q8. - int32_t logLrtTimeAvgW32[HALF_ANAL_BLOCKL]; - int32_t featureLogLrt; - int32_t thresholdLogLrt; - int16_t weightLogLrt; - - uint32_t featureSpecDiff; - uint32_t thresholdSpecDiff; - int16_t weightSpecDiff; - - uint32_t featureSpecFlat; - uint32_t thresholdSpecFlat; - int16_t weightSpecFlat; - - // Conservative estimate of noise spectrum. - int32_t avgMagnPause[HALF_ANAL_BLOCKL]; - uint32_t magnEnergy; - uint32_t sumMagn; - uint32_t curAvgMagnEnergy; - uint32_t timeAvgMagnEnergy; - uint32_t timeAvgMagnEnergyTmp; - - uint32_t whiteNoiseLevel; // Initial noise estimate. - // Initial magnitude spectrum estimate. - uint32_t initMagnEst[HALF_ANAL_BLOCKL]; - // Pink noise parameters: - int32_t pinkNoiseNumerator; // Numerator. - int32_t pinkNoiseExp; // Power of freq. - int minNorm; // Smallest normalization factor. - int zeroInputSignal; // Zero input signal flag. - - // Noise spectrum from previous frame. - uint32_t prevNoiseU32[HALF_ANAL_BLOCKL]; - // Magnitude spectrum from previous frame. - uint16_t prevMagnU16[HALF_ANAL_BLOCKL]; - // Prior speech/noise probability in Q14. - int16_t priorNonSpeechProb; - - int blockIndex; // Frame index counter. - // Parameter for updating or estimating thresholds/weights for prior model. - int modelUpdate; - int cntThresUpdate; - - // Histograms for parameter estimation. - int16_t histLrt[HIST_PAR_EST]; - int16_t histSpecFlat[HIST_PAR_EST]; - int16_t histSpecDiff[HIST_PAR_EST]; - - // Quantities for high band estimate. - int16_t dataBufHBFX[NUM_HIGH_BANDS_MAX][ANAL_BLOCKL_MAX]; - - int qNoise; - int prevQNoise; - int prevQMagn; - size_t blockLen10ms; - - int16_t real[ANAL_BLOCKL_MAX]; - int16_t imag[ANAL_BLOCKL_MAX]; - int32_t energyIn; - int scaleEnergyIn; - int normData; - - struct RealFFT* real_fft; -} NoiseSuppressionFixedC; - -#ifdef __cplusplus -extern "C" { -#endif - -/**************************************************************************** - * WebRtcNsx_InitCore(...) - * - * This function initializes a noise suppression instance - * - * Input: - * - inst : Instance that should be initialized - * - fs : Sampling frequency - * - * Output: - * - inst : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int32_t WebRtcNsx_InitCore(NoiseSuppressionFixedC* inst, uint32_t fs); - -/**************************************************************************** - * WebRtcNsx_set_policy_core(...) - * - * This changes the aggressiveness of the noise suppression method. - * - * Input: - * - inst : Instance that should be initialized - * - mode : 0: Mild (6 dB), 1: Medium (10 dB), 2: Aggressive (15 dB) - * - * Output: - * - inst : Initialized instance - * - * Return value : 0 - Ok - * -1 - Error - */ -int WebRtcNsx_set_policy_core(NoiseSuppressionFixedC* inst, int mode); - -/**************************************************************************** - * WebRtcNsx_ProcessCore - * - * Do noise suppression. - * - * Input: - * - inst : Instance that should be initialized - * - inFrame : Input speech frame for each band - * - num_bands : Number of bands - * - * Output: - * - inst : Updated instance - * - outFrame : Output speech frame for each band - */ -void WebRtcNsx_ProcessCore(NoiseSuppressionFixedC* inst, - const int16_t* const* inFrame, - int num_bands, - int16_t* const* outFrame); - -/**************************************************************************** - * Some function pointers, for internal functions shared by ARM NEON and - * generic C code. - */ -// Noise Estimation. -typedef void (*NoiseEstimation)(NoiseSuppressionFixedC* inst, - uint16_t* magn, - uint32_t* noise, - int16_t* q_noise); -extern NoiseEstimation WebRtcNsx_NoiseEstimation; - -// Filter the data in the frequency domain, and create spectrum. -typedef void (*PrepareSpectrum)(NoiseSuppressionFixedC* inst, - int16_t* freq_buff); -extern PrepareSpectrum WebRtcNsx_PrepareSpectrum; - -// For the noise supression process, synthesis, read out fully processed -// segment, and update synthesis buffer. -typedef void (*SynthesisUpdate)(NoiseSuppressionFixedC* inst, - int16_t* out_frame, - int16_t gain_factor); -extern SynthesisUpdate WebRtcNsx_SynthesisUpdate; - -// Update analysis buffer for lower band, and window data before FFT. -typedef void (*AnalysisUpdate)(NoiseSuppressionFixedC* inst, - int16_t* out, - int16_t* new_speech); -extern AnalysisUpdate WebRtcNsx_AnalysisUpdate; - -// Denormalize the real-valued signal |in|, the output from inverse FFT. -typedef void (*Denormalize)(NoiseSuppressionFixedC* inst, - int16_t* in, - int factor); -extern Denormalize WebRtcNsx_Denormalize; - -// Normalize the real-valued signal |in|, the input to forward FFT. -typedef void (*NormalizeRealBuffer)(NoiseSuppressionFixedC* inst, - const int16_t* in, - int16_t* out); -extern NormalizeRealBuffer WebRtcNsx_NormalizeRealBuffer; - -// Compute speech/noise probability. -// Intended to be private. -void WebRtcNsx_SpeechNoiseProb(NoiseSuppressionFixedC* inst, - uint16_t* nonSpeechProbFinal, - uint32_t* priorLocSnr, - uint32_t* postLocSnr); - -#if defined(WEBRTC_HAS_NEON) -// For the above function pointers, functions for generic platforms are declared -// and defined as static in file nsx_core.c, while those for ARM Neon platforms -// are declared below and defined in file nsx_core_neon.c. -void WebRtcNsx_NoiseEstimationNeon(NoiseSuppressionFixedC* inst, - uint16_t* magn, - uint32_t* noise, - int16_t* q_noise); -void WebRtcNsx_SynthesisUpdateNeon(NoiseSuppressionFixedC* inst, - int16_t* out_frame, - int16_t gain_factor); -void WebRtcNsx_AnalysisUpdateNeon(NoiseSuppressionFixedC* inst, - int16_t* out, - int16_t* new_speech); -void WebRtcNsx_PrepareSpectrumNeon(NoiseSuppressionFixedC* inst, - int16_t* freq_buff); -#endif - -#if defined(MIPS32_LE) -// For the above function pointers, functions for generic platforms are declared -// and defined as static in file nsx_core.c, while those for MIPS platforms -// are declared below and defined in file nsx_core_mips.c. -void WebRtcNsx_SynthesisUpdate_mips(NoiseSuppressionFixedC* inst, - int16_t* out_frame, - int16_t gain_factor); -void WebRtcNsx_AnalysisUpdate_mips(NoiseSuppressionFixedC* inst, - int16_t* out, - int16_t* new_speech); -void WebRtcNsx_PrepareSpectrum_mips(NoiseSuppressionFixedC* inst, - int16_t* freq_buff); -void WebRtcNsx_NormalizeRealBuffer_mips(NoiseSuppressionFixedC* inst, - const int16_t* in, - int16_t* out); -#if defined(MIPS_DSP_R1_LE) -void WebRtcNsx_Denormalize_mips(NoiseSuppressionFixedC* inst, - int16_t* in, - int factor); -#endif - -#endif - -#ifdef __cplusplus -} -#endif - -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_CORE_H_
diff --git a/modules/audio_processing/legacy_ns/nsx_core_c.c b/modules/audio_processing/legacy_ns/nsx_core_c.c deleted file mode 100644 index 2b0bb2f..0000000 --- a/modules/audio_processing/legacy_ns/nsx_core_c.c +++ /dev/null
@@ -1,259 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "rtc_base/checks.h" -#include "modules/audio_processing/legacy_ns/noise_suppression_x.h" -#include "modules/audio_processing/legacy_ns/nsx_core.h" -#include "modules/audio_processing/legacy_ns/nsx_defines.h" - -static const int16_t kIndicatorTable[17] = { - 0, 2017, 3809, 5227, 6258, 6963, 7424, 7718, - 7901, 8014, 8084, 8126, 8152, 8168, 8177, 8183, 8187 -}; - -// Compute speech/noise probability -// speech/noise probability is returned in: probSpeechFinal -//snrLocPrior is the prior SNR for each frequency (in Q11) -//snrLocPost is the post SNR for each frequency (in Q11) -void WebRtcNsx_SpeechNoiseProb(NoiseSuppressionFixedC* inst, - uint16_t* nonSpeechProbFinal, - uint32_t* priorLocSnr, - uint32_t* postLocSnr) { - uint32_t zeros, num, den, tmpU32no1, tmpU32no2, tmpU32no3; - int32_t invLrtFX, indPriorFX, tmp32, tmp32no1, tmp32no2, besselTmpFX32; - int32_t frac32, logTmp; - int32_t logLrtTimeAvgKsumFX; - int16_t indPriorFX16; - int16_t tmp16, tmp16no1, tmp16no2, tmpIndFX, tableIndex, frac, intPart; - size_t i; - int normTmp, normTmp2, nShifts; - - // compute feature based on average LR factor - // this is the average over all frequencies of the smooth log LRT - logLrtTimeAvgKsumFX = 0; - for (i = 0; i < inst->magnLen; i++) { - besselTmpFX32 = (int32_t)postLocSnr[i]; // Q11 - normTmp = WebRtcSpl_NormU32(postLocSnr[i]); - num = postLocSnr[i] << normTmp; // Q(11+normTmp) - if (normTmp > 10) { - den = priorLocSnr[i] << (normTmp - 11); // Q(normTmp) - } else { - den = priorLocSnr[i] >> (11 - normTmp); // Q(normTmp) - } - if (den > 0) { - besselTmpFX32 -= num / den; // Q11 - } else { - besselTmpFX32 = 0; - } - - // inst->logLrtTimeAvg[i] += LRT_TAVG * (besselTmp - log(snrLocPrior) - // - inst->logLrtTimeAvg[i]); - // Here, LRT_TAVG = 0.5 - zeros = WebRtcSpl_NormU32(priorLocSnr[i]); - frac32 = (int32_t)(((priorLocSnr[i] << zeros) & 0x7FFFFFFF) >> 19); - tmp32 = (frac32 * frac32 * -43) >> 19; - tmp32 += ((int16_t)frac32 * 5412) >> 12; - frac32 = tmp32 + 37; - // tmp32 = log2(priorLocSnr[i]) - tmp32 = (int32_t)(((31 - zeros) << 12) + frac32) - (11 << 12); // Q12 - logTmp = (tmp32 * 178) >> 8; // log2(priorLocSnr[i])*log(2) - // tmp32no1 = LRT_TAVG * (log(snrLocPrior) + inst->logLrtTimeAvg[i]) in Q12. - tmp32no1 = (logTmp + inst->logLrtTimeAvgW32[i]) / 2; - inst->logLrtTimeAvgW32[i] += (besselTmpFX32 - tmp32no1); // Q12 - - logLrtTimeAvgKsumFX += inst->logLrtTimeAvgW32[i]; // Q12 - } - inst->featureLogLrt = (logLrtTimeAvgKsumFX * BIN_SIZE_LRT) >> - (inst->stages + 11); - - // done with computation of LR factor - - // - //compute the indicator functions - // - - // average LRT feature - // FLOAT code - // indicator0 = 0.5 * (tanh(widthPrior * - // (logLrtTimeAvgKsum - threshPrior0)) + 1.0); - tmpIndFX = 16384; // Q14(1.0) - tmp32no1 = logLrtTimeAvgKsumFX - inst->thresholdLogLrt; // Q12 - nShifts = 7 - inst->stages; // WIDTH_PR_MAP_SHIFT - inst->stages + 5; - //use larger width in tanh map for pause regions - if (tmp32no1 < 0) { - tmpIndFX = 0; - tmp32no1 = -tmp32no1; - //widthPrior = widthPrior * 2.0; - nShifts++; - } - tmp32no1 = WEBRTC_SPL_SHIFT_W32(tmp32no1, nShifts); // Q14 - // compute indicator function: sigmoid map - if (tmp32no1 < (16 << 14) && tmp32no1 >= 0) { - tableIndex = (int16_t)(tmp32no1 >> 14); - tmp16no2 = kIndicatorTable[tableIndex]; - tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex]; - frac = (int16_t)(tmp32no1 & 0x00003fff); // Q14 - tmp16no2 += (int16_t)((tmp16no1 * frac) >> 14); - if (tmpIndFX == 0) { - tmpIndFX = 8192 - tmp16no2; // Q14 - } else { - tmpIndFX = 8192 + tmp16no2; // Q14 - } - } - indPriorFX = inst->weightLogLrt * tmpIndFX; // 6*Q14 - - //spectral flatness feature - if (inst->weightSpecFlat) { - tmpU32no1 = WEBRTC_SPL_UMUL(inst->featureSpecFlat, 400); // Q10 - tmpIndFX = 16384; // Q14(1.0) - //use larger width in tanh map for pause regions - tmpU32no2 = inst->thresholdSpecFlat - tmpU32no1; //Q10 - nShifts = 4; - if (inst->thresholdSpecFlat < tmpU32no1) { - tmpIndFX = 0; - tmpU32no2 = tmpU32no1 - inst->thresholdSpecFlat; - //widthPrior = widthPrior * 2.0; - nShifts++; - } - tmpU32no1 = WebRtcSpl_DivU32U16(tmpU32no2 << nShifts, 25); // Q14 - // compute indicator function: sigmoid map - // FLOAT code - // indicator1 = 0.5 * (tanh(sgnMap * widthPrior * - // (threshPrior1 - tmpFloat1)) + 1.0); - if (tmpU32no1 < (16 << 14)) { - tableIndex = (int16_t)(tmpU32no1 >> 14); - tmp16no2 = kIndicatorTable[tableIndex]; - tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex]; - frac = (int16_t)(tmpU32no1 & 0x00003fff); // Q14 - tmp16no2 += (int16_t)((tmp16no1 * frac) >> 14); - if (tmpIndFX) { - tmpIndFX = 8192 + tmp16no2; // Q14 - } else { - tmpIndFX = 8192 - tmp16no2; // Q14 - } - } - indPriorFX += inst->weightSpecFlat * tmpIndFX; // 6*Q14 - } - - //for template spectral-difference - if (inst->weightSpecDiff) { - tmpU32no1 = 0; - if (inst->featureSpecDiff) { - normTmp = WEBRTC_SPL_MIN(20 - inst->stages, - WebRtcSpl_NormU32(inst->featureSpecDiff)); - RTC_DCHECK_GE(normTmp, 0); - tmpU32no1 = inst->featureSpecDiff << normTmp; // Q(normTmp-2*stages) - tmpU32no2 = inst->timeAvgMagnEnergy >> (20 - inst->stages - normTmp); - if (tmpU32no2 > 0) { - // Q(20 - inst->stages) - tmpU32no1 /= tmpU32no2; - } else { - tmpU32no1 = (uint32_t)(0x7fffffff); - } - } - tmpU32no3 = (inst->thresholdSpecDiff << 17) / 25; - tmpU32no2 = tmpU32no1 - tmpU32no3; - nShifts = 1; - tmpIndFX = 16384; // Q14(1.0) - //use larger width in tanh map for pause regions - if (tmpU32no2 & 0x80000000) { - tmpIndFX = 0; - tmpU32no2 = tmpU32no3 - tmpU32no1; - //widthPrior = widthPrior * 2.0; - nShifts--; - } - tmpU32no1 = tmpU32no2 >> nShifts; - // compute indicator function: sigmoid map - /* FLOAT code - indicator2 = 0.5 * (tanh(widthPrior * (tmpFloat1 - threshPrior2)) + 1.0); - */ - if (tmpU32no1 < (16 << 14)) { - tableIndex = (int16_t)(tmpU32no1 >> 14); - tmp16no2 = kIndicatorTable[tableIndex]; - tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex]; - frac = (int16_t)(tmpU32no1 & 0x00003fff); // Q14 - tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( - tmp16no1, frac, 14); - if (tmpIndFX) { - tmpIndFX = 8192 + tmp16no2; - } else { - tmpIndFX = 8192 - tmp16no2; - } - } - indPriorFX += inst->weightSpecDiff * tmpIndFX; // 6*Q14 - } - - //combine the indicator function with the feature weights - // FLOAT code - // indPrior = 1 - (weightIndPrior0 * indicator0 + weightIndPrior1 * - // indicator1 + weightIndPrior2 * indicator2); - indPriorFX16 = WebRtcSpl_DivW32W16ResW16(98307 - indPriorFX, 6); // Q14 - // done with computing indicator function - - //compute the prior probability - // FLOAT code - // inst->priorNonSpeechProb += PRIOR_UPDATE * - // (indPriorNonSpeech - inst->priorNonSpeechProb); - tmp16 = indPriorFX16 - inst->priorNonSpeechProb; // Q14 - inst->priorNonSpeechProb += (int16_t)((PRIOR_UPDATE_Q14 * tmp16) >> 14); - - //final speech probability: combine prior model with LR factor: - - memset(nonSpeechProbFinal, 0, sizeof(uint16_t) * inst->magnLen); - - if (inst->priorNonSpeechProb > 0) { - for (i = 0; i < inst->magnLen; i++) { - // FLOAT code - // invLrt = exp(inst->logLrtTimeAvg[i]); - // invLrt = inst->priorSpeechProb * invLrt; - // nonSpeechProbFinal[i] = (1.0 - inst->priorSpeechProb) / - // (1.0 - inst->priorSpeechProb + invLrt); - // invLrt = (1.0 - inst->priorNonSpeechProb) * invLrt; - // nonSpeechProbFinal[i] = inst->priorNonSpeechProb / - // (inst->priorNonSpeechProb + invLrt); - if (inst->logLrtTimeAvgW32[i] < 65300) { - tmp32no1 = (inst->logLrtTimeAvgW32[i] * 23637) >> 14; // Q12 - intPart = (int16_t)(tmp32no1 >> 12); - if (intPart < -8) { - intPart = -8; - } - frac = (int16_t)(tmp32no1 & 0x00000fff); // Q12 - - // Quadratic approximation of 2^frac - tmp32no2 = (frac * frac * 44) >> 19; // Q12. - tmp32no2 += (frac * 84) >> 7; // Q12 - invLrtFX = (1 << (8 + intPart)) + - WEBRTC_SPL_SHIFT_W32(tmp32no2, intPart - 4); // Q8 - - normTmp = WebRtcSpl_NormW32(invLrtFX); - normTmp2 = WebRtcSpl_NormW16((16384 - inst->priorNonSpeechProb)); - if (normTmp + normTmp2 >= 7) { - if (normTmp + normTmp2 < 15) { - invLrtFX >>= 15 - normTmp2 - normTmp; - // Q(normTmp+normTmp2-7) - tmp32no1 = invLrtFX * (16384 - inst->priorNonSpeechProb); - // Q(normTmp+normTmp2+7) - invLrtFX = WEBRTC_SPL_SHIFT_W32(tmp32no1, 7 - normTmp - normTmp2); - // Q14 - } else { - tmp32no1 = invLrtFX * (16384 - inst->priorNonSpeechProb); - // Q22 - invLrtFX = tmp32no1 >> 8; // Q14. - } - - tmp32no1 = (int32_t)inst->priorNonSpeechProb << 8; // Q22 - - nonSpeechProbFinal[i] = tmp32no1 / - (inst->priorNonSpeechProb + invLrtFX); // Q8 - } - } - } - } -}
diff --git a/modules/audio_processing/legacy_ns/nsx_core_neon.c b/modules/audio_processing/legacy_ns/nsx_core_neon.c deleted file mode 100644 index 244111c..0000000 --- a/modules/audio_processing/legacy_ns/nsx_core_neon.c +++ /dev/null
@@ -1,606 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_processing/legacy_ns/nsx_core.h" - -#include <arm_neon.h> - -#include "rtc_base/checks.h" - -// Constants to compensate for shifting signal log(2^shifts). -const int16_t WebRtcNsx_kLogTable[9] = { - 0, 177, 355, 532, 710, 887, 1065, 1242, 1420 -}; - -const int16_t WebRtcNsx_kCounterDiv[201] = { - 32767, 16384, 10923, 8192, 6554, 5461, 4681, 4096, 3641, 3277, 2979, 2731, - 2521, 2341, 2185, 2048, 1928, 1820, 1725, 1638, 1560, 1489, 1425, 1365, 1311, - 1260, 1214, 1170, 1130, 1092, 1057, 1024, 993, 964, 936, 910, 886, 862, 840, - 819, 799, 780, 762, 745, 728, 712, 697, 683, 669, 655, 643, 630, 618, 607, - 596, 585, 575, 565, 555, 546, 537, 529, 520, 512, 504, 496, 489, 482, 475, - 468, 462, 455, 449, 443, 437, 431, 426, 420, 415, 410, 405, 400, 395, 390, - 386, 381, 377, 372, 368, 364, 360, 356, 352, 349, 345, 341, 338, 334, 331, - 328, 324, 321, 318, 315, 312, 309, 306, 303, 301, 298, 295, 293, 290, 287, - 285, 282, 280, 278, 275, 273, 271, 269, 266, 264, 262, 260, 258, 256, 254, - 252, 250, 248, 246, 245, 243, 241, 239, 237, 236, 234, 232, 231, 229, 228, - 226, 224, 223, 221, 220, 218, 217, 216, 214, 213, 211, 210, 209, 207, 206, - 205, 204, 202, 201, 200, 199, 197, 196, 195, 194, 193, 192, 191, 189, 188, - 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, - 172, 172, 171, 170, 169, 168, 167, 166, 165, 165, 164, 163 -}; - -const int16_t WebRtcNsx_kLogTableFrac[256] = { - 0, 1, 3, 4, 6, 7, 9, 10, 11, 13, 14, 16, 17, 18, 20, 21, - 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, - 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 57, 59, 60, 61, 62, - 63, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, - 82, 84, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 178, 179, 180, 181, 182, 183, 184, 185, 185, 186, 187, - 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, 197, 198, 198, 199, 200, - 201, 202, 203, 203, 204, 205, 206, 207, 208, 208, 209, 210, 211, 212, 212, - 213, 214, 215, 216, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224, - 225, 226, 227, 228, 228, 229, 230, 231, 231, 232, 233, 234, 234, 235, 236, - 237, 238, 238, 239, 240, 241, 241, 242, 243, 244, 244, 245, 246, 247, 247, - 248, 249, 249, 250, 251, 252, 252, 253, 254, 255, 255 -}; - -// Update the noise estimation information. -static void UpdateNoiseEstimateNeon(NoiseSuppressionFixedC* inst, int offset) { - const int16_t kExp2Const = 11819; // Q13 - int16_t* ptr_noiseEstLogQuantile = NULL; - int16_t* ptr_noiseEstQuantile = NULL; - int16x4_t kExp2Const16x4 = vdup_n_s16(kExp2Const); - int32x4_t twentyOne32x4 = vdupq_n_s32(21); - int32x4_t constA32x4 = vdupq_n_s32(0x1fffff); - int32x4_t constB32x4 = vdupq_n_s32(0x200000); - - int16_t tmp16 = WebRtcSpl_MaxValueW16(inst->noiseEstLogQuantile + offset, - inst->magnLen); - - // Guarantee a Q-domain as high as possible and still fit in int16 - inst->qNoise = 14 - (int) WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2Const, - tmp16, - 21); - - int32x4_t qNoise32x4 = vdupq_n_s32(inst->qNoise); - - for (ptr_noiseEstLogQuantile = &inst->noiseEstLogQuantile[offset], - ptr_noiseEstQuantile = &inst->noiseEstQuantile[0]; - ptr_noiseEstQuantile < &inst->noiseEstQuantile[inst->magnLen - 3]; - ptr_noiseEstQuantile += 4, ptr_noiseEstLogQuantile += 4) { - - // tmp32no2 = kExp2Const * inst->noiseEstLogQuantile[offset + i]; - int16x4_t v16x4 = vld1_s16(ptr_noiseEstLogQuantile); - int32x4_t v32x4B = vmull_s16(v16x4, kExp2Const16x4); - - // tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac - int32x4_t v32x4A = vandq_s32(v32x4B, constA32x4); - v32x4A = vorrq_s32(v32x4A, constB32x4); - - // tmp16 = (int16_t)(tmp32no2 >> 21); - v32x4B = vshrq_n_s32(v32x4B, 21); - - // tmp16 -= 21;// shift 21 to get result in Q0 - v32x4B = vsubq_s32(v32x4B, twentyOne32x4); - - // tmp16 += (int16_t) inst->qNoise; - // shift to get result in Q(qNoise) - v32x4B = vaddq_s32(v32x4B, qNoise32x4); - - // if (tmp16 < 0) { - // tmp32no1 >>= -tmp16; - // } else { - // tmp32no1 <<= tmp16; - // } - v32x4B = vshlq_s32(v32x4A, v32x4B); - - // tmp16 = WebRtcSpl_SatW32ToW16(tmp32no1); - v16x4 = vqmovn_s32(v32x4B); - - //inst->noiseEstQuantile[i] = tmp16; - vst1_s16(ptr_noiseEstQuantile, v16x4); - } - - // Last iteration: - - // inst->quantile[i]=exp(inst->lquantile[offset+i]); - // in Q21 - int32_t tmp32no2 = kExp2Const * *ptr_noiseEstLogQuantile; - int32_t tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac - - tmp16 = (int16_t)(tmp32no2 >> 21); - tmp16 -= 21;// shift 21 to get result in Q0 - tmp16 += (int16_t) inst->qNoise; //shift to get result in Q(qNoise) - if (tmp16 < 0) { - tmp32no1 >>= -tmp16; - } else { - tmp32no1 <<= tmp16; - } - *ptr_noiseEstQuantile = WebRtcSpl_SatW32ToW16(tmp32no1); -} - -// Noise Estimation -void WebRtcNsx_NoiseEstimationNeon(NoiseSuppressionFixedC* inst, - uint16_t* magn, - uint32_t* noise, - int16_t* q_noise) { - int16_t lmagn[HALF_ANAL_BLOCKL], counter, countDiv; - int16_t countProd, delta, zeros, frac; - int16_t log2, tabind, logval, tmp16, tmp16no1, tmp16no2; - const int16_t log2_const = 22713; - const int16_t width_factor = 21845; - - size_t i, s, offset; - - tabind = inst->stages - inst->normData; - RTC_DCHECK_LT(tabind, 9); - RTC_DCHECK_GT(tabind, -9); - if (tabind < 0) { - logval = -WebRtcNsx_kLogTable[-tabind]; - } else { - logval = WebRtcNsx_kLogTable[tabind]; - } - - int16x8_t logval_16x8 = vdupq_n_s16(logval); - - // lmagn(i)=log(magn(i))=log(2)*log2(magn(i)) - // magn is in Q(-stages), and the real lmagn values are: - // real_lmagn(i)=log(magn(i)*2^stages)=log(magn(i))+log(2^stages) - // lmagn in Q8 - for (i = 0; i < inst->magnLen; i++) { - if (magn[i]) { - zeros = WebRtcSpl_NormU32((uint32_t)magn[i]); - frac = (int16_t)((((uint32_t)magn[i] << zeros) - & 0x7FFFFFFF) >> 23); - RTC_DCHECK_LT(frac, 256); - // log2(magn(i)) - log2 = (int16_t)(((31 - zeros) << 8) - + WebRtcNsx_kLogTableFrac[frac]); - // log2(magn(i))*log(2) - lmagn[i] = (int16_t)((log2 * log2_const) >> 15); - // + log(2^stages) - lmagn[i] += logval; - } else { - lmagn[i] = logval; - } - } - - int16x4_t Q3_16x4 = vdup_n_s16(3); - int16x8_t WIDTHQ8_16x8 = vdupq_n_s16(WIDTH_Q8); - int16x8_t WIDTHFACTOR_16x8 = vdupq_n_s16(width_factor); - - int16_t factor = FACTOR_Q7; - if (inst->blockIndex < END_STARTUP_LONG) - factor = FACTOR_Q7_STARTUP; - - // Loop over simultaneous estimates - for (s = 0; s < SIMULT; s++) { - offset = s * inst->magnLen; - - // Get counter values from state - counter = inst->noiseEstCounter[s]; - RTC_DCHECK_LT(counter, 201); - countDiv = WebRtcNsx_kCounterDiv[counter]; - countProd = (int16_t)(counter * countDiv); - - // quant_est(...) - int16_t deltaBuff[8]; - int16x4_t tmp16x4_0; - int16x4_t tmp16x4_1; - int16x4_t countDiv_16x4 = vdup_n_s16(countDiv); - int16x8_t countProd_16x8 = vdupq_n_s16(countProd); - int16x8_t tmp16x8_0 = vdupq_n_s16(countDiv); - int16x8_t prod16x8 = vqrdmulhq_s16(WIDTHFACTOR_16x8, tmp16x8_0); - int16x8_t tmp16x8_1; - int16x8_t tmp16x8_2; - int16x8_t tmp16x8_3; - uint16x8_t tmp16x8_4; - int32x4_t tmp32x4; - - for (i = 0; i + 7 < inst->magnLen; i += 8) { - // Compute delta. - // Smaller step size during startup. This prevents from using - // unrealistic values causing overflow. - tmp16x8_0 = vdupq_n_s16(factor); - vst1q_s16(deltaBuff, tmp16x8_0); - - int j; - for (j = 0; j < 8; j++) { - if (inst->noiseEstDensity[offset + i + j] > 512) { - // Get values for deltaBuff by shifting intead of dividing. - int factor = WebRtcSpl_NormW16(inst->noiseEstDensity[offset + i + j]); - deltaBuff[j] = (int16_t)(FACTOR_Q16 >> (14 - factor)); - } - } - - // Update log quantile estimate - - // tmp16 = (int16_t)((delta * countDiv) >> 14); - tmp32x4 = vmull_s16(vld1_s16(&deltaBuff[0]), countDiv_16x4); - tmp16x4_1 = vshrn_n_s32(tmp32x4, 14); - tmp32x4 = vmull_s16(vld1_s16(&deltaBuff[4]), countDiv_16x4); - tmp16x4_0 = vshrn_n_s32(tmp32x4, 14); - tmp16x8_0 = vcombine_s16(tmp16x4_1, tmp16x4_0); // Keep for several lines. - - // prepare for the "if" branch - // tmp16 += 2; - // tmp16_1 = (Word16)(tmp16>>2); - tmp16x8_1 = vrshrq_n_s16(tmp16x8_0, 2); - - // inst->noiseEstLogQuantile[offset+i] + tmp16_1; - tmp16x8_2 = vld1q_s16(&inst->noiseEstLogQuantile[offset + i]); // Keep - tmp16x8_1 = vaddq_s16(tmp16x8_2, tmp16x8_1); // Keep for several lines - - // Prepare for the "else" branch - // tmp16 += 1; - // tmp16_1 = (Word16)(tmp16>>1); - tmp16x8_0 = vrshrq_n_s16(tmp16x8_0, 1); - - // tmp16_2 = (int16_t)((tmp16_1 * 3) >> 1); - tmp32x4 = vmull_s16(vget_low_s16(tmp16x8_0), Q3_16x4); - tmp16x4_1 = vshrn_n_s32(tmp32x4, 1); - - // tmp16_2 = (int16_t)((tmp16_1 * 3) >> 1); - tmp32x4 = vmull_s16(vget_high_s16(tmp16x8_0), Q3_16x4); - tmp16x4_0 = vshrn_n_s32(tmp32x4, 1); - - // inst->noiseEstLogQuantile[offset + i] - tmp16_2; - tmp16x8_0 = vcombine_s16(tmp16x4_1, tmp16x4_0); // keep - tmp16x8_0 = vsubq_s16(tmp16x8_2, tmp16x8_0); - - // logval is the smallest fixed point representation we can have. Values - // below that will correspond to values in the interval [0, 1], which - // can't possibly occur. - tmp16x8_0 = vmaxq_s16(tmp16x8_0, logval_16x8); - - // Do the if-else branches: - tmp16x8_3 = vld1q_s16(&lmagn[i]); // keep for several lines - tmp16x8_4 = vcgtq_s16(tmp16x8_3, tmp16x8_2); - tmp16x8_2 = vbslq_s16(tmp16x8_4, tmp16x8_1, tmp16x8_0); - vst1q_s16(&inst->noiseEstLogQuantile[offset + i], tmp16x8_2); - - // Update density estimate - // tmp16_1 + tmp16_2 - tmp16x8_1 = vld1q_s16(&inst->noiseEstDensity[offset + i]); - tmp16x8_0 = vqrdmulhq_s16(tmp16x8_1, countProd_16x8); - tmp16x8_0 = vaddq_s16(tmp16x8_0, prod16x8); - - // lmagn[i] - inst->noiseEstLogQuantile[offset + i] - tmp16x8_3 = vsubq_s16(tmp16x8_3, tmp16x8_2); - tmp16x8_3 = vabsq_s16(tmp16x8_3); - tmp16x8_4 = vcgtq_s16(WIDTHQ8_16x8, tmp16x8_3); - tmp16x8_1 = vbslq_s16(tmp16x8_4, tmp16x8_0, tmp16x8_1); - vst1q_s16(&inst->noiseEstDensity[offset + i], tmp16x8_1); - } // End loop over magnitude spectrum - - // Last iteration over magnitude spectrum: - // compute delta - if (inst->noiseEstDensity[offset + i] > 512) { - // Get values for deltaBuff by shifting intead of dividing. - int factor = WebRtcSpl_NormW16(inst->noiseEstDensity[offset + i]); - delta = (int16_t)(FACTOR_Q16 >> (14 - factor)); - } else { - delta = FACTOR_Q7; - if (inst->blockIndex < END_STARTUP_LONG) { - // Smaller step size during startup. This prevents from using - // unrealistic values causing overflow. - delta = FACTOR_Q7_STARTUP; - } - } - // update log quantile estimate - tmp16 = (int16_t)((delta * countDiv) >> 14); - if (lmagn[i] > inst->noiseEstLogQuantile[offset + i]) { - // +=QUANTILE*delta/(inst->counter[s]+1) QUANTILE=0.25, =1 in Q2 - // CounterDiv=1/(inst->counter[s]+1) in Q15 - tmp16 += 2; - inst->noiseEstLogQuantile[offset + i] += tmp16 / 4; - } else { - tmp16 += 1; - // *(1-QUANTILE), in Q2 QUANTILE=0.25, 1-0.25=0.75=3 in Q2 - // TODO(bjornv): investigate why we need to truncate twice. - tmp16no2 = (int16_t)((tmp16 / 2) * 3 / 2); - inst->noiseEstLogQuantile[offset + i] -= tmp16no2; - if (inst->noiseEstLogQuantile[offset + i] < logval) { - // logval is the smallest fixed point representation we can have. - // Values below that will correspond to values in the interval - // [0, 1], which can't possibly occur. - inst->noiseEstLogQuantile[offset + i] = logval; - } - } - - // update density estimate - if (WEBRTC_SPL_ABS_W16(lmagn[i] - inst->noiseEstLogQuantile[offset + i]) - < WIDTH_Q8) { - tmp16no1 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( - inst->noiseEstDensity[offset + i], countProd, 15); - tmp16no2 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( - width_factor, countDiv, 15); - inst->noiseEstDensity[offset + i] = tmp16no1 + tmp16no2; - } - - - if (counter >= END_STARTUP_LONG) { - inst->noiseEstCounter[s] = 0; - if (inst->blockIndex >= END_STARTUP_LONG) { - UpdateNoiseEstimateNeon(inst, offset); - } - } - inst->noiseEstCounter[s]++; - - } // end loop over simultaneous estimates - - // Sequentially update the noise during startup - if (inst->blockIndex < END_STARTUP_LONG) { - UpdateNoiseEstimateNeon(inst, offset); - } - - for (i = 0; i < inst->magnLen; i++) { - noise[i] = (uint32_t)(inst->noiseEstQuantile[i]); // Q(qNoise) - } - (*q_noise) = (int16_t)inst->qNoise; -} - -// Filter the data in the frequency domain, and create spectrum. -void WebRtcNsx_PrepareSpectrumNeon(NoiseSuppressionFixedC* inst, - int16_t* freq_buf) { - RTC_DCHECK_EQ(1, inst->magnLen % 8); - RTC_DCHECK_EQ(0, inst->anaLen2 % 16); - - // (1) Filtering. - - // Fixed point C code for the next block is as follows: - // for (i = 0; i < inst->magnLen; i++) { - // inst->real[i] = (int16_t)((inst->real[i] * - // (int16_t)(inst->noiseSupFilter[i])) >> 14); // Q(normData-stages) - // inst->imag[i] = (int16_t)((inst->imag[i] * - // (int16_t)(inst->noiseSupFilter[i])) >> 14); // Q(normData-stages) - // } - - int16_t* preal = &inst->real[0]; - int16_t* pimag = &inst->imag[0]; - int16_t* pns_filter = (int16_t*)&inst->noiseSupFilter[0]; - int16_t* pimag_end = pimag + inst->magnLen - 4; - - while (pimag < pimag_end) { - int16x8_t real = vld1q_s16(preal); - int16x8_t imag = vld1q_s16(pimag); - int16x8_t ns_filter = vld1q_s16(pns_filter); - - int32x4_t tmp_r_0 = vmull_s16(vget_low_s16(real), vget_low_s16(ns_filter)); - int32x4_t tmp_i_0 = vmull_s16(vget_low_s16(imag), vget_low_s16(ns_filter)); - int32x4_t tmp_r_1 = vmull_s16(vget_high_s16(real), - vget_high_s16(ns_filter)); - int32x4_t tmp_i_1 = vmull_s16(vget_high_s16(imag), - vget_high_s16(ns_filter)); - - int16x4_t result_r_0 = vshrn_n_s32(tmp_r_0, 14); - int16x4_t result_i_0 = vshrn_n_s32(tmp_i_0, 14); - int16x4_t result_r_1 = vshrn_n_s32(tmp_r_1, 14); - int16x4_t result_i_1 = vshrn_n_s32(tmp_i_1, 14); - - vst1q_s16(preal, vcombine_s16(result_r_0, result_r_1)); - vst1q_s16(pimag, vcombine_s16(result_i_0, result_i_1)); - preal += 8; - pimag += 8; - pns_filter += 8; - } - - // Filter the last element - *preal = (int16_t)((*preal * *pns_filter) >> 14); - *pimag = (int16_t)((*pimag * *pns_filter) >> 14); - - // (2) Create spectrum. - - // Fixed point C code for the rest of the function is as follows: - // freq_buf[0] = inst->real[0]; - // freq_buf[1] = -inst->imag[0]; - // for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { - // freq_buf[j] = inst->real[i]; - // freq_buf[j + 1] = -inst->imag[i]; - // } - // freq_buf[inst->anaLen] = inst->real[inst->anaLen2]; - // freq_buf[inst->anaLen + 1] = -inst->imag[inst->anaLen2]; - - preal = &inst->real[0]; - pimag = &inst->imag[0]; - pimag_end = pimag + inst->anaLen2; - int16_t * freq_buf_start = freq_buf; - while (pimag < pimag_end) { - // loop unroll - int16x8x2_t real_imag_0; - int16x8x2_t real_imag_1; - real_imag_0.val[1] = vld1q_s16(pimag); - real_imag_0.val[0] = vld1q_s16(preal); - preal += 8; - pimag += 8; - real_imag_1.val[1] = vld1q_s16(pimag); - real_imag_1.val[0] = vld1q_s16(preal); - preal += 8; - pimag += 8; - - real_imag_0.val[1] = vnegq_s16(real_imag_0.val[1]); - real_imag_1.val[1] = vnegq_s16(real_imag_1.val[1]); - vst2q_s16(freq_buf_start, real_imag_0); - freq_buf_start += 16; - vst2q_s16(freq_buf_start, real_imag_1); - freq_buf_start += 16; - } - freq_buf[inst->anaLen] = inst->real[inst->anaLen2]; - freq_buf[inst->anaLen + 1] = -inst->imag[inst->anaLen2]; -} - -// For the noise supress process, synthesis, read out fully processed segment, -// and update synthesis buffer. -void WebRtcNsx_SynthesisUpdateNeon(NoiseSuppressionFixedC* inst, - int16_t* out_frame, - int16_t gain_factor) { - RTC_DCHECK_EQ(0, inst->anaLen % 16); - RTC_DCHECK_EQ(0, inst->blockLen10ms % 16); - - int16_t* preal_start = inst->real; - const int16_t* pwindow = inst->window; - int16_t* preal_end = preal_start + inst->anaLen; - int16_t* psynthesis_buffer = inst->synthesisBuffer; - - while (preal_start < preal_end) { - // Loop unroll. - int16x8_t window_0 = vld1q_s16(pwindow); - int16x8_t real_0 = vld1q_s16(preal_start); - int16x8_t synthesis_buffer_0 = vld1q_s16(psynthesis_buffer); - - int16x8_t window_1 = vld1q_s16(pwindow + 8); - int16x8_t real_1 = vld1q_s16(preal_start + 8); - int16x8_t synthesis_buffer_1 = vld1q_s16(psynthesis_buffer + 8); - - int32x4_t tmp32a_0_low = vmull_s16(vget_low_s16(real_0), - vget_low_s16(window_0)); - int32x4_t tmp32a_0_high = vmull_s16(vget_high_s16(real_0), - vget_high_s16(window_0)); - - int32x4_t tmp32a_1_low = vmull_s16(vget_low_s16(real_1), - vget_low_s16(window_1)); - int32x4_t tmp32a_1_high = vmull_s16(vget_high_s16(real_1), - vget_high_s16(window_1)); - - int16x4_t tmp16a_0_low = vqrshrn_n_s32(tmp32a_0_low, 14); - int16x4_t tmp16a_0_high = vqrshrn_n_s32(tmp32a_0_high, 14); - - int16x4_t tmp16a_1_low = vqrshrn_n_s32(tmp32a_1_low, 14); - int16x4_t tmp16a_1_high = vqrshrn_n_s32(tmp32a_1_high, 14); - - int32x4_t tmp32b_0_low = vmull_n_s16(tmp16a_0_low, gain_factor); - int32x4_t tmp32b_0_high = vmull_n_s16(tmp16a_0_high, gain_factor); - - int32x4_t tmp32b_1_low = vmull_n_s16(tmp16a_1_low, gain_factor); - int32x4_t tmp32b_1_high = vmull_n_s16(tmp16a_1_high, gain_factor); - - int16x4_t tmp16b_0_low = vqrshrn_n_s32(tmp32b_0_low, 13); - int16x4_t tmp16b_0_high = vqrshrn_n_s32(tmp32b_0_high, 13); - - int16x4_t tmp16b_1_low = vqrshrn_n_s32(tmp32b_1_low, 13); - int16x4_t tmp16b_1_high = vqrshrn_n_s32(tmp32b_1_high, 13); - - synthesis_buffer_0 = vqaddq_s16(vcombine_s16(tmp16b_0_low, tmp16b_0_high), - synthesis_buffer_0); - synthesis_buffer_1 = vqaddq_s16(vcombine_s16(tmp16b_1_low, tmp16b_1_high), - synthesis_buffer_1); - vst1q_s16(psynthesis_buffer, synthesis_buffer_0); - vst1q_s16(psynthesis_buffer + 8, synthesis_buffer_1); - - pwindow += 16; - preal_start += 16; - psynthesis_buffer += 16; - } - - // Read out fully processed segment. - int16_t * p_start = inst->synthesisBuffer; - int16_t * p_end = inst->synthesisBuffer + inst->blockLen10ms; - int16_t * p_frame = out_frame; - while (p_start < p_end) { - int16x8_t frame_0 = vld1q_s16(p_start); - vst1q_s16(p_frame, frame_0); - p_start += 8; - p_frame += 8; - } - - // Update synthesis buffer. - int16_t* p_start_src = inst->synthesisBuffer + inst->blockLen10ms; - int16_t* p_end_src = inst->synthesisBuffer + inst->anaLen; - int16_t* p_start_dst = inst->synthesisBuffer; - while (p_start_src < p_end_src) { - int16x8_t frame = vld1q_s16(p_start_src); - vst1q_s16(p_start_dst, frame); - p_start_src += 8; - p_start_dst += 8; - } - - p_start = inst->synthesisBuffer + inst->anaLen - inst->blockLen10ms; - p_end = p_start + inst->blockLen10ms; - int16x8_t zero = vdupq_n_s16(0); - for (;p_start < p_end; p_start += 8) { - vst1q_s16(p_start, zero); - } -} - -// Update analysis buffer for lower band, and window data before FFT. -void WebRtcNsx_AnalysisUpdateNeon(NoiseSuppressionFixedC* inst, - int16_t* out, - int16_t* new_speech) { - RTC_DCHECK_EQ(0, inst->blockLen10ms % 16); - RTC_DCHECK_EQ(0, inst->anaLen % 16); - - // For lower band update analysis buffer. - // memcpy(inst->analysisBuffer, inst->analysisBuffer + inst->blockLen10ms, - // (inst->anaLen - inst->blockLen10ms) * sizeof(*inst->analysisBuffer)); - int16_t* p_start_src = inst->analysisBuffer + inst->blockLen10ms; - int16_t* p_end_src = inst->analysisBuffer + inst->anaLen; - int16_t* p_start_dst = inst->analysisBuffer; - while (p_start_src < p_end_src) { - int16x8_t frame = vld1q_s16(p_start_src); - vst1q_s16(p_start_dst, frame); - - p_start_src += 8; - p_start_dst += 8; - } - - // memcpy(inst->analysisBuffer + inst->anaLen - inst->blockLen10ms, - // new_speech, inst->blockLen10ms * sizeof(*inst->analysisBuffer)); - p_start_src = new_speech; - p_end_src = new_speech + inst->blockLen10ms; - p_start_dst = inst->analysisBuffer + inst->anaLen - inst->blockLen10ms; - while (p_start_src < p_end_src) { - int16x8_t frame = vld1q_s16(p_start_src); - vst1q_s16(p_start_dst, frame); - - p_start_src += 8; - p_start_dst += 8; - } - - // Window data before FFT. - int16_t* p_start_window = (int16_t*) inst->window; - int16_t* p_start_buffer = inst->analysisBuffer; - int16_t* p_end_buffer = inst->analysisBuffer + inst->anaLen; - int16_t* p_start_out = out; - - // Load the first element to reduce pipeline bubble. - int16x8_t window = vld1q_s16(p_start_window); - int16x8_t buffer = vld1q_s16(p_start_buffer); - p_start_window += 8; - p_start_buffer += 8; - - while (p_start_buffer < p_end_buffer) { - // Unroll loop. - int32x4_t tmp32_low = vmull_s16(vget_low_s16(window), vget_low_s16(buffer)); - int32x4_t tmp32_high = vmull_s16(vget_high_s16(window), - vget_high_s16(buffer)); - window = vld1q_s16(p_start_window); - buffer = vld1q_s16(p_start_buffer); - - int16x4_t result_low = vrshrn_n_s32(tmp32_low, 14); - int16x4_t result_high = vrshrn_n_s32(tmp32_high, 14); - vst1q_s16(p_start_out, vcombine_s16(result_low, result_high)); - - p_start_buffer += 8; - p_start_window += 8; - p_start_out += 8; - } - int32x4_t tmp32_low = vmull_s16(vget_low_s16(window), vget_low_s16(buffer)); - int32x4_t tmp32_high = vmull_s16(vget_high_s16(window), - vget_high_s16(buffer)); - - int16x4_t result_low = vrshrn_n_s32(tmp32_low, 14); - int16x4_t result_high = vrshrn_n_s32(tmp32_high, 14); - vst1q_s16(p_start_out, vcombine_s16(result_low, result_high)); -}
diff --git a/modules/audio_processing/legacy_ns/nsx_defines.h b/modules/audio_processing/legacy_ns/nsx_defines.h deleted file mode 100644 index 18db311..0000000 --- a/modules/audio_processing/legacy_ns/nsx_defines.h +++ /dev/null
@@ -1,74 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_DEFINES_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_DEFINES_H_ - -#define ANAL_BLOCKL_MAX 256 /* Max analysis block length */ -#define HALF_ANAL_BLOCKL 129 /* Half max analysis block length + 1 */ -#define NUM_HIGH_BANDS_MAX 2 /* Max number of high bands */ -#define SIMULT 3 -#define END_STARTUP_LONG 200 -#define END_STARTUP_SHORT 50 -#define FACTOR_Q16 2621440 /* 40 in Q16 */ -#define FACTOR_Q7 5120 /* 40 in Q7 */ -#define FACTOR_Q7_STARTUP 1024 /* 8 in Q7 */ -#define WIDTH_Q8 3 /* 0.01 in Q8 (or 25 ) */ - -/* PARAMETERS FOR NEW METHOD */ -#define DD_PR_SNR_Q11 2007 /* ~= Q11(0.98) DD update of prior SNR */ -#define ONE_MINUS_DD_PR_SNR_Q11 41 /* DD update of prior SNR */ -#define SPECT_FLAT_TAVG_Q14 \ - 4915 /* (0.30) tavg parameter for spectral flatness measure */ -#define SPECT_DIFF_TAVG_Q8 \ - 77 /* (0.30) tavg parameter for spectral flatness measure */ -#define PRIOR_UPDATE_Q14 1638 /* Q14(0.1) Update parameter of prior model */ -#define NOISE_UPDATE_Q8 26 /* 26 ~= Q8(0.1) Update parameter for noise */ - -/* Probability threshold for noise state in speech/noise likelihood. */ -#define ONE_MINUS_PROB_RANGE_Q8 205 /* 205 ~= Q8(0.8) */ -#define HIST_PAR_EST 1000 /* Histogram size for estimation of parameters */ - -/* FEATURE EXTRACTION CONFIG */ -/* Bin size of histogram */ -#define BIN_SIZE_LRT 10 -/* Scale parameters: multiply dominant peaks of the histograms by scale factor - * to obtain. */ -/* Thresholds for prior model */ -#define FACTOR_1_LRT_DIFF \ - 6 /* For LRT and spectral difference (5 times bigger) */ -/* For spectral_flatness: used when noise is flatter than speech (10 times - * bigger). */ -#define FACTOR_2_FLAT_Q10 922 -/* Peak limit for spectral flatness (varies between 0 and 1) */ -#define THRES_PEAK_FLAT 24 /* * 2 * BIN_SIZE_FLAT_FX */ -/* Limit on spacing of two highest peaks in histogram: spacing determined by bin - * size. */ -#define LIM_PEAK_SPACE_FLAT_DIFF 4 /* * 2 * BIN_SIZE_DIFF_FX */ -/* Limit on relevance of second peak */ -#define LIM_PEAK_WEIGHT_FLAT_DIFF 2 -#define THRES_FLUCT_LRT \ - 10240 /* = 20 * inst->modelUpdate; fluctuation limit of LRT feat. */ -/* Limit on the max and min values for the feature thresholds */ -#define MAX_FLAT_Q10 38912 /* * 2 * BIN_SIZE_FLAT_FX */ -#define MIN_FLAT_Q10 4096 /* * 2 * BIN_SIZE_FLAT_FX */ -#define MAX_DIFF 100 /* * 2 * BIN_SIZE_DIFF_FX */ -#define MIN_DIFF 16 /* * 2 * BIN_SIZE_DIFF_FX */ -/* Criteria of weight of histogram peak to accept/reject feature */ -#define THRES_WEIGHT_FLAT_DIFF \ - 154 /*(int)(0.3*(inst->modelUpdate)) for flatness and difference */ - -#define STAT_UPDATES 9 /* Update every 512 = 1 << 9 block */ -#define ONE_MINUS_GAMMA_PAUSE_Q8 \ - 13 /* ~= Q8(0.05) Update for conservative noise estimate */ -#define GAMMA_NOISE_TRANS_AND_SPEECH_Q8 \ - 3 /* ~= Q8(0.01) Update for transition and noise region */ - -#endif /* MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_DEFINES_H_ */
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc index 0201983..57c9503 100644 --- a/modules/audio_processing/test/audio_processing_simulator.cc +++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -520,12 +520,6 @@ *settings_.maximum_internal_processing_rate; } - const bool use_legacy_ns = - settings_.use_legacy_ns && *settings_.use_legacy_ns; - if (use_legacy_ns) { - apm_config.noise_suppression.use_legacy_ns = use_legacy_ns; - } - if (settings_.use_ns) { apm_config.noise_suppression.enabled = *settings_.use_ns; }
diff --git a/modules/audio_processing/test/audio_processing_simulator.h b/modules/audio_processing/test/audio_processing_simulator.h index affb644..8ea1772 100644 --- a/modules/audio_processing/test/audio_processing_simulator.h +++ b/modules/audio_processing/test/audio_processing_simulator.h
@@ -61,7 +61,6 @@ absl::optional<bool> use_vad; absl::optional<bool> use_le; absl::optional<bool> use_all; - absl::optional<bool> use_legacy_ns; absl::optional<bool> use_analog_agc_agc2_level_estimator; absl::optional<bool> analog_agc_disable_digital_adaptive; absl::optional<int> agc_mode;
diff --git a/modules/audio_processing/test/audioproc_float_impl.cc b/modules/audio_processing/test/audioproc_float_impl.cc index 0c08349..a37856e 100644 --- a/modules/audio_processing/test/audioproc_float_impl.cc +++ b/modules/audio_processing/test/audioproc_float_impl.cc
@@ -119,10 +119,6 @@ "Activate all of the default components (will be overridden by any " "other settings)"); ABSL_FLAG(int, - use_legacy_ns, - kParameterNotSpecifiedValue, - "Activate (1) or deactivate(0) the legacy NS"); -ABSL_FLAG(int, analog_agc_disable_digital_adaptive, kParameterNotSpecifiedValue, "Force-deactivate (1) digital adaptation in " @@ -381,8 +377,6 @@ &settings.use_analog_agc); SetSettingIfFlagSet(absl::GetFlag(FLAGS_vad), &settings.use_vad); SetSettingIfFlagSet(absl::GetFlag(FLAGS_le), &settings.use_le); - SetSettingIfFlagSet(absl::GetFlag(FLAGS_use_legacy_ns), - &settings.use_legacy_ns); SetSettingIfFlagSet(absl::GetFlag(FLAGS_analog_agc_disable_digital_adaptive), &settings.analog_agc_disable_digital_adaptive); SetSettingIfFlagSet(absl::GetFlag(FLAGS_analog_agc_agc2_level_estimator),
diff --git a/modules/audio_processing/transient/transient_suppressor.cc b/modules/audio_processing/transient/transient_suppressor.cc index b10b055..e09c5f8 100644 --- a/modules/audio_processing/transient/transient_suppressor.cc +++ b/modules/audio_processing/transient/transient_suppressor.cc
@@ -20,9 +20,9 @@ #include "common_audio/include/audio_util.h" #include "common_audio/signal_processing/include/signal_processing_library.h" #include "common_audio/third_party/fft4g/fft4g.h" -#include "modules/audio_processing/legacy_ns/windows_private.h" #include "modules/audio_processing/transient/common.h" #include "modules/audio_processing/transient/transient_detector.h" +#include "modules/audio_processing/transient/windows_private.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h"
diff --git a/modules/audio_processing/legacy_ns/windows_private.h b/modules/audio_processing/transient/windows_private.h similarity index 99% rename from modules/audio_processing/legacy_ns/windows_private.h rename to modules/audio_processing/transient/windows_private.h index 21bb7d4..767bcd8 100644 --- a/modules/audio_processing/legacy_ns/windows_private.h +++ b/modules/audio_processing/transient/windows_private.h
@@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_WINDOWS_PRIVATE_H_ -#define MODULES_AUDIO_PROCESSING_LEGACY_NS_WINDOWS_PRIVATE_H_ +#ifndef MODULES_AUDIO_PROCESSING_TRANSIENT_WINDOWS_PRIVATE_H_ +#define MODULES_AUDIO_PROCESSING_TRANSIENT_WINDOWS_PRIVATE_H_ // Hanning window for 4ms 16kHz static const float kHanning64w128[128] = { @@ -550,4 +550,4 @@ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f}; -#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_WINDOWS_PRIVATE_H_ +#endif // MODULES_AUDIO_PROCESSING_TRANSIENT_WINDOWS_PRIVATE_H_