Reland "Refactoring of the noise suppressor and adding true multichannel support"
This is a reland of 87a7b82520b83a6cf42da27cdc46142c2eb6248c
Original change's description:
> Refactoring of the noise suppressor and adding true multichannel support
>
> This CL adds proper multichannel support to the noise suppressor.
> To accomplish that in a safe way, a full refactoring of the noise
> suppressor code has been done.
>
> Due to floating point precision, the changes made are not entirely
> bitexact. They are, however, very close to being bitexact.
>
> As a safety measure, the former noise suppressor code is preserved
> and a kill-switch is added to allow revering to the legacy noise
> suppressor in case issues arise.
>
> Bug: webrtc:10895, b/143344262
> Change-Id: I0b071011b23265ac12e6d4b3956499d122286657
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158407
> Commit-Queue: Per Åhgren <peah@webrtc.org>
> Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#29646}
Bug: webrtc:10895, b/143344262
Change-Id: I236f1e67bb0baa4e30908a4cf7a8a7bb55fbced3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158747
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29663}
diff --git a/modules/BUILD.gn b/modules/BUILD.gn
index ece91af..4fe4db5 100644
--- a/modules/BUILD.gn
+++ b/modules/BUILD.gn
@@ -229,6 +229,7 @@
"audio_mixer:audio_mixer_unittests",
"audio_processing:audio_processing_unittests",
"audio_processing/aec3:aec3_unittests",
+ "audio_processing/ns:ns_unittests",
"congestion_controller:congestion_controller_unittests",
"pacing:pacing_unittests",
"remote_bitrate_estimator:remote_bitrate_estimator_unittests",
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index f270416..57b49b2 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -132,10 +132,10 @@
"gain_controller2.h",
"include/aec_dump.cc",
"include/aec_dump.h",
+ "legacy_noise_suppression.cc",
+ "legacy_noise_suppression.h",
"level_estimator.cc",
"level_estimator.h",
- "noise_suppression.cc",
- "noise_suppression.h",
"render_queue_item_verifier.h",
"residual_echo_detector.cc",
"residual_echo_detector.h",
@@ -199,6 +199,7 @@
"agc2:adaptive_digital",
"agc2:fixed_digital",
"agc2:gain_applier",
+ "ns",
"vad",
"//third_party/abseil-cpp/absl/types:optional",
]
@@ -287,29 +288,29 @@
rtc_source_set("audio_processing_c") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [
- "ns/windows_private.h",
+ "legacy_ns/windows_private.h",
]
if (rtc_prefer_fixed_point) {
sources += [
- "ns/noise_suppression_x.c",
- "ns/noise_suppression_x.h",
- "ns/nsx_core.c",
- "ns/nsx_core.h",
- "ns/nsx_defines.h",
+ "legacy_ns/noise_suppression_x.c",
+ "legacy_ns/noise_suppression_x.h",
+ "legacy_ns/nsx_core.c",
+ "legacy_ns/nsx_core.h",
+ "legacy_ns/nsx_defines.h",
]
if (current_cpu == "mipsel") {
- sources += [ "ns/nsx_core_mips.c" ]
+ sources += [ "legacy_ns/nsx_core_mips.c" ]
} else {
- sources += [ "ns/nsx_core_c.c" ]
+ sources += [ "legacy_ns/nsx_core_c.c" ]
}
} else {
sources += [
- "ns/defines.h",
- "ns/noise_suppression.c",
- "ns/noise_suppression.h",
- "ns/ns_core.c",
- "ns/ns_core.h",
+ "legacy_ns/defines.h",
+ "legacy_ns/noise_suppression.c",
+ "legacy_ns/noise_suppression.h",
+ "legacy_ns/ns_core.c",
+ "legacy_ns/ns_core.h",
]
}
@@ -324,7 +325,7 @@
]
if (rtc_build_with_neon) {
- sources += [ "ns/nsx_core_neon.c" ]
+ sources += [ "legacy_ns/nsx_core_neon.c" ]
if (current_cpu != "arm64") {
# Enable compilation for the NEON instruction set.
@@ -507,8 +508,8 @@
"echo_detector/normalized_covariance_estimator_unittest.cc",
"gain_control_unittest.cc",
"high_pass_filter_unittest.cc",
+ "legacy_noise_suppression_unittest.cc",
"level_estimator_unittest.cc",
- "noise_suppression_unittest.cc",
"residual_echo_detector_unittest.cc",
"rms_level_unittest.cc",
"test/debug_dump_replayer.cc",
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index f9e7bce..4573aed 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -70,6 +70,11 @@
sample_rate_hz == AudioProcessing::kSampleRate48kHz;
}
+// Checks whether the legacy ns functionality should be enforced.
+bool DetectLegacyNsEnforcement() {
+ return field_trial::IsEnabled("WebRTC-NewNoiseSuppressionKillSwitch");
+}
+
// Identify the native processing rate that best handles a sample rate.
int SuitableProcessRate(int minimum_rate,
int max_splitting_rate,
@@ -306,6 +311,7 @@
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
+ enforced_usage_of_legacy_ns_(DetectLegacyNsEnforcement()),
capture_runtime_settings_(kRuntimeSettingQueueSize),
render_runtime_settings_(kRuntimeSettingQueueSize),
capture_runtime_settings_enqueuer_(&capture_runtime_settings_),
@@ -1303,9 +1309,14 @@
if (submodules_.high_pass_filter) {
submodules_.high_pass_filter->Process(capture_buffer);
}
+
RETURN_ON_ERR(submodules_.gain_control->AnalyzeCaptureAudio(capture_buffer));
+ RTC_DCHECK(
+ !(submodules_.legacy_noise_suppressor && submodules_.noise_suppressor));
if (submodules_.noise_suppressor) {
- submodules_.noise_suppressor->AnalyzeCaptureAudio(capture_buffer);
+ submodules_.noise_suppressor->Analyze(*capture_buffer);
+ } else if (submodules_.legacy_noise_suppressor) {
+ submodules_.legacy_noise_suppressor->AnalyzeCaptureAudio(capture_buffer);
}
if (submodules_.echo_control_mobile) {
@@ -1316,8 +1327,10 @@
}
if (submodules_.noise_suppressor) {
+ submodules_.noise_suppressor->Process(capture_buffer);
+ } else if (submodules_.legacy_noise_suppressor) {
submodules_.echo_control_mobile->CopyLowPassReference(capture_buffer);
- submodules_.noise_suppressor->ProcessCaptureAudio(capture_buffer);
+ submodules_.legacy_noise_suppressor->ProcessCaptureAudio(capture_buffer);
}
RETURN_ON_ERR(submodules_.echo_control_mobile->ProcessCaptureAudio(
@@ -1344,7 +1357,9 @@
}
if (submodules_.noise_suppressor) {
- submodules_.noise_suppressor->ProcessCaptureAudio(capture_buffer);
+ submodules_.noise_suppressor->Process(capture_buffer);
+ } else if (submodules_.legacy_noise_suppressor) {
+ submodules_.legacy_noise_suppressor->ProcessCaptureAudio(capture_buffer);
}
}
@@ -1726,9 +1741,9 @@
return submodule_states_.Update(
config_.high_pass_filter.enabled, !!submodules_.echo_cancellation,
!!submodules_.echo_control_mobile, config_.residual_echo_detector.enabled,
- !!submodules_.noise_suppressor, submodules_.gain_control->is_enabled(),
- config_.gain_controller2.enabled, config_.pre_amplifier.enabled,
- capture_nonlocked_.echo_controller_enabled,
+ !!submodules_.legacy_noise_suppressor || !!submodules_.noise_suppressor,
+ submodules_.gain_control->is_enabled(), config_.gain_controller2.enabled,
+ config_.pre_amplifier.enabled, capture_nonlocked_.echo_controller_enabled,
config_.voice_detection.enabled, capture_.transient_suppressor_enabled);
}
@@ -1868,13 +1883,42 @@
}
void AudioProcessingImpl::InitializeNoiseSuppressor() {
+ submodules_.legacy_noise_suppressor.reset();
+ submodules_.noise_suppressor.reset();
+
if (config_.noise_suppression.enabled) {
- auto ns_level =
- NsConfigLevelToInterfaceLevel(config_.noise_suppression.level);
- submodules_.noise_suppressor = std::make_unique<NoiseSuppression>(
- num_proc_channels(), proc_sample_rate_hz(), ns_level);
- } else {
- submodules_.noise_suppressor.reset();
+ 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 =
+ AudioProcessing::Config::NoiseSuppression;
+ switch (level) {
+ case NoiseSuppresionConfig::kLow:
+ return NsConfig::SuppressionLevel::k6dB;
+ case NoiseSuppresionConfig::kModerate:
+ return NsConfig::SuppressionLevel::k12dB;
+ case NoiseSuppresionConfig::kHigh:
+ return NsConfig::SuppressionLevel::k18dB;
+ case NoiseSuppresionConfig::kVeryHigh:
+ return NsConfig::SuppressionLevel::k21dB;
+ default:
+ RTC_NOTREACHED();
+ }
+ };
+
+ NsConfig cfg;
+ 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 eb1fe7f..3e1b466 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -29,8 +29,9 @@
#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_noise_suppression.h"
#include "modules/audio_processing/level_estimator.h"
-#include "modules/audio_processing/noise_suppression.h"
+#include "modules/audio_processing/ns/noise_suppressor.h"
#include "modules/audio_processing/render_queue_item_verifier.h"
#include "modules/audio_processing/residual_echo_detector.h"
#include "modules/audio_processing/rms_level.h"
@@ -150,6 +151,7 @@
std::unique_ptr<ApmDataDumper> data_dumper_;
static int instance_count_;
+ const bool enforced_usage_of_legacy_ns_;
SwapQueue<RuntimeSetting> capture_runtime_settings_;
SwapQueue<RuntimeSetting> render_runtime_settings_;
@@ -343,7 +345,8 @@
std::unique_ptr<EchoCancellationImpl> echo_cancellation;
std::unique_ptr<EchoControl> echo_controller;
std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
- std::unique_ptr<NoiseSuppression> noise_suppressor;
+ 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;
std::unique_ptr<CustomProcessing> render_pre_processor;
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 1aac2cf..094823d 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -2145,30 +2145,30 @@
std::make_tuple(44100, 16000, 32000, 16000, 19, 20),
std::make_tuple(44100, 16000, 16000, 16000, 19, 0),
- std::make_tuple(32000, 48000, 48000, 48000, 35, 0),
+ std::make_tuple(32000, 48000, 48000, 48000, 28, 0),
std::make_tuple(32000, 48000, 32000, 48000, 65, 30),
- std::make_tuple(32000, 48000, 16000, 48000, 40, 20),
+ std::make_tuple(32000, 48000, 16000, 48000, 30, 20),
std::make_tuple(32000, 44100, 48000, 44100, 20, 20),
std::make_tuple(32000, 44100, 32000, 44100, 20, 15),
std::make_tuple(32000, 44100, 16000, 44100, 20, 15),
- std::make_tuple(32000, 32000, 48000, 32000, 35, 35),
+ std::make_tuple(32000, 32000, 48000, 32000, 29, 35),
std::make_tuple(32000, 32000, 32000, 32000, 0, 0),
- std::make_tuple(32000, 32000, 16000, 32000, 40, 20),
+ std::make_tuple(32000, 32000, 16000, 32000, 32, 20),
std::make_tuple(32000, 16000, 48000, 16000, 20, 20),
std::make_tuple(32000, 16000, 32000, 16000, 20, 20),
std::make_tuple(32000, 16000, 16000, 16000, 20, 0),
- std::make_tuple(16000, 48000, 48000, 48000, 25, 0),
+ std::make_tuple(16000, 48000, 48000, 48000, 24, 0),
std::make_tuple(16000, 48000, 32000, 48000, 25, 30),
std::make_tuple(16000, 48000, 16000, 48000, 25, 20),
std::make_tuple(16000, 44100, 48000, 44100, 15, 20),
std::make_tuple(16000, 44100, 32000, 44100, 15, 15),
std::make_tuple(16000, 44100, 16000, 44100, 15, 15),
- std::make_tuple(16000, 32000, 48000, 32000, 25, 35),
+ std::make_tuple(16000, 32000, 48000, 32000, 24, 35),
std::make_tuple(16000, 32000, 32000, 32000, 25, 0),
std::make_tuple(16000, 32000, 16000, 32000, 25, 20),
- std::make_tuple(16000, 16000, 48000, 16000, 35, 20),
- std::make_tuple(16000, 16000, 32000, 16000, 35, 20),
+ std::make_tuple(16000, 16000, 48000, 16000, 30, 20),
+ std::make_tuple(16000, 16000, 32000, 16000, 30, 20),
std::make_tuple(16000, 16000, 16000, 16000, 0, 0)));
#endif
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index f516015..8c46155 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -285,6 +285,8 @@
bool enabled = false;
enum Level { kLow, kModerate, kHigh, kVeryHigh };
Level level = kModerate;
+ // Recommended not to use. Will be removed in the future.
+ bool use_legacy_ns = false;
} noise_suppression;
// Enables reporting of |voice_detected| in webrtc::AudioProcessingStats.
diff --git a/modules/audio_processing/noise_suppression.cc b/modules/audio_processing/legacy_noise_suppression.cc
similarity index 96%
rename from modules/audio_processing/noise_suppression.cc
rename to modules/audio_processing/legacy_noise_suppression.cc
index b8ddd30..b2c8853 100644
--- a/modules/audio_processing/noise_suppression.cc
+++ b/modules/audio_processing/legacy_noise_suppression.cc
@@ -8,12 +8,12 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "modules/audio_processing/noise_suppression.h"
+#include "modules/audio_processing/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/ns/noise_suppression.h"
+#include "modules/audio_processing/legacy_ns/noise_suppression.h"
#define NS_CREATE WebRtcNs_Create
#define NS_FREE WebRtcNs_Free
@@ -21,7 +21,7 @@
#define NS_SET_POLICY WebRtcNs_set_policy
typedef NsHandle NsState;
#elif defined(WEBRTC_NS_FIXED)
-#include "modules/audio_processing/ns/noise_suppression_x.h"
+#include "modules/audio_processing/legacy_ns/noise_suppression_x.h"
#define NS_CREATE WebRtcNsx_Create
#define NS_FREE WebRtcNsx_Free
diff --git a/modules/audio_processing/noise_suppression.h b/modules/audio_processing/legacy_noise_suppression.h
similarity index 90%
rename from modules/audio_processing/noise_suppression.h
rename to modules/audio_processing/legacy_noise_suppression.h
index df5aed4..c2435db 100644
--- a/modules/audio_processing/noise_suppression.h
+++ b/modules/audio_processing/legacy_noise_suppression.h
@@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_H_
-#define MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_H_
+#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NOISE_SUPPRESSION_H_
+#define MODULES_AUDIO_PROCESSING_LEGACY_NOISE_SUPPRESSION_H_
#include <memory>
#include <vector>
@@ -54,4 +54,4 @@
};
} // namespace webrtc
-#endif // MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_H_
+#endif // MODULES_AUDIO_PROCESSING_LEGACY_NOISE_SUPPRESSION_H_
diff --git a/modules/audio_processing/noise_suppression_unittest.cc b/modules/audio_processing/legacy_noise_suppression_unittest.cc
similarity index 95%
rename from modules/audio_processing/noise_suppression_unittest.cc
rename to modules/audio_processing/legacy_noise_suppression_unittest.cc
index 649fc93..57deedb 100644
--- a/modules/audio_processing/noise_suppression_unittest.cc
+++ b/modules/audio_processing/legacy_noise_suppression_unittest.cc
@@ -11,7 +11,7 @@
#include "api/array_view.h"
#include "modules/audio_processing/audio_buffer.h"
-#include "modules/audio_processing/noise_suppression.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"
@@ -90,7 +90,7 @@
} // namespace
-TEST(NoiseSuppresionBitExactnessTest, Mono8kHzLow) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono8kHzLow) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {1432.341431f, 3321.919922f,
@@ -113,7 +113,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Mono16kHzLow) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzLow) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {2534.461914f, 6277.638672f,
@@ -136,7 +136,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Mono32kHzLow) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono32kHzLow) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {2540.059082f, 6317.822754f,
@@ -159,7 +159,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Mono48kHzLow) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono48kHzLow) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {2135.292480f, 6692.695801f,
@@ -182,7 +182,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Stereo16kHzLow) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Stereo16kHzLow) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {9992.127930f, 12689.569336f,
@@ -208,7 +208,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Mono16kHzModerate) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzModerate) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {2057.085938f, 7601.055176f,
@@ -231,7 +231,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Mono16kHzHigh) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzHigh) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {2095.148193f, 7698.553711f,
@@ -254,7 +254,7 @@
kOutputReference);
}
-TEST(NoiseSuppresionBitExactnessTest, Mono16kHzVeryHigh) {
+TEST(LegacyNoiseSuppresionBitExactnessTest, Mono16kHzVeryHigh) {
#if defined(WEBRTC_ARCH_ARM64)
const float kSpeechProbabilityReference = -4.0f;
const float kNoiseEstimateReference[] = {2677.733398f, 6186.987305f,
diff --git a/modules/audio_processing/legacy_ns/defines.h b/modules/audio_processing/legacy_ns/defines.h
new file mode 100644
index 0000000..02e0318
--- /dev/null
+++ b/modules/audio_processing/legacy_ns/defines.h
@@ -0,0 +1,52 @@
+/*
+ * 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/ns/noise_suppression.c b/modules/audio_processing/legacy_ns/noise_suppression.c
similarity index 91%
rename from modules/audio_processing/ns/noise_suppression.c
rename to modules/audio_processing/legacy_ns/noise_suppression.c
index e21416f..8b95640 100644
--- a/modules/audio_processing/ns/noise_suppression.c
+++ b/modules/audio_processing/legacy_ns/noise_suppression.c
@@ -8,14 +8,14 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "modules/audio_processing/ns/noise_suppression.h"
+#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/ns/defines.h"
-#include "modules/audio_processing/ns/ns_core.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));
diff --git a/modules/audio_processing/ns/noise_suppression.h b/modules/audio_processing/legacy_ns/noise_suppression.h
similarity index 94%
rename from modules/audio_processing/ns/noise_suppression.h
rename to modules/audio_processing/legacy_ns/noise_suppression.h
index 0775ffa..01f04cc 100644
--- a/modules/audio_processing/ns/noise_suppression.h
+++ b/modules/audio_processing/legacy_ns/noise_suppression.h
@@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_
-#define MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_
+#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_H_
+#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_H_
#include <stddef.h>
#include <stdint.h>
@@ -131,4 +131,4 @@
}
#endif
-#endif // MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_
+#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_H_
diff --git a/modules/audio_processing/ns/noise_suppression_x.c b/modules/audio_processing/legacy_ns/noise_suppression_x.c
similarity index 85%
rename from modules/audio_processing/ns/noise_suppression_x.c
rename to modules/audio_processing/legacy_ns/noise_suppression_x.c
index c6faf75..faa866e 100644
--- a/modules/audio_processing/ns/noise_suppression_x.c
+++ b/modules/audio_processing/legacy_ns/noise_suppression_x.c
@@ -8,13 +8,13 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "modules/audio_processing/ns/noise_suppression_x.h"
+#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/ns/nsx_core.h"
-#include "modules/audio_processing/ns/nsx_defines.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));
@@ -37,9 +37,9 @@
}
void WebRtcNsx_Process(NsxHandle* nsxInst,
- const short* const* speechFrame,
+ const int16_t* const* speechFrame,
int num_bands,
- short* const* outFrame) {
+ int16_t* const* outFrame) {
WebRtcNsx_ProcessCore((NoiseSuppressionFixedC*)nsxInst, speechFrame,
num_bands, outFrame);
}
diff --git a/modules/audio_processing/ns/noise_suppression_x.h b/modules/audio_processing/legacy_ns/noise_suppression_x.h
similarity index 90%
rename from modules/audio_processing/ns/noise_suppression_x.h
rename to modules/audio_processing/legacy_ns/noise_suppression_x.h
index 972784e..572db41 100644
--- a/modules/audio_processing/ns/noise_suppression_x.h
+++ b/modules/audio_processing/legacy_ns/noise_suppression_x.h
@@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_X_H_
-#define MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_X_H_
+#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>
@@ -78,9 +78,9 @@
* - outFrame : Pointer to output frame for each band
*/
void WebRtcNsx_Process(NsxHandle* nsxInst,
- const short* const* speechFrame,
+ const int16_t* const* speechFrame,
int num_bands,
- short* const* outFrame);
+ 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().
@@ -109,4 +109,4 @@
}
#endif
-#endif // MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_X_H_
+#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NOISE_SUPPRESSION_X_H_
diff --git a/modules/audio_processing/ns/ns_core.c b/modules/audio_processing/legacy_ns/ns_core.c
similarity index 99%
rename from modules/audio_processing/ns/ns_core.c
rename to modules/audio_processing/legacy_ns/ns_core.c
index bc5dd6d..b5dc829 100644
--- a/modules/audio_processing/ns/ns_core.c
+++ b/modules/audio_processing/legacy_ns/ns_core.c
@@ -15,9 +15,9 @@
#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/ns/noise_suppression.h"
-#include "modules/audio_processing/ns/ns_core.h"
-#include "modules/audio_processing/ns/windows_private.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) {
diff --git a/modules/audio_processing/ns/ns_core.h b/modules/audio_processing/legacy_ns/ns_core.h
similarity index 96%
rename from modules/audio_processing/ns/ns_core.h
rename to modules/audio_processing/legacy_ns/ns_core.h
index e90b8ce..7a3b0a4 100644
--- a/modules/audio_processing/ns/ns_core.h
+++ b/modules/audio_processing/legacy_ns/ns_core.h
@@ -8,10 +8,10 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef MODULES_AUDIO_PROCESSING_NS_NS_CORE_H_
-#define MODULES_AUDIO_PROCESSING_NS_NS_CORE_H_
+#ifndef MODULES_AUDIO_PROCESSING_LEGACY_NS_NS_CORE_H_
+#define MODULES_AUDIO_PROCESSING_LEGACY_NS_NS_CORE_H_
-#include "modules/audio_processing/ns/defines.h"
+#include "modules/audio_processing/legacy_ns/defines.h"
typedef struct NSParaExtract_ {
// Bin size of histogram.
@@ -46,7 +46,6 @@
// Criteria of weight of histogram peak to accept/reject feature.
int thresWeightSpecFlat;
int thresWeightSpecDiff;
-
} NSParaExtract;
typedef struct NoiseSuppressionC_ {
@@ -186,4 +185,4 @@
#ifdef __cplusplus
}
#endif
-#endif // MODULES_AUDIO_PROCESSING_NS_NS_CORE_H_
+#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
new file mode 100644
index 0000000..aa1e73b
--- /dev/null
+++ b/modules/audio_processing/legacy_ns/nsx_core.c
@@ -0,0 +1,2154 @@
+/*
+ * 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/ns/nsx_core.h b/modules/audio_processing/legacy_ns/nsx_core.h
similarity index 95%
rename from modules/audio_processing/ns/nsx_core.h
rename to modules/audio_processing/legacy_ns/nsx_core.h
index 9e9d142..a3f224a 100644
--- a/modules/audio_processing/ns/nsx_core.h
+++ b/modules/audio_processing/legacy_ns/nsx_core.h
@@ -8,15 +8,15 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_CORE_H_
-#define MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_CORE_H_
+#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/ns/nsx_defines.h"
+#include "modules/audio_processing/legacy_ns/nsx_defines.h"
typedef struct NoiseSuppressionFixedC_ {
uint32_t fs;
@@ -161,9 +161,9 @@
* - outFrame : Output speech frame for each band
*/
void WebRtcNsx_ProcessCore(NoiseSuppressionFixedC* inst,
- const short* const* inFrame,
+ const int16_t* const* inFrame,
int num_bands,
- short* const* outFrame);
+ int16_t* const* outFrame);
/****************************************************************************
* Some function pointers, for internal functions shared by ARM NEON and
@@ -258,4 +258,4 @@
}
#endif
-#endif // MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_CORE_H_
+#endif // MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_CORE_H_
diff --git a/modules/audio_processing/ns/nsx_core_c.c b/modules/audio_processing/legacy_ns/nsx_core_c.c
similarity index 97%
rename from modules/audio_processing/ns/nsx_core_c.c
rename to modules/audio_processing/legacy_ns/nsx_core_c.c
index 162fb19..2b0bb2f 100644
--- a/modules/audio_processing/ns/nsx_core_c.c
+++ b/modules/audio_processing/legacy_ns/nsx_core_c.c
@@ -9,9 +9,9 @@
*/
#include "rtc_base/checks.h"
-#include "modules/audio_processing/ns/noise_suppression_x.h"
-#include "modules/audio_processing/ns/nsx_core.h"
-#include "modules/audio_processing/ns/nsx_defines.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,
@@ -257,4 +257,3 @@
}
}
}
-
diff --git a/modules/audio_processing/ns/nsx_core_mips.c b/modules/audio_processing/legacy_ns/nsx_core_mips.c
similarity index 99%
rename from modules/audio_processing/ns/nsx_core_mips.c
rename to modules/audio_processing/legacy_ns/nsx_core_mips.c
index d58a9b2..af4c287 100644
--- a/modules/audio_processing/ns/nsx_core_mips.c
+++ b/modules/audio_processing/legacy_ns/nsx_core_mips.c
@@ -11,8 +11,8 @@
#include <string.h>
#include "rtc_base/checks.h"
-#include "modules/audio_processing/ns/noise_suppression_x.h"
-#include "modules/audio_processing/ns/nsx_core.h"
+#include "modules/audio_processing/legacy_ns/noise_suppression_x.h"
+#include "modules/audio_processing/legacy_ns/nsx_core.h"
static const int16_t kIndicatorTable[17] = {
0, 2017, 3809, 5227, 6258, 6963, 7424, 7718,
@@ -999,4 +999,3 @@
: "memory"
);
}
-
diff --git a/modules/audio_processing/ns/nsx_core_neon.c b/modules/audio_processing/legacy_ns/nsx_core_neon.c
similarity index 99%
rename from modules/audio_processing/ns/nsx_core_neon.c
rename to modules/audio_processing/legacy_ns/nsx_core_neon.c
index 64ce99c..244111c 100644
--- a/modules/audio_processing/ns/nsx_core_neon.c
+++ b/modules/audio_processing/legacy_ns/nsx_core_neon.c
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "modules/audio_processing/ns/nsx_core.h"
+#include "modules/audio_processing/legacy_ns/nsx_core.h"
#include <arm_neon.h>
diff --git a/modules/audio_processing/ns/nsx_defines.h b/modules/audio_processing/legacy_ns/nsx_defines.h
similarity index 94%
rename from modules/audio_processing/ns/nsx_defines.h
rename to modules/audio_processing/legacy_ns/nsx_defines.h
index dc14dbc..18db311 100644
--- a/modules/audio_processing/ns/nsx_defines.h
+++ b/modules/audio_processing/legacy_ns/nsx_defines.h
@@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#ifndef MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_
-#define MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_
+#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 */
@@ -71,4 +71,4 @@
#define GAMMA_NOISE_TRANS_AND_SPEECH_Q8 \
3 /* ~= Q8(0.01) Update for transition and noise region */
-#endif /* MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_NSX_DEFINES_H_ */
+#endif /* MODULES_AUDIO_PROCESSING_LEGACY_NS_NSX_DEFINES_H_ */
diff --git a/modules/audio_processing/legacy_ns/windows_private.h b/modules/audio_processing/legacy_ns/windows_private.h
new file mode 100644
index 0000000..21bb7d4
--- /dev/null
+++ b/modules/audio_processing/legacy_ns/windows_private.h
@@ -0,0 +1,553 @@
+/*
+ * 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_WINDOWS_PRIVATE_H_
+#define MODULES_AUDIO_PROCESSING_LEGACY_NS_WINDOWS_PRIVATE_H_
+
+// Hanning window for 4ms 16kHz
+static const float kHanning64w128[128] = {
+ 0.00000000000000f, 0.02454122852291f, 0.04906767432742f, 0.07356456359967f,
+ 0.09801714032956f, 0.12241067519922f, 0.14673047445536f, 0.17096188876030f,
+ 0.19509032201613f, 0.21910124015687f, 0.24298017990326f, 0.26671275747490f,
+ 0.29028467725446f, 0.31368174039889f, 0.33688985339222f, 0.35989503653499f,
+ 0.38268343236509f, 0.40524131400499f, 0.42755509343028f, 0.44961132965461f,
+ 0.47139673682600f, 0.49289819222978f, 0.51410274419322f, 0.53499761988710f,
+ 0.55557023301960f, 0.57580819141785f, 0.59569930449243f, 0.61523159058063f,
+ 0.63439328416365f, 0.65317284295378f, 0.67155895484702f, 0.68954054473707f,
+ 0.70710678118655f, 0.72424708295147f, 0.74095112535496f, 0.75720884650648f,
+ 0.77301045336274f, 0.78834642762661f, 0.80320753148064f, 0.81758481315158f,
+ 0.83146961230255f, 0.84485356524971f, 0.85772861000027f, 0.87008699110871f,
+ 0.88192126434835f, 0.89322430119552f, 0.90398929312344f, 0.91420975570353f,
+ 0.92387953251129f, 0.93299279883474f, 0.94154406518302f, 0.94952818059304f,
+ 0.95694033573221f, 0.96377606579544f, 0.97003125319454f, 0.97570213003853f,
+ 0.98078528040323f, 0.98527764238894f, 0.98917650996478f, 0.99247953459871f,
+ 0.99518472667220f, 0.99729045667869f, 0.99879545620517f, 0.99969881869620f,
+ 1.00000000000000f, 0.99969881869620f, 0.99879545620517f, 0.99729045667869f,
+ 0.99518472667220f, 0.99247953459871f, 0.98917650996478f, 0.98527764238894f,
+ 0.98078528040323f, 0.97570213003853f, 0.97003125319454f, 0.96377606579544f,
+ 0.95694033573221f, 0.94952818059304f, 0.94154406518302f, 0.93299279883474f,
+ 0.92387953251129f, 0.91420975570353f, 0.90398929312344f, 0.89322430119552f,
+ 0.88192126434835f, 0.87008699110871f, 0.85772861000027f, 0.84485356524971f,
+ 0.83146961230255f, 0.81758481315158f, 0.80320753148064f, 0.78834642762661f,
+ 0.77301045336274f, 0.75720884650648f, 0.74095112535496f, 0.72424708295147f,
+ 0.70710678118655f, 0.68954054473707f, 0.67155895484702f, 0.65317284295378f,
+ 0.63439328416365f, 0.61523159058063f, 0.59569930449243f, 0.57580819141785f,
+ 0.55557023301960f, 0.53499761988710f, 0.51410274419322f, 0.49289819222978f,
+ 0.47139673682600f, 0.44961132965461f, 0.42755509343028f, 0.40524131400499f,
+ 0.38268343236509f, 0.35989503653499f, 0.33688985339222f, 0.31368174039889f,
+ 0.29028467725446f, 0.26671275747490f, 0.24298017990326f, 0.21910124015687f,
+ 0.19509032201613f, 0.17096188876030f, 0.14673047445536f, 0.12241067519922f,
+ 0.09801714032956f, 0.07356456359967f, 0.04906767432742f, 0.02454122852291f};
+
+// hybrib Hanning & flat window
+static const float kBlocks80w128[128] = {
+ 0.00000000f, 0.03271908f, 0.06540313f, 0.09801714f, 0.13052619f,
+ 0.16289547f, 0.19509032f, 0.22707626f, 0.25881905f, 0.29028468f,
+ 0.32143947f, 0.35225005f, 0.38268343f, 0.41270703f, 0.44228869f,
+ 0.47139674f, 0.50000000f, 0.52806785f, 0.55557023f, 0.58247770f,
+ 0.60876143f, 0.63439328f, 0.65934582f, 0.68359230f, 0.70710678f,
+ 0.72986407f, 0.75183981f, 0.77301045f, 0.79335334f, 0.81284668f,
+ 0.83146961f, 0.84920218f, 0.86602540f, 0.88192126f, 0.89687274f,
+ 0.91086382f, 0.92387953f, 0.93590593f, 0.94693013f, 0.95694034f,
+ 0.96592583f, 0.97387698f, 0.98078528f, 0.98664333f, 0.99144486f,
+ 0.99518473f, 0.99785892f, 0.99946459f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 0.99946459f, 0.99785892f, 0.99518473f, 0.99144486f,
+ 0.98664333f, 0.98078528f, 0.97387698f, 0.96592583f, 0.95694034f,
+ 0.94693013f, 0.93590593f, 0.92387953f, 0.91086382f, 0.89687274f,
+ 0.88192126f, 0.86602540f, 0.84920218f, 0.83146961f, 0.81284668f,
+ 0.79335334f, 0.77301045f, 0.75183981f, 0.72986407f, 0.70710678f,
+ 0.68359230f, 0.65934582f, 0.63439328f, 0.60876143f, 0.58247770f,
+ 0.55557023f, 0.52806785f, 0.50000000f, 0.47139674f, 0.44228869f,
+ 0.41270703f, 0.38268343f, 0.35225005f, 0.32143947f, 0.29028468f,
+ 0.25881905f, 0.22707626f, 0.19509032f, 0.16289547f, 0.13052619f,
+ 0.09801714f, 0.06540313f, 0.03271908f};
+
+// hybrib Hanning & flat window
+static const float kBlocks160w256[256] = {
+ 0.00000000f, 0.01636173f, 0.03271908f, 0.04906767f, 0.06540313f,
+ 0.08172107f, 0.09801714f, 0.11428696f, 0.13052619f, 0.14673047f,
+ 0.16289547f, 0.17901686f, 0.19509032f, 0.21111155f, 0.22707626f,
+ 0.24298018f, 0.25881905f, 0.27458862f, 0.29028468f, 0.30590302f,
+ 0.32143947f, 0.33688985f, 0.35225005f, 0.36751594f, 0.38268343f,
+ 0.39774847f, 0.41270703f, 0.42755509f, 0.44228869f, 0.45690388f,
+ 0.47139674f, 0.48576339f, 0.50000000f, 0.51410274f, 0.52806785f,
+ 0.54189158f, 0.55557023f, 0.56910015f, 0.58247770f, 0.59569930f,
+ 0.60876143f, 0.62166057f, 0.63439328f, 0.64695615f, 0.65934582f,
+ 0.67155895f, 0.68359230f, 0.69544264f, 0.70710678f, 0.71858162f,
+ 0.72986407f, 0.74095113f, 0.75183981f, 0.76252720f, 0.77301045f,
+ 0.78328675f, 0.79335334f, 0.80320753f, 0.81284668f, 0.82226822f,
+ 0.83146961f, 0.84044840f, 0.84920218f, 0.85772861f, 0.86602540f,
+ 0.87409034f, 0.88192126f, 0.88951608f, 0.89687274f, 0.90398929f,
+ 0.91086382f, 0.91749450f, 0.92387953f, 0.93001722f, 0.93590593f,
+ 0.94154407f, 0.94693013f, 0.95206268f, 0.95694034f, 0.96156180f,
+ 0.96592583f, 0.97003125f, 0.97387698f, 0.97746197f, 0.98078528f,
+ 0.98384601f, 0.98664333f, 0.98917651f, 0.99144486f, 0.99344778f,
+ 0.99518473f, 0.99665524f, 0.99785892f, 0.99879546f, 0.99946459f,
+ 0.99986614f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 0.99986614f, 0.99946459f, 0.99879546f, 0.99785892f,
+ 0.99665524f, 0.99518473f, 0.99344778f, 0.99144486f, 0.98917651f,
+ 0.98664333f, 0.98384601f, 0.98078528f, 0.97746197f, 0.97387698f,
+ 0.97003125f, 0.96592583f, 0.96156180f, 0.95694034f, 0.95206268f,
+ 0.94693013f, 0.94154407f, 0.93590593f, 0.93001722f, 0.92387953f,
+ 0.91749450f, 0.91086382f, 0.90398929f, 0.89687274f, 0.88951608f,
+ 0.88192126f, 0.87409034f, 0.86602540f, 0.85772861f, 0.84920218f,
+ 0.84044840f, 0.83146961f, 0.82226822f, 0.81284668f, 0.80320753f,
+ 0.79335334f, 0.78328675f, 0.77301045f, 0.76252720f, 0.75183981f,
+ 0.74095113f, 0.72986407f, 0.71858162f, 0.70710678f, 0.69544264f,
+ 0.68359230f, 0.67155895f, 0.65934582f, 0.64695615f, 0.63439328f,
+ 0.62166057f, 0.60876143f, 0.59569930f, 0.58247770f, 0.56910015f,
+ 0.55557023f, 0.54189158f, 0.52806785f, 0.51410274f, 0.50000000f,
+ 0.48576339f, 0.47139674f, 0.45690388f, 0.44228869f, 0.42755509f,
+ 0.41270703f, 0.39774847f, 0.38268343f, 0.36751594f, 0.35225005f,
+ 0.33688985f, 0.32143947f, 0.30590302f, 0.29028468f, 0.27458862f,
+ 0.25881905f, 0.24298018f, 0.22707626f, 0.21111155f, 0.19509032f,
+ 0.17901686f, 0.16289547f, 0.14673047f, 0.13052619f, 0.11428696f,
+ 0.09801714f, 0.08172107f, 0.06540313f, 0.04906767f, 0.03271908f,
+ 0.01636173f};
+
+// hybrib Hanning & flat window: for 20ms
+static const float kBlocks320w512[512] = {
+ 0.00000000f, 0.00818114f, 0.01636173f, 0.02454123f, 0.03271908f,
+ 0.04089475f, 0.04906767f, 0.05723732f, 0.06540313f, 0.07356456f,
+ 0.08172107f, 0.08987211f, 0.09801714f, 0.10615561f, 0.11428696f,
+ 0.12241068f, 0.13052619f, 0.13863297f, 0.14673047f, 0.15481816f,
+ 0.16289547f, 0.17096189f, 0.17901686f, 0.18705985f, 0.19509032f,
+ 0.20310773f, 0.21111155f, 0.21910124f, 0.22707626f, 0.23503609f,
+ 0.24298018f, 0.25090801f, 0.25881905f, 0.26671276f, 0.27458862f,
+ 0.28244610f, 0.29028468f, 0.29810383f, 0.30590302f, 0.31368174f,
+ 0.32143947f, 0.32917568f, 0.33688985f, 0.34458148f, 0.35225005f,
+ 0.35989504f, 0.36751594f, 0.37511224f, 0.38268343f, 0.39022901f,
+ 0.39774847f, 0.40524131f, 0.41270703f, 0.42014512f, 0.42755509f,
+ 0.43493645f, 0.44228869f, 0.44961133f, 0.45690388f, 0.46416584f,
+ 0.47139674f, 0.47859608f, 0.48576339f, 0.49289819f, 0.50000000f,
+ 0.50706834f, 0.51410274f, 0.52110274f, 0.52806785f, 0.53499762f,
+ 0.54189158f, 0.54874927f, 0.55557023f, 0.56235401f, 0.56910015f,
+ 0.57580819f, 0.58247770f, 0.58910822f, 0.59569930f, 0.60225052f,
+ 0.60876143f, 0.61523159f, 0.62166057f, 0.62804795f, 0.63439328f,
+ 0.64069616f, 0.64695615f, 0.65317284f, 0.65934582f, 0.66547466f,
+ 0.67155895f, 0.67759830f, 0.68359230f, 0.68954054f, 0.69544264f,
+ 0.70129818f, 0.70710678f, 0.71286806f, 0.71858162f, 0.72424708f,
+ 0.72986407f, 0.73543221f, 0.74095113f, 0.74642045f, 0.75183981f,
+ 0.75720885f, 0.76252720f, 0.76779452f, 0.77301045f, 0.77817464f,
+ 0.78328675f, 0.78834643f, 0.79335334f, 0.79830715f, 0.80320753f,
+ 0.80805415f, 0.81284668f, 0.81758481f, 0.82226822f, 0.82689659f,
+ 0.83146961f, 0.83598698f, 0.84044840f, 0.84485357f, 0.84920218f,
+ 0.85349396f, 0.85772861f, 0.86190585f, 0.86602540f, 0.87008699f,
+ 0.87409034f, 0.87803519f, 0.88192126f, 0.88574831f, 0.88951608f,
+ 0.89322430f, 0.89687274f, 0.90046115f, 0.90398929f, 0.90745693f,
+ 0.91086382f, 0.91420976f, 0.91749450f, 0.92071783f, 0.92387953f,
+ 0.92697940f, 0.93001722f, 0.93299280f, 0.93590593f, 0.93875641f,
+ 0.94154407f, 0.94426870f, 0.94693013f, 0.94952818f, 0.95206268f,
+ 0.95453345f, 0.95694034f, 0.95928317f, 0.96156180f, 0.96377607f,
+ 0.96592583f, 0.96801094f, 0.97003125f, 0.97198664f, 0.97387698f,
+ 0.97570213f, 0.97746197f, 0.97915640f, 0.98078528f, 0.98234852f,
+ 0.98384601f, 0.98527764f, 0.98664333f, 0.98794298f, 0.98917651f,
+ 0.99034383f, 0.99144486f, 0.99247953f, 0.99344778f, 0.99434953f,
+ 0.99518473f, 0.99595331f, 0.99665524f, 0.99729046f, 0.99785892f,
+ 0.99836060f, 0.99879546f, 0.99916346f, 0.99946459f, 0.99969882f,
+ 0.99986614f, 0.99996653f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
+ 1.00000000f, 0.99996653f, 0.99986614f, 0.99969882f, 0.99946459f,
+ 0.99916346f, 0.99879546f, 0.99836060f, 0.99785892f, 0.99729046f,
+ 0.99665524f, 0.99595331f, 0.99518473f, 0.99434953f, 0.99344778f,
+ 0.99247953f, 0.99144486f, 0.99034383f, 0.98917651f, 0.98794298f,
+ 0.98664333f, 0.98527764f, 0.98384601f, 0.98234852f, 0.98078528f,
+ 0.97915640f, 0.97746197f, 0.97570213f, 0.97387698f, 0.97198664f,
+ 0.97003125f, 0.96801094f, 0.96592583f, 0.96377607f, 0.96156180f,
+ 0.95928317f, 0.95694034f, 0.95453345f, 0.95206268f, 0.94952818f,
+ 0.94693013f, 0.94426870f, 0.94154407f, 0.93875641f, 0.93590593f,
+ 0.93299280f, 0.93001722f, 0.92697940f, 0.92387953f, 0.92071783f,
+ 0.91749450f, 0.91420976f, 0.91086382f, 0.90745693f, 0.90398929f,
+ 0.90046115f, 0.89687274f, 0.89322430f, 0.88951608f, 0.88574831f,
+ 0.88192126f, 0.87803519f, 0.87409034f, 0.87008699f, 0.86602540f,
+ 0.86190585f, 0.85772861f, 0.85349396f, 0.84920218f, 0.84485357f,
+ 0.84044840f, 0.83598698f, 0.83146961f, 0.82689659f, 0.82226822f,
+ 0.81758481f, 0.81284668f, 0.80805415f, 0.80320753f, 0.79830715f,
+ 0.79335334f, 0.78834643f, 0.78328675f, 0.77817464f, 0.77301045f,
+ 0.76779452f, 0.76252720f, 0.75720885f, 0.75183981f, 0.74642045f,
+ 0.74095113f, 0.73543221f, 0.72986407f, 0.72424708f, 0.71858162f,
+ 0.71286806f, 0.70710678f, 0.70129818f, 0.69544264f, 0.68954054f,
+ 0.68359230f, 0.67759830f, 0.67155895f, 0.66547466f, 0.65934582f,
+ 0.65317284f, 0.64695615f, 0.64069616f, 0.63439328f, 0.62804795f,
+ 0.62166057f, 0.61523159f, 0.60876143f, 0.60225052f, 0.59569930f,
+ 0.58910822f, 0.58247770f, 0.57580819f, 0.56910015f, 0.56235401f,
+ 0.55557023f, 0.54874927f, 0.54189158f, 0.53499762f, 0.52806785f,
+ 0.52110274f, 0.51410274f, 0.50706834f, 0.50000000f, 0.49289819f,
+ 0.48576339f, 0.47859608f, 0.47139674f, 0.46416584f, 0.45690388f,
+ 0.44961133f, 0.44228869f, 0.43493645f, 0.42755509f, 0.42014512f,
+ 0.41270703f, 0.40524131f, 0.39774847f, 0.39022901f, 0.38268343f,
+ 0.37511224f, 0.36751594f, 0.35989504f, 0.35225005f, 0.34458148f,
+ 0.33688985f, 0.32917568f, 0.32143947f, 0.31368174f, 0.30590302f,
+ 0.29810383f, 0.29028468f, 0.28244610f, 0.27458862f, 0.26671276f,
+ 0.25881905f, 0.25090801f, 0.24298018f, 0.23503609f, 0.22707626f,
+ 0.21910124f, 0.21111155f, 0.20310773f, 0.19509032f, 0.18705985f,
+ 0.17901686f, 0.17096189f, 0.16289547f, 0.15481816f, 0.14673047f,
+ 0.13863297f, 0.13052619f, 0.12241068f, 0.11428696f, 0.10615561f,
+ 0.09801714f, 0.08987211f, 0.08172107f, 0.07356456f, 0.06540313f,
+ 0.05723732f, 0.04906767f, 0.04089475f, 0.03271908f, 0.02454123f,
+ 0.01636173f, 0.00818114f};
+
+// Hanning window: for 15ms at 16kHz with symmetric zeros
+static const float kBlocks240w512[512] = {
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00654494f, 0.01308960f, 0.01963369f,
+ 0.02617695f, 0.03271908f, 0.03925982f, 0.04579887f, 0.05233596f,
+ 0.05887080f, 0.06540313f, 0.07193266f, 0.07845910f, 0.08498218f,
+ 0.09150162f, 0.09801714f, 0.10452846f, 0.11103531f, 0.11753740f,
+ 0.12403446f, 0.13052620f, 0.13701233f, 0.14349262f, 0.14996676f,
+ 0.15643448f, 0.16289547f, 0.16934951f, 0.17579629f, 0.18223552f,
+ 0.18866697f, 0.19509032f, 0.20150533f, 0.20791170f, 0.21430916f,
+ 0.22069745f, 0.22707628f, 0.23344538f, 0.23980446f, 0.24615330f,
+ 0.25249159f, 0.25881904f, 0.26513544f, 0.27144045f, 0.27773386f,
+ 0.28401536f, 0.29028466f, 0.29654160f, 0.30278578f, 0.30901700f,
+ 0.31523499f, 0.32143945f, 0.32763019f, 0.33380687f, 0.33996925f,
+ 0.34611708f, 0.35225007f, 0.35836795f, 0.36447051f, 0.37055743f,
+ 0.37662852f, 0.38268346f, 0.38872197f, 0.39474389f, 0.40074885f,
+ 0.40673664f, 0.41270703f, 0.41865975f, 0.42459452f, 0.43051112f,
+ 0.43640924f, 0.44228873f, 0.44814920f, 0.45399052f, 0.45981237f,
+ 0.46561453f, 0.47139674f, 0.47715878f, 0.48290035f, 0.48862126f,
+ 0.49432120f, 0.50000000f, 0.50565743f, 0.51129311f, 0.51690692f,
+ 0.52249855f, 0.52806789f, 0.53361452f, 0.53913832f, 0.54463905f,
+ 0.55011642f, 0.55557024f, 0.56100029f, 0.56640625f, 0.57178795f,
+ 0.57714522f, 0.58247769f, 0.58778524f, 0.59306765f, 0.59832460f,
+ 0.60355598f, 0.60876143f, 0.61394083f, 0.61909395f, 0.62422055f,
+ 0.62932038f, 0.63439333f, 0.63943899f, 0.64445734f, 0.64944810f,
+ 0.65441096f, 0.65934587f, 0.66425246f, 0.66913062f, 0.67398012f,
+ 0.67880076f, 0.68359232f, 0.68835455f, 0.69308740f, 0.69779050f,
+ 0.70246369f, 0.70710677f, 0.71171963f, 0.71630198f, 0.72085363f,
+ 0.72537440f, 0.72986406f, 0.73432255f, 0.73874950f, 0.74314487f,
+ 0.74750835f, 0.75183982f, 0.75613910f, 0.76040596f, 0.76464027f,
+ 0.76884186f, 0.77301043f, 0.77714598f, 0.78124821f, 0.78531694f,
+ 0.78935206f, 0.79335338f, 0.79732066f, 0.80125386f, 0.80515265f,
+ 0.80901700f, 0.81284672f, 0.81664157f, 0.82040149f, 0.82412618f,
+ 0.82781565f, 0.83146966f, 0.83508795f, 0.83867061f, 0.84221727f,
+ 0.84572780f, 0.84920216f, 0.85264021f, 0.85604161f, 0.85940641f,
+ 0.86273444f, 0.86602545f, 0.86927933f, 0.87249607f, 0.87567532f,
+ 0.87881714f, 0.88192129f, 0.88498765f, 0.88801610f, 0.89100653f,
+ 0.89395881f, 0.89687276f, 0.89974827f, 0.90258533f, 0.90538365f,
+ 0.90814316f, 0.91086388f, 0.91354549f, 0.91618794f, 0.91879123f,
+ 0.92135513f, 0.92387950f, 0.92636442f, 0.92880958f, 0.93121493f,
+ 0.93358046f, 0.93590593f, 0.93819135f, 0.94043654f, 0.94264150f,
+ 0.94480604f, 0.94693011f, 0.94901365f, 0.95105654f, 0.95305866f,
+ 0.95501995f, 0.95694035f, 0.95881975f, 0.96065807f, 0.96245527f,
+ 0.96421117f, 0.96592581f, 0.96759909f, 0.96923089f, 0.97082120f,
+ 0.97236991f, 0.97387701f, 0.97534233f, 0.97676587f, 0.97814763f,
+ 0.97948742f, 0.98078531f, 0.98204112f, 0.98325491f, 0.98442656f,
+ 0.98555607f, 0.98664331f, 0.98768836f, 0.98869103f, 0.98965138f,
+ 0.99056935f, 0.99144489f, 0.99227792f, 0.99306846f, 0.99381649f,
+ 0.99452192f, 0.99518472f, 0.99580491f, 0.99638247f, 0.99691731f,
+ 0.99740952f, 0.99785894f, 0.99826562f, 0.99862951f, 0.99895066f,
+ 0.99922901f, 0.99946457f, 0.99965733f, 0.99980724f, 0.99991435f,
+ 0.99997860f, 1.00000000f, 0.99997860f, 0.99991435f, 0.99980724f,
+ 0.99965733f, 0.99946457f, 0.99922901f, 0.99895066f, 0.99862951f,
+ 0.99826562f, 0.99785894f, 0.99740946f, 0.99691731f, 0.99638247f,
+ 0.99580491f, 0.99518472f, 0.99452192f, 0.99381644f, 0.99306846f,
+ 0.99227792f, 0.99144489f, 0.99056935f, 0.98965138f, 0.98869103f,
+ 0.98768836f, 0.98664331f, 0.98555607f, 0.98442656f, 0.98325491f,
+ 0.98204112f, 0.98078525f, 0.97948742f, 0.97814757f, 0.97676587f,
+ 0.97534227f, 0.97387695f, 0.97236991f, 0.97082120f, 0.96923089f,
+ 0.96759909f, 0.96592581f, 0.96421117f, 0.96245521f, 0.96065807f,
+ 0.95881969f, 0.95694029f, 0.95501995f, 0.95305860f, 0.95105648f,
+ 0.94901365f, 0.94693011f, 0.94480604f, 0.94264150f, 0.94043654f,
+ 0.93819129f, 0.93590593f, 0.93358046f, 0.93121493f, 0.92880952f,
+ 0.92636436f, 0.92387950f, 0.92135507f, 0.91879123f, 0.91618794f,
+ 0.91354543f, 0.91086382f, 0.90814310f, 0.90538365f, 0.90258527f,
+ 0.89974827f, 0.89687276f, 0.89395875f, 0.89100647f, 0.88801610f,
+ 0.88498759f, 0.88192123f, 0.87881714f, 0.87567532f, 0.87249595f,
+ 0.86927933f, 0.86602539f, 0.86273432f, 0.85940641f, 0.85604161f,
+ 0.85264009f, 0.84920216f, 0.84572780f, 0.84221715f, 0.83867055f,
+ 0.83508795f, 0.83146954f, 0.82781565f, 0.82412612f, 0.82040137f,
+ 0.81664157f, 0.81284660f, 0.80901700f, 0.80515265f, 0.80125374f,
+ 0.79732066f, 0.79335332f, 0.78935200f, 0.78531694f, 0.78124815f,
+ 0.77714586f, 0.77301049f, 0.76884180f, 0.76464021f, 0.76040596f,
+ 0.75613904f, 0.75183970f, 0.74750835f, 0.74314481f, 0.73874938f,
+ 0.73432249f, 0.72986400f, 0.72537428f, 0.72085363f, 0.71630186f,
+ 0.71171951f, 0.70710677f, 0.70246363f, 0.69779032f, 0.69308734f,
+ 0.68835449f, 0.68359220f, 0.67880070f, 0.67398006f, 0.66913044f,
+ 0.66425240f, 0.65934575f, 0.65441096f, 0.64944804f, 0.64445722f,
+ 0.63943905f, 0.63439327f, 0.62932026f, 0.62422055f, 0.61909389f,
+ 0.61394072f, 0.60876143f, 0.60355592f, 0.59832448f, 0.59306765f,
+ 0.58778518f, 0.58247757f, 0.57714522f, 0.57178789f, 0.56640613f,
+ 0.56100023f, 0.55557019f, 0.55011630f, 0.54463905f, 0.53913826f,
+ 0.53361434f, 0.52806783f, 0.52249849f, 0.51690674f, 0.51129305f,
+ 0.50565726f, 0.50000006f, 0.49432117f, 0.48862115f, 0.48290038f,
+ 0.47715873f, 0.47139663f, 0.46561456f, 0.45981231f, 0.45399037f,
+ 0.44814920f, 0.44228864f, 0.43640912f, 0.43051112f, 0.42459446f,
+ 0.41865960f, 0.41270703f, 0.40673658f, 0.40074870f, 0.39474386f,
+ 0.38872188f, 0.38268328f, 0.37662849f, 0.37055734f, 0.36447033f,
+ 0.35836792f, 0.35224995f, 0.34611690f, 0.33996922f, 0.33380675f,
+ 0.32763001f, 0.32143945f, 0.31523487f, 0.30901679f, 0.30278572f,
+ 0.29654145f, 0.29028472f, 0.28401530f, 0.27773371f, 0.27144048f,
+ 0.26513538f, 0.25881892f, 0.25249159f, 0.24615324f, 0.23980433f,
+ 0.23344538f, 0.22707619f, 0.22069728f, 0.21430916f, 0.20791161f,
+ 0.20150517f, 0.19509031f, 0.18866688f, 0.18223536f, 0.17579627f,
+ 0.16934940f, 0.16289529f, 0.15643445f, 0.14996666f, 0.14349243f,
+ 0.13701232f, 0.13052608f, 0.12403426f, 0.11753736f, 0.11103519f,
+ 0.10452849f, 0.09801710f, 0.09150149f, 0.08498220f, 0.07845904f,
+ 0.07193252f, 0.06540315f, 0.05887074f, 0.05233581f, 0.04579888f,
+ 0.03925974f, 0.03271893f, 0.02617695f, 0.01963361f, 0.01308943f,
+ 0.00654493f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f};
+
+// Hanning window: for 30ms with 1024 fft with symmetric zeros at 16kHz
+static const float kBlocks480w1024[1024] = {
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00327249f, 0.00654494f,
+ 0.00981732f, 0.01308960f, 0.01636173f, 0.01963369f, 0.02290544f,
+ 0.02617695f, 0.02944817f, 0.03271908f, 0.03598964f, 0.03925982f,
+ 0.04252957f, 0.04579887f, 0.04906768f, 0.05233596f, 0.05560368f,
+ 0.05887080f, 0.06213730f, 0.06540313f, 0.06866825f, 0.07193266f,
+ 0.07519628f, 0.07845910f, 0.08172107f, 0.08498218f, 0.08824237f,
+ 0.09150162f, 0.09475989f, 0.09801714f, 0.10127335f, 0.10452846f,
+ 0.10778246f, 0.11103531f, 0.11428697f, 0.11753740f, 0.12078657f,
+ 0.12403446f, 0.12728101f, 0.13052620f, 0.13376999f, 0.13701233f,
+ 0.14025325f, 0.14349262f, 0.14673047f, 0.14996676f, 0.15320145f,
+ 0.15643448f, 0.15966582f, 0.16289547f, 0.16612339f, 0.16934951f,
+ 0.17257382f, 0.17579629f, 0.17901687f, 0.18223552f, 0.18545224f,
+ 0.18866697f, 0.19187967f, 0.19509032f, 0.19829889f, 0.20150533f,
+ 0.20470962f, 0.20791170f, 0.21111156f, 0.21430916f, 0.21750447f,
+ 0.22069745f, 0.22388805f, 0.22707628f, 0.23026206f, 0.23344538f,
+ 0.23662618f, 0.23980446f, 0.24298020f, 0.24615330f, 0.24932377f,
+ 0.25249159f, 0.25565669f, 0.25881904f, 0.26197866f, 0.26513544f,
+ 0.26828939f, 0.27144045f, 0.27458861f, 0.27773386f, 0.28087610f,
+ 0.28401536f, 0.28715158f, 0.29028466f, 0.29341471f, 0.29654160f,
+ 0.29966527f, 0.30278578f, 0.30590302f, 0.30901700f, 0.31212768f,
+ 0.31523499f, 0.31833893f, 0.32143945f, 0.32453656f, 0.32763019f,
+ 0.33072028f, 0.33380687f, 0.33688986f, 0.33996925f, 0.34304500f,
+ 0.34611708f, 0.34918544f, 0.35225007f, 0.35531089f, 0.35836795f,
+ 0.36142117f, 0.36447051f, 0.36751595f, 0.37055743f, 0.37359497f,
+ 0.37662852f, 0.37965801f, 0.38268346f, 0.38570479f, 0.38872197f,
+ 0.39173502f, 0.39474389f, 0.39774847f, 0.40074885f, 0.40374491f,
+ 0.40673664f, 0.40972406f, 0.41270703f, 0.41568562f, 0.41865975f,
+ 0.42162940f, 0.42459452f, 0.42755508f, 0.43051112f, 0.43346250f,
+ 0.43640924f, 0.43935132f, 0.44228873f, 0.44522133f, 0.44814920f,
+ 0.45107228f, 0.45399052f, 0.45690390f, 0.45981237f, 0.46271592f,
+ 0.46561453f, 0.46850815f, 0.47139674f, 0.47428030f, 0.47715878f,
+ 0.48003215f, 0.48290035f, 0.48576337f, 0.48862126f, 0.49147385f,
+ 0.49432120f, 0.49716330f, 0.50000000f, 0.50283140f, 0.50565743f,
+ 0.50847799f, 0.51129311f, 0.51410276f, 0.51690692f, 0.51970553f,
+ 0.52249855f, 0.52528602f, 0.52806789f, 0.53084403f, 0.53361452f,
+ 0.53637928f, 0.53913832f, 0.54189163f, 0.54463905f, 0.54738063f,
+ 0.55011642f, 0.55284631f, 0.55557024f, 0.55828828f, 0.56100029f,
+ 0.56370628f, 0.56640625f, 0.56910014f, 0.57178795f, 0.57446963f,
+ 0.57714522f, 0.57981455f, 0.58247769f, 0.58513463f, 0.58778524f,
+ 0.59042960f, 0.59306765f, 0.59569931f, 0.59832460f, 0.60094351f,
+ 0.60355598f, 0.60616195f, 0.60876143f, 0.61135441f, 0.61394083f,
+ 0.61652070f, 0.61909395f, 0.62166059f, 0.62422055f, 0.62677383f,
+ 0.62932038f, 0.63186020f, 0.63439333f, 0.63691956f, 0.63943899f,
+ 0.64195162f, 0.64445734f, 0.64695615f, 0.64944810f, 0.65193301f,
+ 0.65441096f, 0.65688187f, 0.65934587f, 0.66180271f, 0.66425246f,
+ 0.66669512f, 0.66913062f, 0.67155898f, 0.67398012f, 0.67639405f,
+ 0.67880076f, 0.68120021f, 0.68359232f, 0.68597710f, 0.68835455f,
+ 0.69072467f, 0.69308740f, 0.69544262f, 0.69779050f, 0.70013082f,
+ 0.70246369f, 0.70478904f, 0.70710677f, 0.70941699f, 0.71171963f,
+ 0.71401459f, 0.71630198f, 0.71858168f, 0.72085363f, 0.72311789f,
+ 0.72537440f, 0.72762316f, 0.72986406f, 0.73209721f, 0.73432255f,
+ 0.73653996f, 0.73874950f, 0.74095118f, 0.74314487f, 0.74533057f,
+ 0.74750835f, 0.74967808f, 0.75183982f, 0.75399351f, 0.75613910f,
+ 0.75827658f, 0.76040596f, 0.76252723f, 0.76464027f, 0.76674515f,
+ 0.76884186f, 0.77093029f, 0.77301043f, 0.77508241f, 0.77714598f,
+ 0.77920127f, 0.78124821f, 0.78328675f, 0.78531694f, 0.78733873f,
+ 0.78935206f, 0.79135692f, 0.79335338f, 0.79534125f, 0.79732066f,
+ 0.79929149f, 0.80125386f, 0.80320752f, 0.80515265f, 0.80708915f,
+ 0.80901700f, 0.81093621f, 0.81284672f, 0.81474853f, 0.81664157f,
+ 0.81852591f, 0.82040149f, 0.82226825f, 0.82412618f, 0.82597536f,
+ 0.82781565f, 0.82964706f, 0.83146966f, 0.83328325f, 0.83508795f,
+ 0.83688378f, 0.83867061f, 0.84044838f, 0.84221727f, 0.84397703f,
+ 0.84572780f, 0.84746957f, 0.84920216f, 0.85092574f, 0.85264021f,
+ 0.85434544f, 0.85604161f, 0.85772866f, 0.85940641f, 0.86107504f,
+ 0.86273444f, 0.86438453f, 0.86602545f, 0.86765707f, 0.86927933f,
+ 0.87089235f, 0.87249607f, 0.87409031f, 0.87567532f, 0.87725097f,
+ 0.87881714f, 0.88037390f, 0.88192129f, 0.88345921f, 0.88498765f,
+ 0.88650668f, 0.88801610f, 0.88951612f, 0.89100653f, 0.89248741f,
+ 0.89395881f, 0.89542055f, 0.89687276f, 0.89831537f, 0.89974827f,
+ 0.90117162f, 0.90258533f, 0.90398932f, 0.90538365f, 0.90676826f,
+ 0.90814316f, 0.90950841f, 0.91086388f, 0.91220951f, 0.91354549f,
+ 0.91487163f, 0.91618794f, 0.91749454f, 0.91879123f, 0.92007810f,
+ 0.92135513f, 0.92262226f, 0.92387950f, 0.92512691f, 0.92636442f,
+ 0.92759192f, 0.92880958f, 0.93001723f, 0.93121493f, 0.93240267f,
+ 0.93358046f, 0.93474817f, 0.93590593f, 0.93705362f, 0.93819135f,
+ 0.93931901f, 0.94043654f, 0.94154406f, 0.94264150f, 0.94372880f,
+ 0.94480604f, 0.94587320f, 0.94693011f, 0.94797695f, 0.94901365f,
+ 0.95004016f, 0.95105654f, 0.95206273f, 0.95305866f, 0.95404440f,
+ 0.95501995f, 0.95598525f, 0.95694035f, 0.95788521f, 0.95881975f,
+ 0.95974404f, 0.96065807f, 0.96156180f, 0.96245527f, 0.96333838f,
+ 0.96421117f, 0.96507370f, 0.96592581f, 0.96676767f, 0.96759909f,
+ 0.96842021f, 0.96923089f, 0.97003126f, 0.97082120f, 0.97160077f,
+ 0.97236991f, 0.97312868f, 0.97387701f, 0.97461486f, 0.97534233f,
+ 0.97605932f, 0.97676587f, 0.97746199f, 0.97814763f, 0.97882277f,
+ 0.97948742f, 0.98014158f, 0.98078531f, 0.98141843f, 0.98204112f,
+ 0.98265332f, 0.98325491f, 0.98384601f, 0.98442656f, 0.98499662f,
+ 0.98555607f, 0.98610497f, 0.98664331f, 0.98717111f, 0.98768836f,
+ 0.98819500f, 0.98869103f, 0.98917651f, 0.98965138f, 0.99011570f,
+ 0.99056935f, 0.99101239f, 0.99144489f, 0.99186671f, 0.99227792f,
+ 0.99267852f, 0.99306846f, 0.99344778f, 0.99381649f, 0.99417448f,
+ 0.99452192f, 0.99485862f, 0.99518472f, 0.99550015f, 0.99580491f,
+ 0.99609905f, 0.99638247f, 0.99665523f, 0.99691731f, 0.99716878f,
+ 0.99740952f, 0.99763954f, 0.99785894f, 0.99806762f, 0.99826562f,
+ 0.99845290f, 0.99862951f, 0.99879545f, 0.99895066f, 0.99909520f,
+ 0.99922901f, 0.99935216f, 0.99946457f, 0.99956632f, 0.99965733f,
+ 0.99973762f, 0.99980724f, 0.99986613f, 0.99991435f, 0.99995178f,
+ 0.99997860f, 0.99999464f, 1.00000000f, 0.99999464f, 0.99997860f,
+ 0.99995178f, 0.99991435f, 0.99986613f, 0.99980724f, 0.99973762f,
+ 0.99965733f, 0.99956632f, 0.99946457f, 0.99935216f, 0.99922901f,
+ 0.99909520f, 0.99895066f, 0.99879545f, 0.99862951f, 0.99845290f,
+ 0.99826562f, 0.99806762f, 0.99785894f, 0.99763954f, 0.99740946f,
+ 0.99716872f, 0.99691731f, 0.99665523f, 0.99638247f, 0.99609905f,
+ 0.99580491f, 0.99550015f, 0.99518472f, 0.99485862f, 0.99452192f,
+ 0.99417448f, 0.99381644f, 0.99344778f, 0.99306846f, 0.99267852f,
+ 0.99227792f, 0.99186671f, 0.99144489f, 0.99101239f, 0.99056935f,
+ 0.99011564f, 0.98965138f, 0.98917651f, 0.98869103f, 0.98819494f,
+ 0.98768836f, 0.98717111f, 0.98664331f, 0.98610497f, 0.98555607f,
+ 0.98499656f, 0.98442656f, 0.98384601f, 0.98325491f, 0.98265326f,
+ 0.98204112f, 0.98141843f, 0.98078525f, 0.98014158f, 0.97948742f,
+ 0.97882277f, 0.97814757f, 0.97746193f, 0.97676587f, 0.97605932f,
+ 0.97534227f, 0.97461486f, 0.97387695f, 0.97312862f, 0.97236991f,
+ 0.97160077f, 0.97082120f, 0.97003126f, 0.96923089f, 0.96842015f,
+ 0.96759909f, 0.96676761f, 0.96592581f, 0.96507365f, 0.96421117f,
+ 0.96333838f, 0.96245521f, 0.96156180f, 0.96065807f, 0.95974404f,
+ 0.95881969f, 0.95788515f, 0.95694029f, 0.95598525f, 0.95501995f,
+ 0.95404440f, 0.95305860f, 0.95206267f, 0.95105648f, 0.95004016f,
+ 0.94901365f, 0.94797695f, 0.94693011f, 0.94587314f, 0.94480604f,
+ 0.94372880f, 0.94264150f, 0.94154406f, 0.94043654f, 0.93931895f,
+ 0.93819129f, 0.93705362f, 0.93590593f, 0.93474817f, 0.93358046f,
+ 0.93240267f, 0.93121493f, 0.93001723f, 0.92880952f, 0.92759192f,
+ 0.92636436f, 0.92512691f, 0.92387950f, 0.92262226f, 0.92135507f,
+ 0.92007804f, 0.91879123f, 0.91749448f, 0.91618794f, 0.91487157f,
+ 0.91354543f, 0.91220951f, 0.91086382f, 0.90950835f, 0.90814310f,
+ 0.90676820f, 0.90538365f, 0.90398932f, 0.90258527f, 0.90117157f,
+ 0.89974827f, 0.89831525f, 0.89687276f, 0.89542055f, 0.89395875f,
+ 0.89248741f, 0.89100647f, 0.88951600f, 0.88801610f, 0.88650662f,
+ 0.88498759f, 0.88345915f, 0.88192123f, 0.88037384f, 0.87881714f,
+ 0.87725091f, 0.87567532f, 0.87409031f, 0.87249595f, 0.87089223f,
+ 0.86927933f, 0.86765701f, 0.86602539f, 0.86438447f, 0.86273432f,
+ 0.86107504f, 0.85940641f, 0.85772860f, 0.85604161f, 0.85434544f,
+ 0.85264009f, 0.85092574f, 0.84920216f, 0.84746951f, 0.84572780f,
+ 0.84397697f, 0.84221715f, 0.84044844f, 0.83867055f, 0.83688372f,
+ 0.83508795f, 0.83328319f, 0.83146954f, 0.82964706f, 0.82781565f,
+ 0.82597530f, 0.82412612f, 0.82226813f, 0.82040137f, 0.81852591f,
+ 0.81664157f, 0.81474847f, 0.81284660f, 0.81093609f, 0.80901700f,
+ 0.80708915f, 0.80515265f, 0.80320752f, 0.80125374f, 0.79929143f,
+ 0.79732066f, 0.79534125f, 0.79335332f, 0.79135686f, 0.78935200f,
+ 0.78733861f, 0.78531694f, 0.78328675f, 0.78124815f, 0.77920121f,
+ 0.77714586f, 0.77508223f, 0.77301049f, 0.77093029f, 0.76884180f,
+ 0.76674509f, 0.76464021f, 0.76252711f, 0.76040596f, 0.75827658f,
+ 0.75613904f, 0.75399339f, 0.75183970f, 0.74967796f, 0.74750835f,
+ 0.74533057f, 0.74314481f, 0.74095106f, 0.73874938f, 0.73653996f,
+ 0.73432249f, 0.73209721f, 0.72986400f, 0.72762305f, 0.72537428f,
+ 0.72311789f, 0.72085363f, 0.71858162f, 0.71630186f, 0.71401453f,
+ 0.71171951f, 0.70941705f, 0.70710677f, 0.70478898f, 0.70246363f,
+ 0.70013070f, 0.69779032f, 0.69544268f, 0.69308734f, 0.69072461f,
+ 0.68835449f, 0.68597704f, 0.68359220f, 0.68120021f, 0.67880070f,
+ 0.67639399f, 0.67398006f, 0.67155886f, 0.66913044f, 0.66669512f,
+ 0.66425240f, 0.66180259f, 0.65934575f, 0.65688181f, 0.65441096f,
+ 0.65193301f, 0.64944804f, 0.64695609f, 0.64445722f, 0.64195150f,
+ 0.63943905f, 0.63691956f, 0.63439327f, 0.63186014f, 0.62932026f,
+ 0.62677372f, 0.62422055f, 0.62166059f, 0.61909389f, 0.61652064f,
+ 0.61394072f, 0.61135429f, 0.60876143f, 0.60616189f, 0.60355592f,
+ 0.60094339f, 0.59832448f, 0.59569913f, 0.59306765f, 0.59042960f,
+ 0.58778518f, 0.58513451f, 0.58247757f, 0.57981461f, 0.57714522f,
+ 0.57446963f, 0.57178789f, 0.56910002f, 0.56640613f, 0.56370628f,
+ 0.56100023f, 0.55828822f, 0.55557019f, 0.55284619f, 0.55011630f,
+ 0.54738069f, 0.54463905f, 0.54189152f, 0.53913826f, 0.53637916f,
+ 0.53361434f, 0.53084403f, 0.52806783f, 0.52528596f, 0.52249849f,
+ 0.51970541f, 0.51690674f, 0.51410276f, 0.51129305f, 0.50847787f,
+ 0.50565726f, 0.50283122f, 0.50000006f, 0.49716327f, 0.49432117f,
+ 0.49147379f, 0.48862115f, 0.48576325f, 0.48290038f, 0.48003212f,
+ 0.47715873f, 0.47428021f, 0.47139663f, 0.46850798f, 0.46561456f,
+ 0.46271589f, 0.45981231f, 0.45690379f, 0.45399037f, 0.45107210f,
+ 0.44814920f, 0.44522130f, 0.44228864f, 0.43935123f, 0.43640912f,
+ 0.43346232f, 0.43051112f, 0.42755505f, 0.42459446f, 0.42162928f,
+ 0.41865960f, 0.41568545f, 0.41270703f, 0.40972400f, 0.40673658f,
+ 0.40374479f, 0.40074870f, 0.39774850f, 0.39474386f, 0.39173496f,
+ 0.38872188f, 0.38570464f, 0.38268328f, 0.37965804f, 0.37662849f,
+ 0.37359491f, 0.37055734f, 0.36751580f, 0.36447033f, 0.36142117f,
+ 0.35836792f, 0.35531086f, 0.35224995f, 0.34918529f, 0.34611690f,
+ 0.34304500f, 0.33996922f, 0.33688980f, 0.33380675f, 0.33072016f,
+ 0.32763001f, 0.32453656f, 0.32143945f, 0.31833887f, 0.31523487f,
+ 0.31212750f, 0.30901679f, 0.30590302f, 0.30278572f, 0.29966521f,
+ 0.29654145f, 0.29341453f, 0.29028472f, 0.28715155f, 0.28401530f,
+ 0.28087601f, 0.27773371f, 0.27458847f, 0.27144048f, 0.26828936f,
+ 0.26513538f, 0.26197854f, 0.25881892f, 0.25565651f, 0.25249159f,
+ 0.24932374f, 0.24615324f, 0.24298008f, 0.23980433f, 0.23662600f,
+ 0.23344538f, 0.23026201f, 0.22707619f, 0.22388794f, 0.22069728f,
+ 0.21750426f, 0.21430916f, 0.21111152f, 0.20791161f, 0.20470949f,
+ 0.20150517f, 0.19829892f, 0.19509031f, 0.19187963f, 0.18866688f,
+ 0.18545210f, 0.18223536f, 0.17901689f, 0.17579627f, 0.17257376f,
+ 0.16934940f, 0.16612324f, 0.16289529f, 0.15966584f, 0.15643445f,
+ 0.15320137f, 0.14996666f, 0.14673033f, 0.14349243f, 0.14025325f,
+ 0.13701232f, 0.13376991f, 0.13052608f, 0.12728085f, 0.12403426f,
+ 0.12078657f, 0.11753736f, 0.11428688f, 0.11103519f, 0.10778230f,
+ 0.10452849f, 0.10127334f, 0.09801710f, 0.09475980f, 0.09150149f,
+ 0.08824220f, 0.08498220f, 0.08172106f, 0.07845904f, 0.07519618f,
+ 0.07193252f, 0.06866808f, 0.06540315f, 0.06213728f, 0.05887074f,
+ 0.05560357f, 0.05233581f, 0.04906749f, 0.04579888f, 0.04252954f,
+ 0.03925974f, 0.03598953f, 0.03271893f, 0.02944798f, 0.02617695f,
+ 0.02290541f, 0.01963361f, 0.01636161f, 0.01308943f, 0.00981712f,
+ 0.00654493f, 0.00327244f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
+ 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_
diff --git a/modules/audio_processing/ns/BUILD.gn b/modules/audio_processing/ns/BUILD.gn
new file mode 100644
index 0000000..077cb00
--- /dev/null
+++ b/modules/audio_processing/ns/BUILD.gn
@@ -0,0 +1,104 @@
+# 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_static_library("ns") {
+ visibility = [ "*" ]
+ configs += [ "..:apm_debug_dump" ]
+ sources = [
+ "fast_math.cc",
+ "fast_math.h",
+ "histograms.cc",
+ "histograms.h",
+ "noise_estimator.cc",
+ "noise_estimator.h",
+ "noise_suppressor.cc",
+ "noise_suppressor.h",
+ "ns_common.h",
+ "ns_config.h",
+ "ns_fft.cc",
+ "ns_fft.h",
+ "prior_signal_model.cc",
+ "prior_signal_model.h",
+ "prior_signal_model_estimator.cc",
+ "prior_signal_model_estimator.h",
+ "quantile_noise_estimator.cc",
+ "quantile_noise_estimator.h",
+ "signal_model.cc",
+ "signal_model.h",
+ "signal_model_estimator.cc",
+ "signal_model_estimator.h",
+ "speech_probability_estimator.cc",
+ "speech_probability_estimator.h",
+ "suppression_params.cc",
+ "suppression_params.h",
+ "wiener_filter.cc",
+ "wiener_filter.h",
+ ]
+
+ defines = []
+ if (rtc_build_with_neon && current_cpu != "arm64") {
+ suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+ cflags = [ "-mfpu=neon" ]
+ }
+
+ deps = [
+ "..:apm_logging",
+ "..:audio_buffer",
+ "..:high_pass_filter",
+ "../../../api:array_view",
+ "../../../common_audio:common_audio_c",
+ "../../../common_audio/third_party/fft4g",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:rtc_base_approved",
+ "../../../rtc_base:safe_minmax",
+ "../../../rtc_base/system:arch",
+ "../../../system_wrappers:cpu_features_api",
+ "../../../system_wrappers:field_trial",
+ "../../../system_wrappers:metrics",
+ "../utility:cascaded_biquad_filter",
+ "../utility:ooura_fft",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+if (rtc_include_tests) {
+ rtc_source_set("ns_unittests") {
+ testonly = true
+
+ configs += [ "..:apm_debug_dump" ]
+ sources = [
+ "noise_suppressor_unittest.cc",
+ ]
+
+ deps = [
+ ":ns",
+ "..:apm_logging",
+ "..:audio_buffer",
+ "..:audio_processing",
+ "..:audio_processing_unittests",
+ "..:high_pass_filter",
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:rtc_base_approved",
+ "../../../rtc_base:safe_minmax",
+ "../../../rtc_base/system:arch",
+ "../../../system_wrappers:cpu_features_api",
+ "../../../test:test_support",
+ "../utility:cascaded_biquad_filter",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+
+ defines = []
+
+ if (rtc_enable_protobuf) {
+ sources += []
+ }
+ }
+}
diff --git a/modules/audio_processing/ns/defines.h b/modules/audio_processing/ns/defines.h
deleted file mode 100644
index 2935f25..0000000
--- a/modules/audio_processing/ns/defines.h
+++ /dev/null
@@ -1,56 +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_NS_MAIN_SOURCE_DEFINES_H_
-#define MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_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 (float)0.25
-
-#define SIMULT 3
-#define END_STARTUP_LONG 200
-#define END_STARTUP_SHORT 50
-#define FACTOR (float)40.0
-#define WIDTH (float)0.01
-
-// 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 (float)0.98 // DD update of prior SNR
-#define LRT_TAVG (float)0.50 // tavg parameter for LRT (previously 0.90)
-#define SPECT_FL_TAVG \
- (float)0.30 // tavg parameter for spectral flatness measure
-#define SPECT_DIFF_TAVG \
- (float)0.30 // tavg parameter for spectral difference measure
-#define PRIOR_UPDATE (float)0.10 // update parameter of prior model
-#define NOISE_UPDATE (float)0.90 // update parameter for noise
-#define SPEECH_UPDATE (float)0.99 // update parameter when likely speech
-#define WIDTH_PR_MAP \
- (float)4.0 // width parameter in sigmoid map for prior model
-#define LRT_FEATURE_THR (float)0.5 // default threshold for LRT feature
-#define SF_FEATURE_THR \
- (float)0.5 // default threshold for Spectral Flatness feature
-#define SD_FEATURE_THR \
- (float)0.5 // default threshold for Spectral Difference feature
-#define PROB_RANGE \
- (float)0.20 // probability threshold for noise state in
- // speech/noise likelihood
-#define HIST_PAR_EST 1000 // histogram size for estimation of parameters
-#define GAMMA_PAUSE (float)0.05 // update for conservative noise estimate
-//
-#define B_LIM (float)0.5 // threshold in final energy gain factor calculation
-#endif // MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_DEFINES_H_
diff --git a/modules/audio_processing/ns/fast_math.cc b/modules/audio_processing/ns/fast_math.cc
new file mode 100644
index 0000000..d13110c
--- /dev/null
+++ b/modules/audio_processing/ns/fast_math.cc
@@ -0,0 +1,84 @@
+/*
+ * 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/ns/fast_math.h"
+
+#include <math.h>
+#include <stdint.h>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+
+float FastLog2f(float in) {
+ RTC_DCHECK_GT(in, .0f);
+ // Read and interpret float as uint32_t and then cast to float.
+ // This is done to extract the exponent (bits 30 - 23).
+ // "Right shift" of the exponent is then performed by multiplying
+ // with the constant (1/2^23). Finally, we subtract a constant to
+ // remove the bias (https://en.wikipedia.org/wiki/Exponent_bias).
+ union {
+ float dummy;
+ uint32_t a;
+ } x = {in};
+ float out = x.a;
+ out *= 1.1920929e-7f; // 1/2^23
+ out -= 126.942695f; // Remove bias.
+ return out;
+}
+
+} // namespace
+
+float SqrtFastApproximation(float f) {
+ // TODO(peah): Add fast approximate implementation.
+ return sqrtf(f);
+}
+
+float Pow2Approximation(float p) {
+ // TODO(peah): Add fast approximate implementation.
+ return powf(2.f, p);
+}
+
+float PowApproximation(float x, float p) {
+ return Pow2Approximation(p * FastLog2f(x));
+}
+
+float LogApproximation(float x) {
+ constexpr float kLogOf2 = 0.69314718056f;
+ return FastLog2f(x) * kLogOf2;
+}
+
+void LogApproximation(rtc::ArrayView<const float> x, rtc::ArrayView<float> y) {
+ for (size_t k = 0; k < x.size(); ++k) {
+ y[k] = LogApproximation(x[k]);
+ }
+}
+
+float ExpApproximation(float x) {
+ constexpr float kLog10Ofe = 0.4342944819f;
+ return PowApproximation(10.f, x * kLog10Ofe);
+}
+
+void ExpApproximation(rtc::ArrayView<const float> x, rtc::ArrayView<float> y) {
+ for (size_t k = 0; k < x.size(); ++k) {
+ y[k] = ExpApproximation(x[k]);
+ }
+}
+
+void ExpApproximationSignFlip(rtc::ArrayView<const float> x,
+ rtc::ArrayView<float> y) {
+ for (size_t k = 0; k < x.size(); ++k) {
+ y[k] = ExpApproximation(-x[k]);
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/fast_math.h b/modules/audio_processing/ns/fast_math.h
new file mode 100644
index 0000000..0aefee9
--- /dev/null
+++ b/modules/audio_processing/ns/fast_math.h
@@ -0,0 +1,38 @@
+/*
+ * 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_NS_FAST_MATH_H_
+#define MODULES_AUDIO_PROCESSING_NS_FAST_MATH_H_
+
+#include "api/array_view.h"
+
+namespace webrtc {
+
+// Sqrt approximation.
+float SqrtFastApproximation(float f);
+
+// Log base conversion log(x) = log2(x)/log2(e).
+float LogApproximation(float x);
+void LogApproximation(rtc::ArrayView<const float> x, rtc::ArrayView<float> y);
+
+// 2^x approximation.
+float Pow2Approximation(float p);
+
+// x^p approximation.
+float PowApproximation(float x, float p);
+
+// e^x approximation.
+float ExpApproximation(float x);
+void ExpApproximation(rtc::ArrayView<const float> x, rtc::ArrayView<float> y);
+void ExpApproximationSignFlip(rtc::ArrayView<const float> x,
+ rtc::ArrayView<float> y);
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_FAST_MATH_H_
diff --git a/modules/audio_processing/ns/histograms.cc b/modules/audio_processing/ns/histograms.cc
new file mode 100644
index 0000000..1d4f459
--- /dev/null
+++ b/modules/audio_processing/ns/histograms.cc
@@ -0,0 +1,47 @@
+/*
+ * 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/ns/histograms.h"
+
+namespace webrtc {
+
+Histograms::Histograms() {
+ Clear();
+}
+
+void Histograms::Clear() {
+ lrt_.fill(0);
+ spectral_flatness_.fill(0);
+ spectral_diff_.fill(0);
+}
+
+void Histograms::Update(const SignalModel& features_) {
+ // Update the histogram for the LRT.
+ constexpr float kOneByBinSizeLrt = 1.f / kBinSizeLrt;
+ if (features_.lrt < kHistogramSize * kBinSizeLrt && features_.lrt >= 0.f) {
+ ++lrt_[kOneByBinSizeLrt * features_.lrt];
+ }
+
+ // Update histogram for the spectral flatness.
+ constexpr float kOneByBinSizeSpecFlat = 1.f / kBinSizeSpecFlat;
+ if (features_.spectral_flatness < kHistogramSize * kBinSizeSpecFlat &&
+ features_.spectral_flatness >= 0.f) {
+ ++spectral_flatness_[features_.spectral_flatness * kOneByBinSizeSpecFlat];
+ }
+
+ // Update histogram for the spectral difference.
+ constexpr float kOneByBinSizeSpecDiff = 1.f / kBinSizeSpecDiff;
+ if (features_.spectral_diff < kHistogramSize * kBinSizeSpecDiff &&
+ features_.spectral_diff >= 0.f) {
+ ++spectral_diff_[features_.spectral_diff * kOneByBinSizeSpecDiff];
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/histograms.h b/modules/audio_processing/ns/histograms.h
new file mode 100644
index 0000000..9640e74
--- /dev/null
+++ b/modules/audio_processing/ns/histograms.h
@@ -0,0 +1,55 @@
+/*
+ * 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_NS_HISTOGRAMS_H_
+#define MODULES_AUDIO_PROCESSING_NS_HISTOGRAMS_H_
+
+#include <array>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/ns_common.h"
+#include "modules/audio_processing/ns/signal_model.h"
+
+namespace webrtc {
+
+constexpr int kHistogramSize = 1000;
+
+// Class for handling the updating of histograms.
+class Histograms {
+ public:
+ Histograms();
+ Histograms(const Histograms&) = delete;
+ Histograms& operator=(const Histograms&) = delete;
+
+ // Clears the histograms.
+ void Clear();
+
+ // Extracts thresholds for feature parameters and updates the corresponding
+ // histogram.
+ void Update(const SignalModel& features_);
+
+ // Methods for accessing the histograms.
+ rtc::ArrayView<const int, kHistogramSize> get_lrt() const { return lrt_; }
+ rtc::ArrayView<const int, kHistogramSize> get_spectral_flatness() const {
+ return spectral_flatness_;
+ }
+ rtc::ArrayView<const int, kHistogramSize> get_spectral_diff() const {
+ return spectral_diff_;
+ }
+
+ private:
+ std::array<int, kHistogramSize> lrt_;
+ std::array<int, kHistogramSize> spectral_flatness_;
+ std::array<int, kHistogramSize> spectral_diff_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_HISTOGRAMS_H_
diff --git a/modules/audio_processing/ns/noise_estimator.cc b/modules/audio_processing/ns/noise_estimator.cc
new file mode 100644
index 0000000..5367545
--- /dev/null
+++ b/modules/audio_processing/ns/noise_estimator.cc
@@ -0,0 +1,195 @@
+/*
+ * 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/ns/noise_estimator.h"
+
+#include <algorithm>
+
+#include "modules/audio_processing/ns/fast_math.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+
+// Log(i).
+constexpr std::array<float, 129> log_table = {
+ 0.f, 0.f, 0.f, 0.f, 0.f, 1.609438f, 1.791759f,
+ 1.945910f, 2.079442f, 2.197225f, 2.302585f, 2.397895f, 2.484907f, 2.564949f,
+ 2.639057f, 2.708050f, 2.772589f, 2.833213f, 2.890372f, 2.944439f, 2.995732f,
+ 3.044522f, 3.091043f, 3.135494f, 3.178054f, 3.218876f, 3.258097f, 3.295837f,
+ 3.332205f, 3.367296f, 3.401197f, 3.433987f, 3.465736f, 3.496507f, 3.526361f,
+ 3.555348f, 3.583519f, 3.610918f, 3.637586f, 3.663562f, 3.688879f, 3.713572f,
+ 3.737669f, 3.761200f, 3.784190f, 3.806663f, 3.828641f, 3.850147f, 3.871201f,
+ 3.891820f, 3.912023f, 3.931826f, 3.951244f, 3.970292f, 3.988984f, 4.007333f,
+ 4.025352f, 4.043051f, 4.060443f, 4.077538f, 4.094345f, 4.110874f, 4.127134f,
+ 4.143135f, 4.158883f, 4.174387f, 4.189655f, 4.204693f, 4.219508f, 4.234107f,
+ 4.248495f, 4.262680f, 4.276666f, 4.290460f, 4.304065f, 4.317488f, 4.330733f,
+ 4.343805f, 4.356709f, 4.369448f, 4.382027f, 4.394449f, 4.406719f, 4.418841f,
+ 4.430817f, 4.442651f, 4.454347f, 4.465908f, 4.477337f, 4.488636f, 4.499810f,
+ 4.510859f, 4.521789f, 4.532599f, 4.543295f, 4.553877f, 4.564348f, 4.574711f,
+ 4.584968f, 4.595119f, 4.605170f, 4.615121f, 4.624973f, 4.634729f, 4.644391f,
+ 4.653960f, 4.663439f, 4.672829f, 4.682131f, 4.691348f, 4.700480f, 4.709530f,
+ 4.718499f, 4.727388f, 4.736198f, 4.744932f, 4.753591f, 4.762174f, 4.770685f,
+ 4.779124f, 4.787492f, 4.795791f, 4.804021f, 4.812184f, 4.820282f, 4.828314f,
+ 4.836282f, 4.844187f, 4.852030f};
+
+} // namespace
+
+NoiseEstimator::NoiseEstimator(const SuppressionParams& suppression_params)
+ : suppression_params_(suppression_params) {
+ noise_spectrum_.fill(0.f);
+ prev_noise_spectrum_.fill(0.f);
+ conservative_noise_spectrum_.fill(0.f);
+ parametric_noise_spectrum_.fill(0.f);
+}
+
+void NoiseEstimator::PrepareAnalysis() {
+ std::copy(noise_spectrum_.begin(), noise_spectrum_.end(),
+ prev_noise_spectrum_.begin());
+}
+
+void NoiseEstimator::PreUpdate(
+ int32_t num_analyzed_frames,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum) {
+ quantile_noise_estimator_.Estimate(signal_spectrum, noise_spectrum_);
+
+ if (num_analyzed_frames < kShortStartupPhaseBlocks) {
+ // Compute simplified noise model during startup.
+ const size_t kStartBand = 5;
+ float sum_log_i_log_magn = 0.f;
+ float sum_log_i = 0.f;
+ float sum_log_i_square = 0.f;
+ float sum_log_magn = 0.f;
+ for (size_t i = kStartBand; i < kFftSizeBy2Plus1; ++i) {
+ float log_i = log_table[i];
+ sum_log_i += log_i;
+ sum_log_i_square += log_i * log_i;
+ float log_signal = LogApproximation(signal_spectrum[i]);
+ sum_log_magn += log_signal;
+ sum_log_i_log_magn += log_i * log_signal;
+ }
+
+ // Estimate the parameter for the level of the white noise.
+ constexpr float kOneByFftSizeBy2Plus1 = 1.f / kFftSizeBy2Plus1;
+ white_noise_level_ += signal_spectral_sum * kOneByFftSizeBy2Plus1 *
+ suppression_params_.over_subtraction_factor;
+
+ // Estimate pink noise parameters.
+ float denom = sum_log_i_square * (kFftSizeBy2Plus1 - kStartBand) -
+ sum_log_i * sum_log_i;
+ float num =
+ sum_log_i_square * sum_log_magn - sum_log_i * sum_log_i_log_magn;
+ RTC_DCHECK_NE(denom, 0.f);
+ float pink_noise_adjustment = num / denom;
+
+ // Constrain the estimated spectrum to be positive.
+ pink_noise_adjustment = std::max(pink_noise_adjustment, 0.f);
+ pink_noise_numerator_ += pink_noise_adjustment;
+ num = sum_log_i * sum_log_magn -
+ (kFftSizeBy2Plus1 - kStartBand) * sum_log_i_log_magn;
+ RTC_DCHECK_NE(denom, 0.f);
+ pink_noise_adjustment = num / denom;
+
+ // Constrain the pink noise power to be in the interval [0, 1].
+ pink_noise_adjustment = std::max(std::min(pink_noise_adjustment, 1.f), 0.f);
+
+ pink_noise_exp_ += pink_noise_adjustment;
+
+ const float one_by_num_analyzed_frames_plus_1 =
+ 1.f / (num_analyzed_frames + 1.f);
+
+ // Calculate the frequency-independent parts of parametric noise estimate.
+ float parametric_exp = 0.f;
+ float parametric_num = 0.f;
+ if (pink_noise_exp_ > 0.f) {
+ // Use pink noise estimate.
+ parametric_num = ExpApproximation(pink_noise_numerator_ *
+ one_by_num_analyzed_frames_plus_1);
+ parametric_num *= num_analyzed_frames + 1.f;
+ parametric_exp = pink_noise_exp_ * one_by_num_analyzed_frames_plus_1;
+ }
+
+ constexpr float kOneByShortStartupPhaseBlocks =
+ 1.f / kShortStartupPhaseBlocks;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ // Estimate the background noise using the white and pink noise
+ // parameters.
+ if (pink_noise_exp_ == 0.f) {
+ // Use white noise estimate.
+ parametric_noise_spectrum_[i] = white_noise_level_;
+ } else {
+ // Use pink noise estimate.
+ float use_band = i < kStartBand ? kStartBand : i;
+ float denom = PowApproximation(use_band, parametric_exp);
+ RTC_DCHECK_NE(denom, 0.f);
+ parametric_noise_spectrum_[i] = parametric_num / denom;
+ }
+ }
+
+ // Weight quantile noise with modeled noise.
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ noise_spectrum_[i] *= num_analyzed_frames;
+ float tmp = parametric_noise_spectrum_[i] *
+ (kShortStartupPhaseBlocks - num_analyzed_frames);
+ noise_spectrum_[i] += tmp * one_by_num_analyzed_frames_plus_1;
+ noise_spectrum_[i] *= kOneByShortStartupPhaseBlocks;
+ }
+ }
+}
+
+void NoiseEstimator::PostUpdate(
+ rtc::ArrayView<const float> speech_probability,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum) {
+ // Time-avg parameter for noise_spectrum update.
+ constexpr float kNoiseUpdate = 0.9f;
+
+ float gamma = kNoiseUpdate;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ const float prob_speech = speech_probability[i];
+ const float prob_non_speech = 1.f - prob_speech;
+
+ // Temporary noise update used for speech frames if update value is less
+ // than previous.
+ float noise_update_tmp =
+ gamma * prev_noise_spectrum_[i] +
+ (1.f - gamma) * (prob_non_speech * signal_spectrum[i] +
+ prob_speech * prev_noise_spectrum_[i]);
+
+ // Time-constant based on speech/noise_spectrum state.
+ float gamma_old = gamma;
+
+ // Increase gamma for frame likely to be seech.
+ constexpr float kProbRange = .2f;
+ gamma = prob_speech > kProbRange ? .99f : kNoiseUpdate;
+
+ // Conservative noise_spectrum update.
+ if (prob_speech < kProbRange) {
+ conservative_noise_spectrum_[i] +=
+ 0.05f * (signal_spectrum[i] - conservative_noise_spectrum_[i]);
+ }
+
+ // Noise_spectrum update.
+ if (gamma == gamma_old) {
+ noise_spectrum_[i] = noise_update_tmp;
+ } else {
+ noise_spectrum_[i] =
+ gamma * prev_noise_spectrum_[i] +
+ (1.f - gamma) * (prob_non_speech * signal_spectrum[i] +
+ prob_speech * prev_noise_spectrum_[i]);
+ // Allow for noise_spectrum update downwards: If noise_spectrum update
+ // decreases the noise_spectrum, it is safe, so allow it to happen.
+ noise_spectrum_[i] = std::min(noise_spectrum_[i], noise_update_tmp);
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/noise_estimator.h b/modules/audio_processing/ns/noise_estimator.h
new file mode 100644
index 0000000..0c0466a
--- /dev/null
+++ b/modules/audio_processing/ns/noise_estimator.h
@@ -0,0 +1,77 @@
+/*
+ * 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_NS_NOISE_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_NS_NOISE_ESTIMATOR_H_
+
+#include <array>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/ns_common.h"
+#include "modules/audio_processing/ns/quantile_noise_estimator.h"
+#include "modules/audio_processing/ns/suppression_params.h"
+
+namespace webrtc {
+
+// Class for estimating the spectral characteristics of the noise in an incoming
+// signal.
+class NoiseEstimator {
+ public:
+ explicit NoiseEstimator(const SuppressionParams& suppression_params);
+
+ // Prepare the estimator for analysis of a new frame.
+ void PrepareAnalysis();
+
+ // Performs the first step of the estimator update.
+ void PreUpdate(int32_t num_analyzed_frames,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum);
+
+ // Performs the second step of the estimator update.
+ void PostUpdate(
+ rtc::ArrayView<const float> speech_probability,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum);
+
+ // Returns the noise spectral estimate.
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> get_noise_spectrum() const {
+ return noise_spectrum_;
+ }
+
+ // Returns the noise from the previous frame.
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> get_prev_noise_spectrum()
+ const {
+ return prev_noise_spectrum_;
+ }
+
+ // Returns a noise spectral estimate based on white and pink noise parameters.
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> get_parametric_noise_spectrum()
+ const {
+ return parametric_noise_spectrum_;
+ }
+ rtc::ArrayView<const float, kFftSizeBy2Plus1>
+ get_conservative_noise_spectrum() const {
+ return conservative_noise_spectrum_;
+ }
+
+ private:
+ const SuppressionParams& suppression_params_;
+ float white_noise_level_ = 0.f;
+ float pink_noise_numerator_ = 0.f;
+ float pink_noise_exp_ = 0.f;
+ std::array<float, kFftSizeBy2Plus1> prev_noise_spectrum_;
+ std::array<float, kFftSizeBy2Plus1> conservative_noise_spectrum_;
+ std::array<float, kFftSizeBy2Plus1> parametric_noise_spectrum_;
+ std::array<float, kFftSizeBy2Plus1> noise_spectrum_;
+ QuantileNoiseEstimator quantile_noise_estimator_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_NOISE_ESTIMATOR_H_
diff --git a/modules/audio_processing/ns/noise_suppressor.cc b/modules/audio_processing/ns/noise_suppressor.cc
new file mode 100644
index 0000000..89e1fe0
--- /dev/null
+++ b/modules/audio_processing/ns/noise_suppressor.cc
@@ -0,0 +1,549 @@
+/*
+ * 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/ns/noise_suppressor.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+#include "modules/audio_processing/ns/fast_math.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+
+// Maps sample rate to number of bands.
+size_t NumBandsForRate(size_t sample_rate_hz) {
+ RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000 ||
+ sample_rate_hz == 48000);
+ return sample_rate_hz / 16000;
+}
+
+// Maximum number of channels for which the channel data is stored on
+// the stack. If the number of channels are larger than this, they are stored
+// using scratch memory that is pre-allocated on the heap. The reason for this
+// partitioning is not to waste heap space for handling the more common numbers
+// of channels, while at the same time not limiting the support for higher
+// numbers of channels by enforcing the channel data to be stored on the
+// stack using a fixed maximum value.
+constexpr size_t kMaxNumChannelsOnStack = 2;
+
+// Chooses the number of channels to store on the heap when that is required due
+// to the number of channels being larger than the pre-defined number
+// of channels to store on the stack.
+size_t NumChannelsOnHeap(size_t num_channels) {
+ return num_channels > kMaxNumChannelsOnStack ? num_channels : 0;
+}
+
+// Hybrib Hanning and flat window for the filterbank.
+constexpr std::array<float, 96> kBlocks160w256FirstHalf = {
+ 0.00000000f, 0.01636173f, 0.03271908f, 0.04906767f, 0.06540313f,
+ 0.08172107f, 0.09801714f, 0.11428696f, 0.13052619f, 0.14673047f,
+ 0.16289547f, 0.17901686f, 0.19509032f, 0.21111155f, 0.22707626f,
+ 0.24298018f, 0.25881905f, 0.27458862f, 0.29028468f, 0.30590302f,
+ 0.32143947f, 0.33688985f, 0.35225005f, 0.36751594f, 0.38268343f,
+ 0.39774847f, 0.41270703f, 0.42755509f, 0.44228869f, 0.45690388f,
+ 0.47139674f, 0.48576339f, 0.50000000f, 0.51410274f, 0.52806785f,
+ 0.54189158f, 0.55557023f, 0.56910015f, 0.58247770f, 0.59569930f,
+ 0.60876143f, 0.62166057f, 0.63439328f, 0.64695615f, 0.65934582f,
+ 0.67155895f, 0.68359230f, 0.69544264f, 0.70710678f, 0.71858162f,
+ 0.72986407f, 0.74095113f, 0.75183981f, 0.76252720f, 0.77301045f,
+ 0.78328675f, 0.79335334f, 0.80320753f, 0.81284668f, 0.82226822f,
+ 0.83146961f, 0.84044840f, 0.84920218f, 0.85772861f, 0.86602540f,
+ 0.87409034f, 0.88192126f, 0.88951608f, 0.89687274f, 0.90398929f,
+ 0.91086382f, 0.91749450f, 0.92387953f, 0.93001722f, 0.93590593f,
+ 0.94154407f, 0.94693013f, 0.95206268f, 0.95694034f, 0.96156180f,
+ 0.96592583f, 0.97003125f, 0.97387698f, 0.97746197f, 0.98078528f,
+ 0.98384601f, 0.98664333f, 0.98917651f, 0.99144486f, 0.99344778f,
+ 0.99518473f, 0.99665524f, 0.99785892f, 0.99879546f, 0.99946459f,
+ 0.99986614f};
+
+// Applies the filterbank window to a buffer.
+void ApplyFilterBankWindow(rtc::ArrayView<float, kFftSize> x) {
+ for (size_t i = 0; i < 96; ++i) {
+ x[i] = kBlocks160w256FirstHalf[i] * x[i];
+ }
+
+ for (size_t i = 161, k = 95; i < kFftSize; ++i, --k) {
+ RTC_DCHECK_NE(0, k);
+ x[i] = kBlocks160w256FirstHalf[k] * x[i];
+ }
+}
+
+// Extends a frame with previous data.
+void FormExtendedFrame(rtc::ArrayView<const float, kNsFrameSize> frame,
+ rtc::ArrayView<float, kFftSize - kNsFrameSize> old_data,
+ rtc::ArrayView<float, kFftSize> extended_frame) {
+ std::copy(old_data.begin(), old_data.end(), extended_frame.begin());
+ std::copy(frame.begin(), frame.end(),
+ extended_frame.begin() + old_data.size());
+ std::copy(extended_frame.end() - old_data.size(), extended_frame.end(),
+ old_data.begin());
+}
+
+// Uses overlap-and-add to produce an output frame.
+void OverlapAndAdd(rtc::ArrayView<const float, kFftSize> extended_frame,
+ rtc::ArrayView<float, kOverlapSize> overlap_memory,
+ rtc::ArrayView<float, kNsFrameSize> output_frame) {
+ for (size_t i = 0; i < kOverlapSize; ++i) {
+ output_frame[i] = overlap_memory[i] + extended_frame[i];
+ }
+ std::copy(extended_frame.begin() + kOverlapSize,
+ extended_frame.begin() + kNsFrameSize,
+ output_frame.begin() + kOverlapSize);
+ std::copy(extended_frame.begin() + kNsFrameSize, extended_frame.end(),
+ overlap_memory.begin());
+}
+
+// Produces a delayed frame.
+void DelaySignal(rtc::ArrayView<const float, kNsFrameSize> frame,
+ rtc::ArrayView<float, kFftSize - kNsFrameSize> delay_buffer,
+ rtc::ArrayView<float, kNsFrameSize> delayed_frame) {
+ constexpr size_t kSamplesFromFrame = kNsFrameSize - (kFftSize - kNsFrameSize);
+ std::copy(delay_buffer.begin(), delay_buffer.end(), delayed_frame.begin());
+ std::copy(frame.begin(), frame.begin() + kSamplesFromFrame,
+ delayed_frame.begin() + delay_buffer.size());
+
+ std::copy(frame.begin() + kSamplesFromFrame, frame.end(),
+ delay_buffer.begin());
+}
+
+// Computes the energy of an extended frame.
+float ComputeEnergyOfExtendedFrame(rtc::ArrayView<const float, kFftSize> x) {
+ float energy = 0.f;
+ for (float x_k : x) {
+ energy += x_k * x_k;
+ }
+
+ return energy;
+}
+
+// Computes the energy of an extended frame based on its subcomponents.
+float ComputeEnergyOfExtendedFrame(
+ rtc::ArrayView<const float, kNsFrameSize> frame,
+ rtc::ArrayView<float, kFftSize - kNsFrameSize> old_data) {
+ float energy = 0.f;
+ for (float v : old_data) {
+ energy += v * v;
+ }
+ for (float v : frame) {
+ energy += v * v;
+ }
+
+ return energy;
+}
+
+// Computes the magnitude spectrum based on an FFT output.
+void ComputeMagnitudeSpectrum(
+ rtc::ArrayView<const float, kFftSize> real,
+ rtc::ArrayView<const float, kFftSize> imag,
+ rtc::ArrayView<float, kFftSizeBy2Plus1> signal_spectrum) {
+ signal_spectrum[0] = fabsf(real[0]) + 1.f;
+ signal_spectrum[kFftSizeBy2Plus1 - 1] =
+ fabsf(real[kFftSizeBy2Plus1 - 1]) + 1.f;
+
+ for (size_t i = 1; i < kFftSizeBy2Plus1 - 1; ++i) {
+ signal_spectrum[i] =
+ SqrtFastApproximation(real[i] * real[i] + imag[i] * imag[i]) + 1.f;
+ }
+}
+
+// Compute prior and post SNR.
+void ComputeSnr(rtc::ArrayView<const float, kFftSizeBy2Plus1> filter,
+ rtc::ArrayView<const float> prev_signal_spectrum,
+ rtc::ArrayView<const float> signal_spectrum,
+ rtc::ArrayView<const float> prev_noise_spectrum,
+ rtc::ArrayView<const float> noise_spectrum,
+ rtc::ArrayView<float> prior_snr,
+ rtc::ArrayView<float> post_snr) {
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ // Previous post SNR.
+ // Previous estimate: based on previous frame with gain filter.
+ float prev_estimate = prev_signal_spectrum[i] /
+ (prev_noise_spectrum[i] + 0.0001f) * filter[i];
+ // Post SNR.
+ if (signal_spectrum[i] > noise_spectrum[i]) {
+ post_snr[i] = signal_spectrum[i] / (noise_spectrum[i] + 0.0001f) - 1.f;
+ } else {
+ post_snr[i] = 0.f;
+ }
+ // The directed decision estimate of the prior SNR is a sum the current and
+ // previous estimates.
+ prior_snr[i] = 0.98f * prev_estimate + (1.f - 0.98f) * post_snr[i];
+ }
+}
+
+// Computes the attenuating gain for the noise suppression of the upper bands.
+float ComputeUpperBandsGain(
+ float minimum_attenuating_gain,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> filter,
+ rtc::ArrayView<const float> speech_probability,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prev_analysis_signal_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum) {
+ // Average speech prob and filter gain for the end of the lowest band.
+ constexpr int kNumAvgBins = 32;
+ constexpr float kOneByNumAvgBins = 1.f / kNumAvgBins;
+
+ float avg_prob_speech = 0.f;
+ float avg_filter_gain = 0.f;
+ for (size_t i = kFftSizeBy2Plus1 - kNumAvgBins - 1; i < kFftSizeBy2Plus1 - 1;
+ i++) {
+ avg_prob_speech += speech_probability[i];
+ avg_filter_gain += filter[i];
+ }
+ avg_prob_speech = avg_prob_speech * kOneByNumAvgBins;
+ avg_filter_gain = avg_filter_gain * kOneByNumAvgBins;
+
+ // If the speech was suppressed by a component between Analyze and Process, an
+ // example being by an AEC, it should not be considered speech for the purpose
+ // of high band suppression. To that end, the speech probability is scaled
+ // accordingly.
+ float sum_analysis_spectrum = 0.f;
+ float sum_processing_spectrum = 0.f;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ sum_analysis_spectrum += prev_analysis_signal_spectrum[i];
+ sum_processing_spectrum += signal_spectrum[i];
+ }
+
+ // The magnitude spectrum computation enforces the spectrum to be strictly
+ // positive.
+ RTC_DCHECK_GT(sum_analysis_spectrum, 0.f);
+ avg_prob_speech *= sum_processing_spectrum / sum_analysis_spectrum;
+
+ // Compute gain based on speech probability.
+ float gain =
+ 0.5f * (1.f + static_cast<float>(tanh(2.f * avg_prob_speech - 1.f)));
+
+ // Combine gain with low band gain.
+ if (avg_prob_speech >= 0.5f) {
+ gain = 0.25f * gain + 0.75f * avg_filter_gain;
+ } else {
+ gain = 0.5f * gain + 0.5f * avg_filter_gain;
+ }
+
+ // Make sure gain is within flooring range.
+ return std::min(std::max(gain, minimum_attenuating_gain), 1.f);
+}
+
+} // namespace
+
+NoiseSuppressor::ChannelState::ChannelState(
+ const SuppressionParams& suppression_params,
+ size_t num_bands)
+ : wiener_filter(suppression_params),
+ noise_estimator(suppression_params),
+ process_delay_memory(num_bands > 1 ? num_bands - 1 : 0) {
+ analyze_analysis_memory.fill(0.f);
+ prev_analysis_signal_spectrum.fill(1.f);
+ process_analysis_memory.fill(0.f);
+ process_synthesis_memory.fill(0.f);
+ for (auto& d : process_delay_memory) {
+ d.fill(0.f);
+ }
+}
+
+NoiseSuppressor::NoiseSuppressor(const NsConfig& config,
+ size_t sample_rate_hz,
+ size_t num_channels)
+ : num_bands_(NumBandsForRate(sample_rate_hz)),
+ num_channels_(num_channels),
+ suppression_params_(config.target_level),
+ filter_bank_states_heap_(NumChannelsOnHeap(num_channels_)),
+ upper_band_gains_heap_(NumChannelsOnHeap(num_channels_)),
+ energies_before_filtering_heap_(NumChannelsOnHeap(num_channels_)),
+ gain_adjustments_heap_(NumChannelsOnHeap(num_channels_)),
+ channels_(num_channels_) {
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ channels_[ch] =
+ std::make_unique<ChannelState>(suppression_params_, num_bands_);
+ }
+}
+
+void NoiseSuppressor::AggregateWienerFilters(
+ rtc::ArrayView<float, kFftSizeBy2Plus1> filter) const {
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> filter0 =
+ channels_[0]->wiener_filter.get_filter();
+ std::copy(filter0.begin(), filter0.end(), filter.begin());
+
+ for (size_t ch = 1; ch < num_channels_; ++ch) {
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> filter_ch =
+ channels_[ch]->wiener_filter.get_filter();
+
+ for (size_t k = 0; k < kFftSizeBy2Plus1; ++k) {
+ filter[k] = std::min(filter[k], filter_ch[k]);
+ }
+ }
+}
+
+void NoiseSuppressor::Analyze(const AudioBuffer& audio) {
+ // Prepare the noise estimator for the analysis stage.
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ channels_[ch]->noise_estimator.PrepareAnalysis();
+ }
+
+ // Check for zero frames.
+ bool zero_frame = true;
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ rtc::ArrayView<const float, kNsFrameSize> y_band0(
+ &audio.split_bands_const(ch)[0][0], kNsFrameSize);
+ float energy = ComputeEnergyOfExtendedFrame(
+ y_band0, channels_[ch]->analyze_analysis_memory);
+ if (energy > 0.f) {
+ zero_frame = false;
+ break;
+ }
+ }
+
+ if (zero_frame) {
+ // 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.
+ return;
+ }
+
+ // Only update analysis counter for frames that are properly analyzed.
+ if (++num_analyzed_frames_ < 0) {
+ num_analyzed_frames_ = 0;
+ }
+
+ // Analyze all channels.
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ std::unique_ptr<ChannelState>& ch_p = channels_[ch];
+ rtc::ArrayView<const float, kNsFrameSize> y_band0(
+ &audio.split_bands_const(ch)[0][0], kNsFrameSize);
+
+ // Form an extended frame and apply analysis filter bank windowing.
+ std::array<float, kFftSize> extended_frame;
+ FormExtendedFrame(y_band0, ch_p->analyze_analysis_memory, extended_frame);
+ ApplyFilterBankWindow(extended_frame);
+
+ // Compute the magnitude spectrum.
+ std::array<float, kFftSize> real;
+ std::array<float, kFftSize> imag;
+ fft_.Fft(extended_frame, real, imag);
+
+ std::array<float, kFftSizeBy2Plus1> signal_spectrum;
+ ComputeMagnitudeSpectrum(real, imag, signal_spectrum);
+
+ // Compute energies.
+ float signal_energy = 0.f;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ signal_energy += real[i] * real[i] + imag[i] * imag[i];
+ }
+ signal_energy /= kFftSizeBy2Plus1;
+
+ float signal_spectral_sum = 0.f;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ signal_spectral_sum += signal_spectrum[i];
+ }
+
+ // Estimate the noise spectra and the probability estimates of speech
+ // presence.
+ ch_p->noise_estimator.PreUpdate(num_analyzed_frames_, signal_spectrum,
+ signal_spectral_sum);
+
+ std::array<float, kFftSizeBy2Plus1> post_snr;
+ std::array<float, kFftSizeBy2Plus1> prior_snr;
+ ComputeSnr(ch_p->wiener_filter.get_filter(),
+ ch_p->prev_analysis_signal_spectrum, signal_spectrum,
+ ch_p->noise_estimator.get_prev_noise_spectrum(),
+ ch_p->noise_estimator.get_noise_spectrum(), prior_snr, post_snr);
+
+ ch_p->speech_probability_estimator.Update(
+ num_analyzed_frames_, prior_snr, post_snr,
+ ch_p->noise_estimator.get_conservative_noise_spectrum(),
+ signal_spectrum, signal_spectral_sum, signal_energy);
+
+ ch_p->noise_estimator.PostUpdate(
+ ch_p->speech_probability_estimator.get_probability(), signal_spectrum);
+
+ // Store the magnitude spectrum to make it avalilable for the process
+ // method.
+ std::copy(signal_spectrum.begin(), signal_spectrum.end(),
+ ch_p->prev_analysis_signal_spectrum.begin());
+ }
+}
+
+void NoiseSuppressor::Process(AudioBuffer* audio) {
+ // Select the space for storing data during the processing.
+ std::array<FilterBankState, kMaxNumChannelsOnStack> filter_bank_states_stack;
+ rtc::ArrayView<FilterBankState> filter_bank_states(
+ filter_bank_states_stack.data(), num_channels_);
+ std::array<float, kMaxNumChannelsOnStack> upper_band_gains_stack;
+ rtc::ArrayView<float> upper_band_gains(upper_band_gains_stack.data(),
+ num_channels_);
+ std::array<float, kMaxNumChannelsOnStack> energies_before_filtering_stack;
+ rtc::ArrayView<float> energies_before_filtering(
+ energies_before_filtering_stack.data(), num_channels_);
+ std::array<float, kMaxNumChannelsOnStack> gain_adjustments_stack;
+ rtc::ArrayView<float> gain_adjustments(gain_adjustments_stack.data(),
+ num_channels_);
+ if (NumChannelsOnHeap(num_channels_) > 0) {
+ // If the stack-allocated space is too small, use the heap for storing the
+ // data.
+ filter_bank_states = rtc::ArrayView<FilterBankState>(
+ filter_bank_states_heap_.data(), num_channels_);
+ upper_band_gains =
+ rtc::ArrayView<float>(upper_band_gains_heap_.data(), num_channels_);
+ energies_before_filtering = rtc::ArrayView<float>(
+ energies_before_filtering_heap_.data(), num_channels_);
+ gain_adjustments =
+ rtc::ArrayView<float>(gain_adjustments_heap_.data(), num_channels_);
+ }
+
+ // Compute the suppression filters for all channels.
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ // Form an extended frame and apply analysis filter bank windowing.
+ rtc::ArrayView<float, kNsFrameSize> y_band0(&audio->split_bands(ch)[0][0],
+ kNsFrameSize);
+
+ FormExtendedFrame(y_band0, channels_[ch]->process_analysis_memory,
+ filter_bank_states[ch].extended_frame);
+
+ ApplyFilterBankWindow(filter_bank_states[ch].extended_frame);
+
+ energies_before_filtering[ch] =
+ ComputeEnergyOfExtendedFrame(filter_bank_states[ch].extended_frame);
+
+ // Perform filter bank analysis and compute the magnitude spectrum.
+ fft_.Fft(filter_bank_states[ch].extended_frame, filter_bank_states[ch].real,
+ filter_bank_states[ch].imag);
+
+ std::array<float, kFftSizeBy2Plus1> signal_spectrum;
+ ComputeMagnitudeSpectrum(filter_bank_states[ch].real,
+ filter_bank_states[ch].imag, signal_spectrum);
+
+ // Compute the frequency domain gain filter for noise attenuation.
+ channels_[ch]->wiener_filter.Update(
+ num_analyzed_frames_,
+ channels_[ch]->noise_estimator.get_noise_spectrum(),
+ channels_[ch]->noise_estimator.get_prev_noise_spectrum(),
+ channels_[ch]->noise_estimator.get_parametric_noise_spectrum(),
+ signal_spectrum);
+
+ if (num_bands_ > 1) {
+ // Compute the time-domain gain for attenuating the noise in the upper
+ // bands.
+
+ upper_band_gains[ch] = ComputeUpperBandsGain(
+ suppression_params_.minimum_attenuating_gain,
+ channels_[ch]->wiener_filter.get_filter(),
+ channels_[ch]->speech_probability_estimator.get_probability(),
+ channels_[ch]->prev_analysis_signal_spectrum, signal_spectrum);
+ }
+ }
+
+ // Aggregate the Wiener filters for all channels.
+ std::array<float, kFftSizeBy2Plus1> filter_data;
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> filter = filter_data;
+ if (num_channels_ == 1) {
+ filter = channels_[0]->wiener_filter.get_filter();
+ } else {
+ AggregateWienerFilters(filter_data);
+ }
+
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ // Apply the filter to the lower band.
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ filter_bank_states[ch].real[i] *= filter[i];
+ filter_bank_states[ch].imag[i] *= filter[i];
+ }
+ }
+
+ // Perform filter bank synthesis
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ fft_.Ifft(filter_bank_states[ch].real, filter_bank_states[ch].imag,
+ filter_bank_states[ch].extended_frame);
+ }
+
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ const float energy_after_filtering =
+ ComputeEnergyOfExtendedFrame(filter_bank_states[ch].extended_frame);
+
+ // Apply synthesis window.
+ ApplyFilterBankWindow(filter_bank_states[ch].extended_frame);
+
+ // Compute the adjustment of the noise attenuation filter based on the
+ // effect of the attenuation.
+ gain_adjustments[ch] =
+ channels_[ch]->wiener_filter.ComputeOverallScalingFactor(
+ num_analyzed_frames_,
+ channels_[ch]->speech_probability_estimator.get_prior_probability(),
+ energies_before_filtering[ch], energy_after_filtering);
+ }
+
+ // Select and apply adjustment of the noise attenuation filter based on the
+ // effect of the attenuation.
+ float gain_adjustment = gain_adjustments[0];
+ for (size_t ch = 1; ch < num_channels_; ++ch) {
+ gain_adjustment = std::min(gain_adjustment, gain_adjustments[ch]);
+ }
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ for (size_t i = 0; i < kFftSize; ++i) {
+ filter_bank_states[ch].extended_frame[i] =
+ gain_adjustment * filter_bank_states[ch].extended_frame[i];
+ }
+ }
+
+ // Use overlap-and-add to form the output frame of the lowest band.
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ rtc::ArrayView<float, kNsFrameSize> y_band0(&audio->split_bands(ch)[0][0],
+ kNsFrameSize);
+ OverlapAndAdd(filter_bank_states[ch].extended_frame,
+ channels_[ch]->process_synthesis_memory, y_band0);
+ }
+
+ if (num_bands_ > 1) {
+ // Select the noise attenuating gain to apply to the upper band.
+ float upper_band_gain = upper_band_gains[0];
+ for (size_t ch = 1; ch < num_channels_; ++ch) {
+ upper_band_gain = std::min(upper_band_gain, upper_band_gains[ch]);
+ }
+
+ // Process the upper bands.
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ for (size_t b = 1; b < num_bands_; ++b) {
+ // Delay the upper bands to match the delay of the filterbank applied to
+ // the lowest band.
+ rtc::ArrayView<float, kNsFrameSize> y_band(
+ &audio->split_bands(ch)[b][0], kNsFrameSize);
+ std::array<float, kNsFrameSize> delayed_frame;
+ DelaySignal(y_band, channels_[ch]->process_delay_memory[b - 1],
+ delayed_frame);
+
+ // Apply the time-domain noise-attenuating gain.
+ for (size_t j = 0; j < kNsFrameSize; j++) {
+ y_band[j] = upper_band_gain * delayed_frame[j];
+ }
+ }
+ }
+ }
+
+ // Limit the output the allowed range.
+ for (size_t ch = 0; ch < num_channels_; ++ch) {
+ for (size_t b = 0; b < num_bands_; ++b) {
+ rtc::ArrayView<float, kNsFrameSize> y_band(&audio->split_bands(ch)[b][0],
+ kNsFrameSize);
+ for (size_t j = 0; j < kNsFrameSize; j++) {
+ y_band[j] = std::min(std::max(y_band[j], -32768.f), 32767.f);
+ }
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/noise_suppressor.h b/modules/audio_processing/ns/noise_suppressor.h
new file mode 100644
index 0000000..d962886
--- /dev/null
+++ b/modules/audio_processing/ns/noise_suppressor.h
@@ -0,0 +1,83 @@
+/*
+ * 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_NS_NOISE_SUPPRESSOR_H_
+#define MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/audio_buffer.h"
+#include "modules/audio_processing/ns/noise_estimator.h"
+#include "modules/audio_processing/ns/ns_common.h"
+#include "modules/audio_processing/ns/ns_config.h"
+#include "modules/audio_processing/ns/ns_fft.h"
+#include "modules/audio_processing/ns/speech_probability_estimator.h"
+#include "modules/audio_processing/ns/wiener_filter.h"
+
+namespace webrtc {
+
+// Class for suppressing noise in a signal.
+class NoiseSuppressor {
+ public:
+ NoiseSuppressor(const NsConfig& config,
+ size_t sample_rate_hz,
+ size_t num_channels);
+ NoiseSuppressor(const NoiseSuppressor&) = delete;
+ NoiseSuppressor& operator=(const NoiseSuppressor&) = delete;
+
+ // Analyses the signal (typically applied before the AEC to avoid analyzing
+ // any comfort noise signal).
+ void Analyze(const AudioBuffer& audio);
+
+ // Applies noise suppression.
+ void Process(AudioBuffer* audio);
+
+ private:
+ const size_t num_bands_;
+ const size_t num_channels_;
+ const SuppressionParams suppression_params_;
+ int32_t num_analyzed_frames_ = -1;
+ NrFft fft_;
+
+ struct ChannelState {
+ ChannelState(const SuppressionParams& suppression_params, size_t num_bands);
+
+ SpeechProbabilityEstimator speech_probability_estimator;
+ WienerFilter wiener_filter;
+ NoiseEstimator noise_estimator;
+ std::array<float, kFftSizeBy2Plus1> prev_analysis_signal_spectrum;
+ std::array<float, kFftSize - kNsFrameSize> analyze_analysis_memory;
+ std::array<float, kOverlapSize> process_analysis_memory;
+ std::array<float, kOverlapSize> process_synthesis_memory;
+ std::vector<std::array<float, kOverlapSize>> process_delay_memory;
+ };
+
+ struct FilterBankState {
+ std::array<float, kFftSize> real;
+ std::array<float, kFftSize> imag;
+ std::array<float, kFftSize> extended_frame;
+ };
+
+ std::vector<FilterBankState> filter_bank_states_heap_;
+ std::vector<float> upper_band_gains_heap_;
+ std::vector<float> energies_before_filtering_heap_;
+ std::vector<float> gain_adjustments_heap_;
+ std::vector<std::unique_ptr<ChannelState>> channels_;
+
+ // Aggregates the Wiener filters into a single filter to use.
+ void AggregateWienerFilters(
+ rtc::ArrayView<float, kFftSizeBy2Plus1> filter) const;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSOR_H_
diff --git a/modules/audio_processing/ns/noise_suppressor_unittest.cc b/modules/audio_processing/ns/noise_suppressor_unittest.cc
new file mode 100644
index 0000000..28ea63a
--- /dev/null
+++ b/modules/audio_processing/ns/noise_suppressor_unittest.cc
@@ -0,0 +1,102 @@
+/*
+ * 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 "modules/audio_processing/ns/noise_suppressor.h"
+
+#include <deque>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "rtc_base/strings/string_builder.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+std::string ProduceDebugText(int sample_rate_hz,
+ size_t num_channels,
+ NsConfig::SuppressionLevel level) {
+ rtc::StringBuilder ss;
+ ss << "Sample rate: " << sample_rate_hz << ", num_channels: " << num_channels
+ << ", level: " << static_cast<int>(level);
+ return ss.Release();
+}
+
+void PopulateInputFrameWithIdenticalChannels(size_t num_channels,
+ size_t num_bands,
+ size_t frame_index,
+ AudioBuffer* audio) {
+ for (size_t ch = 0; ch < num_channels; ++ch) {
+ for (size_t b = 0; b < num_bands; ++b) {
+ for (size_t i = 0; i < 160; ++i) {
+ float value = static_cast<int>(frame_index * 160 + i);
+ audio->split_bands(ch)[b][i] = (value > 0 ? 5000 * b + value : 0);
+ }
+ }
+ }
+}
+
+void VerifyIdenticalChannels(size_t num_channels,
+ size_t num_bands,
+ size_t frame_index,
+ const AudioBuffer& audio) {
+ EXPECT_GT(num_channels, 1u);
+ for (size_t ch = 1; ch < num_channels; ++ch) {
+ for (size_t b = 0; b < num_bands; ++b) {
+ for (size_t i = 0; i < 160; ++i) {
+ EXPECT_EQ(audio.split_bands_const(ch)[b][i],
+ audio.split_bands_const(0)[b][i]);
+ }
+ }
+ }
+}
+
+} // namespace
+
+// Verifies that the same noise reduction effect is applied to all channels.
+TEST(NoiseSuppressor, IdenticalChannelEffects) {
+ for (auto rate : {16000, 32000, 48000}) {
+ for (auto num_channels : {1, 4, 8}) {
+ for (auto level :
+ {NsConfig::SuppressionLevel::k6dB, NsConfig::SuppressionLevel::k12dB,
+ NsConfig::SuppressionLevel::k18dB,
+ NsConfig::SuppressionLevel::k21dB}) {
+ SCOPED_TRACE(ProduceDebugText(rate, num_channels, level));
+
+ const size_t num_bands = rate / 16000;
+ // const int frame_length = rtc::CheckedDivExact(rate, 100);
+ AudioBuffer audio(rate, num_channels, rate, num_channels, rate,
+ num_channels);
+ NsConfig cfg;
+ NoiseSuppressor ns(cfg, rate, num_channels);
+ for (size_t frame_index = 0; frame_index < 1000; ++frame_index) {
+ if (rate > 16000) {
+ audio.SplitIntoFrequencyBands();
+ }
+
+ PopulateInputFrameWithIdenticalChannels(num_channels, num_bands,
+ frame_index, &audio);
+
+ ns.Analyze(audio);
+ ns.Process(&audio);
+ if (num_channels > 1) {
+ VerifyIdenticalChannels(num_channels, num_bands, frame_index,
+ audio);
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/ns_common.h b/modules/audio_processing/ns/ns_common.h
new file mode 100644
index 0000000..d6149f7
--- /dev/null
+++ b/modules/audio_processing/ns/ns_common.h
@@ -0,0 +1,34 @@
+/*
+ * 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_NS_NS_COMMON_H_
+#define MODULES_AUDIO_PROCESSING_NS_NS_COMMON_H_
+
+#include <cstddef>
+
+namespace webrtc {
+
+constexpr size_t kFftSize = 256;
+constexpr size_t kFftSizeBy2Plus1 = kFftSize / 2 + 1;
+constexpr size_t kNsFrameSize = 160;
+constexpr size_t kOverlapSize = kFftSize - kNsFrameSize;
+
+constexpr int kShortStartupPhaseBlocks = 50;
+constexpr int kLongStartupPhaseBlocks = 200;
+constexpr int kFeatureUpdateWindowSize = 500;
+
+constexpr float kLtrFeatureThr = 0.5f;
+constexpr float kBinSizeLrt = 0.1f;
+constexpr float kBinSizeSpecFlat = 0.05f;
+constexpr float kBinSizeSpecDiff = 0.1f;
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_NS_COMMON_H_
diff --git a/modules/audio_processing/ns/ns_config.h b/modules/audio_processing/ns/ns_config.h
new file mode 100644
index 0000000..0a285e9
--- /dev/null
+++ b/modules/audio_processing/ns/ns_config.h
@@ -0,0 +1,24 @@
+/*
+ * 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_NS_NS_CONFIG_H_
+#define MODULES_AUDIO_PROCESSING_NS_NS_CONFIG_H_
+
+namespace webrtc {
+
+// Config struct for the noise suppressor
+struct NsConfig {
+ enum class SuppressionLevel { k6dB, k12dB, k18dB, k21dB };
+ SuppressionLevel target_level = SuppressionLevel::k12dB;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_NS_CONFIG_H_
diff --git a/modules/audio_processing/ns/ns_fft.cc b/modules/audio_processing/ns/ns_fft.cc
new file mode 100644
index 0000000..8d1c43f
--- /dev/null
+++ b/modules/audio_processing/ns/ns_fft.cc
@@ -0,0 +1,64 @@
+/*
+ * 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/ns/ns_fft.h"
+
+#include "common_audio/third_party/fft4g/fft4g.h"
+
+namespace webrtc {
+
+NrFft::NrFft() : bit_reversal_state_(kFftSize / 2), tables_(kFftSize / 2) {
+ // Initialize WebRtc_rdt (setting (bit_reversal_state_[0] to 0 triggers
+ // initialization)
+ bit_reversal_state_[0] = 0.f;
+ std::array<float, kFftSize> tmp_buffer;
+ tmp_buffer.fill(0.f);
+ WebRtc_rdft(kFftSize, 1, tmp_buffer.data(), bit_reversal_state_.data(),
+ tables_.data());
+}
+
+void NrFft::Fft(rtc::ArrayView<float, kFftSize> time_data,
+ rtc::ArrayView<float, kFftSize> real,
+ rtc::ArrayView<float, kFftSize> imag) {
+ WebRtc_rdft(kFftSize, 1, time_data.data(), bit_reversal_state_.data(),
+ tables_.data());
+
+ imag[0] = 0;
+ real[0] = time_data[0];
+
+ imag[kFftSizeBy2Plus1 - 1] = 0;
+ real[kFftSizeBy2Plus1 - 1] = time_data[1];
+
+ for (size_t i = 1; i < kFftSizeBy2Plus1 - 1; ++i) {
+ real[i] = time_data[2 * i];
+ imag[i] = time_data[2 * i + 1];
+ }
+}
+
+void NrFft::Ifft(rtc::ArrayView<const float> real,
+ rtc::ArrayView<const float> imag,
+ rtc::ArrayView<float> time_data) {
+ time_data[0] = real[0];
+ time_data[1] = real[kFftSizeBy2Plus1 - 1];
+ for (size_t i = 1; i < kFftSizeBy2Plus1 - 1; ++i) {
+ time_data[2 * i] = real[i];
+ time_data[2 * i + 1] = imag[i];
+ }
+ WebRtc_rdft(kFftSize, -1, time_data.data(), bit_reversal_state_.data(),
+ tables_.data());
+
+ // Scale the output
+ constexpr float kScaling = 2.f / kFftSize;
+ for (float& d : time_data) {
+ d *= kScaling;
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/ns_fft.h b/modules/audio_processing/ns/ns_fft.h
new file mode 100644
index 0000000..539251e
--- /dev/null
+++ b/modules/audio_processing/ns/ns_fft.h
@@ -0,0 +1,45 @@
+/*
+ * 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_NS_NS_FFT_H_
+#define MODULES_AUDIO_PROCESSING_NS_NS_FFT_H_
+
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/ns_common.h"
+
+namespace webrtc {
+
+// Wrapper class providing 256 point FFT functionality.
+class NrFft {
+ public:
+ NrFft();
+ NrFft(const NrFft&) = delete;
+ NrFft& operator=(const NrFft&) = delete;
+
+ // Transforms the signal from time to frequency domain.
+ void Fft(rtc::ArrayView<float, kFftSize> time_data,
+ rtc::ArrayView<float, kFftSize> real,
+ rtc::ArrayView<float, kFftSize> imag);
+
+ // Transforms the signal from frequency to time domain.
+ void Ifft(rtc::ArrayView<const float> real,
+ rtc::ArrayView<const float> imag,
+ rtc::ArrayView<float> time_data);
+
+ private:
+ std::vector<size_t> bit_reversal_state_;
+ std::vector<float> tables_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_NS_FFT_H_
diff --git a/modules/audio_processing/ns/nsx_core.c b/modules/audio_processing/ns/nsx_core.c
deleted file mode 100644
index 8043656..0000000
--- a/modules/audio_processing/ns/nsx_core.c
+++ /dev/null
@@ -1,2107 +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/ns/noise_suppression_x.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "rtc_base/checks.h"
-#include "common_audio/signal_processing/include/real_fft.h"
-#include "modules/audio_processing/ns/nsx_core.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 short* const* speechFrame,
- int num_bands,
- short* 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 short* const* speechFrameHB = NULL;
- short* 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, (short*)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/ns/prior_signal_model.cc b/modules/audio_processing/ns/prior_signal_model.cc
new file mode 100644
index 0000000..f25a1e2
--- /dev/null
+++ b/modules/audio_processing/ns/prior_signal_model.cc
@@ -0,0 +1,18 @@
+/*
+ * 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/ns/prior_signal_model.h"
+
+namespace webrtc {
+
+PriorSignalModel::PriorSignalModel(float lrt_initial_value)
+ : lrt(lrt_initial_value) {}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/prior_signal_model.h b/modules/audio_processing/ns/prior_signal_model.h
new file mode 100644
index 0000000..dcfa7ea
--- /dev/null
+++ b/modules/audio_processing/ns/prior_signal_model.h
@@ -0,0 +1,32 @@
+/*
+ * 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_NS_PRIOR_SIGNAL_MODEL_H_
+#define MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_H_
+
+namespace webrtc {
+
+// Struct for storing the prior signal model parameters.
+struct PriorSignalModel {
+ explicit PriorSignalModel(float lrt_initial_value);
+ PriorSignalModel(const PriorSignalModel&) = delete;
+ PriorSignalModel& operator=(const PriorSignalModel&) = delete;
+
+ float lrt;
+ float flatness_threshold = .5f;
+ float template_diff_threshold = .5f;
+ float lrt_weighting = 1.f;
+ float flatness_weighting = 0.f;
+ float difference_weighting = 0.f;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_H_
diff --git a/modules/audio_processing/ns/prior_signal_model_estimator.cc b/modules/audio_processing/ns/prior_signal_model_estimator.cc
new file mode 100644
index 0000000..c814658
--- /dev/null
+++ b/modules/audio_processing/ns/prior_signal_model_estimator.cc
@@ -0,0 +1,170 @@
+/*
+ * 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/ns/prior_signal_model_estimator.h"
+
+#include <math.h>
+#include <algorithm>
+
+#include "modules/audio_processing/ns/fast_math.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+
+// Identifies the first of the two largest peaks in the histogram.
+void FindFirstOfTwoLargestPeaks(
+ float bin_size,
+ rtc::ArrayView<const int, kHistogramSize> spectral_flatness,
+ float* peak_position,
+ int* peak_weight) {
+ RTC_DCHECK(peak_position);
+ RTC_DCHECK(peak_weight);
+
+ int peak_value = 0;
+ int secondary_peak_value = 0;
+ *peak_position = 0.f;
+ float secondary_peak_position = 0.f;
+ *peak_weight = 0;
+ int secondary_peak_weight = 0;
+
+ // Identify the two largest peaks.
+ for (int i = 0; i < kHistogramSize; ++i) {
+ const float bin_mid = (i + 0.5f) * bin_size;
+ if (spectral_flatness[i] > peak_value) {
+ // Found new "first" peak candidate.
+ secondary_peak_value = peak_value;
+ secondary_peak_weight = *peak_weight;
+ secondary_peak_position = *peak_position;
+
+ peak_value = spectral_flatness[i];
+ *peak_weight = spectral_flatness[i];
+ *peak_position = bin_mid;
+ } else if (spectral_flatness[i] > secondary_peak_value) {
+ // Found new "second" peak candidate.
+ secondary_peak_value = spectral_flatness[i];
+ secondary_peak_weight = spectral_flatness[i];
+ secondary_peak_position = bin_mid;
+ }
+ }
+
+ // Merge the peaks if they are close.
+ if ((fabs(secondary_peak_position - *peak_position) < 2 * bin_size) &&
+ (secondary_peak_weight > 0.5f * (*peak_weight))) {
+ *peak_weight += secondary_peak_weight;
+ *peak_position = 0.5f * (*peak_position + secondary_peak_position);
+ }
+}
+
+void UpdateLrt(rtc::ArrayView<const int, kHistogramSize> lrt_histogram,
+ float* prior_model_lrt,
+ bool* low_lrt_fluctuations) {
+ RTC_DCHECK(prior_model_lrt);
+ RTC_DCHECK(low_lrt_fluctuations);
+
+ float average = 0.f;
+ float average_compl = 0.f;
+ float average_squared = 0.f;
+ int count = 0;
+
+ for (int i = 0; i < 10; ++i) {
+ float bin_mid = (i + 0.5f) * kBinSizeLrt;
+ average += lrt_histogram[i] * bin_mid;
+ count += lrt_histogram[i];
+ }
+ if (count > 0) {
+ average = average / count;
+ }
+
+ for (int i = 0; i < kHistogramSize; ++i) {
+ float bin_mid = (i + 0.5f) * kBinSizeLrt;
+ average_squared += lrt_histogram[i] * bin_mid * bin_mid;
+ average_compl += lrt_histogram[i] * bin_mid;
+ }
+ constexpr float kOneFeatureUpdateWindowSize = 1.f / kFeatureUpdateWindowSize;
+ average_squared = average_squared * kOneFeatureUpdateWindowSize;
+ average_compl = average_compl * kOneFeatureUpdateWindowSize;
+
+ // Fluctuation limit of LRT feature.
+ *low_lrt_fluctuations = average_squared - average * average_compl < 0.05f;
+
+ // Get threshold for LRT feature.
+ constexpr float kMaxLrt = 1.f;
+ constexpr float kMinLrt = .2f;
+ if (*low_lrt_fluctuations) {
+ // Very low fluctuation, so likely noise.
+ *prior_model_lrt = kMaxLrt;
+ } else {
+ *prior_model_lrt = std::min(kMaxLrt, std::max(kMinLrt, 1.2f * average));
+ }
+}
+
+} // namespace
+
+PriorSignalModelEstimator::PriorSignalModelEstimator(float lrt_initial_value)
+ : prior_model_(lrt_initial_value) {}
+
+// Extract thresholds for feature parameters and computes the threshold/weights.
+void PriorSignalModelEstimator::Update(const Histograms& histograms) {
+ bool low_lrt_fluctuations;
+ UpdateLrt(histograms.get_lrt(), &prior_model_.lrt, &low_lrt_fluctuations);
+
+ // For spectral flatness and spectral difference: compute the main peaks of
+ // the histograms.
+ float spectral_flatness_peak_position;
+ int spectral_flatness_peak_weight;
+ FindFirstOfTwoLargestPeaks(
+ kBinSizeSpecFlat, histograms.get_spectral_flatness(),
+ &spectral_flatness_peak_position, &spectral_flatness_peak_weight);
+
+ float spectral_diff_peak_position = 0.f;
+ int spectral_diff_peak_weight = 0;
+ FindFirstOfTwoLargestPeaks(kBinSizeSpecDiff, histograms.get_spectral_diff(),
+ &spectral_diff_peak_position,
+ &spectral_diff_peak_weight);
+
+ // Reject if weight of peaks is not large enough, or peak value too small.
+ // Peak limit for spectral flatness (varies between 0 and 1).
+ const int use_spec_flat = spectral_flatness_peak_weight < 0.3f * 500 ||
+ spectral_flatness_peak_position < 0.6f
+ ? 0
+ : 1;
+
+ // Reject if weight of peaks is not large enough or if fluctuation of the LRT
+ // feature are very low, indicating a noise state.
+ const int use_spec_diff =
+ spectral_diff_peak_weight < 0.3f * 500 || low_lrt_fluctuations ? 0 : 1;
+
+ // Update the model.
+ prior_model_.template_diff_threshold = 1.2f * spectral_diff_peak_position;
+ prior_model_.template_diff_threshold =
+ std::min(1.f, std::max(0.16f, prior_model_.template_diff_threshold));
+
+ float one_by_feature_sum = 1.f / (1.f + use_spec_flat + use_spec_diff);
+ prior_model_.lrt_weighting = one_by_feature_sum;
+
+ if (use_spec_flat == 1) {
+ prior_model_.flatness_threshold = 0.9f * spectral_flatness_peak_position;
+ prior_model_.flatness_threshold =
+ std::min(.95f, std::max(0.1f, prior_model_.flatness_threshold));
+ prior_model_.flatness_weighting = one_by_feature_sum;
+ } else {
+ prior_model_.flatness_weighting = 0.f;
+ }
+
+ if (use_spec_diff == 1) {
+ prior_model_.difference_weighting = one_by_feature_sum;
+ } else {
+ prior_model_.difference_weighting = 0.f;
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/prior_signal_model_estimator.h b/modules/audio_processing/ns/prior_signal_model_estimator.h
new file mode 100644
index 0000000..d178323
--- /dev/null
+++ b/modules/audio_processing/ns/prior_signal_model_estimator.h
@@ -0,0 +1,39 @@
+/*
+ * 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_NS_PRIOR_SIGNAL_MODEL_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_ESTIMATOR_H_
+
+#include "modules/audio_processing/ns/histograms.h"
+#include "modules/audio_processing/ns/prior_signal_model.h"
+
+namespace webrtc {
+
+// Estimator of the prior signal model parameters.
+class PriorSignalModelEstimator {
+ public:
+ explicit PriorSignalModelEstimator(float lrt_initial_value);
+ PriorSignalModelEstimator(const PriorSignalModelEstimator&) = delete;
+ PriorSignalModelEstimator& operator=(const PriorSignalModelEstimator&) =
+ delete;
+
+ // Updates the model estimate.
+ void Update(const Histograms& h);
+
+ // Returns the estimated model.
+ const PriorSignalModel& get_prior_model() const { return prior_model_; }
+
+ private:
+ PriorSignalModel prior_model_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_ESTIMATOR_H_
diff --git a/modules/audio_processing/ns/quantile_noise_estimator.cc b/modules/audio_processing/ns/quantile_noise_estimator.cc
new file mode 100644
index 0000000..bab494f
--- /dev/null
+++ b/modules/audio_processing/ns/quantile_noise_estimator.cc
@@ -0,0 +1,88 @@
+/*
+ * 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/ns/quantile_noise_estimator.h"
+
+#include <algorithm>
+
+#include "modules/audio_processing/ns/fast_math.h"
+
+namespace webrtc {
+
+QuantileNoiseEstimator::QuantileNoiseEstimator() {
+ quantile_.fill(0.f);
+ density_.fill(0.3f);
+ log_quantile_.fill(8.f);
+
+ constexpr float kOneBySimult = 1.f / kSimult;
+ for (size_t i = 0; i < kSimult; ++i) {
+ counter_[i] = floor(kLongStartupPhaseBlocks * (i + 1.f) * kOneBySimult);
+ }
+}
+
+void QuantileNoiseEstimator::Estimate(
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ rtc::ArrayView<float, kFftSizeBy2Plus1> noise_spectrum) {
+ std::array<float, kFftSizeBy2Plus1> log_spectrum;
+ LogApproximation(signal_spectrum, log_spectrum);
+
+ int quantile_index_to_return = -1;
+ // Loop over simultaneous estimates.
+ for (int s = 0, k = 0; s < kSimult;
+ ++s, k += static_cast<int>(kFftSizeBy2Plus1)) {
+ const float one_by_counter_plus_1 = 1.f / (counter_[s] + 1.f);
+ for (int i = 0, j = k; i < static_cast<int>(kFftSizeBy2Plus1); ++i, ++j) {
+ // Update log quantile estimate.
+ const float delta = density_[j] > 1.f ? 40.f / density_[j] : 40.f;
+
+ const float multiplier = delta * one_by_counter_plus_1;
+ if (log_spectrum[i] > log_quantile_[j]) {
+ log_quantile_[j] += 0.25f * multiplier;
+ } else {
+ log_quantile_[j] -= 0.75f * multiplier;
+ }
+
+ // Update density estimate.
+ constexpr float kWidth = 0.01f;
+ constexpr float kOneByWidthPlus2 = 1.f / (2.f * kWidth);
+ if (fabs(log_spectrum[i] - log_quantile_[j]) < kWidth) {
+ density_[j] = (counter_[s] * density_[j] + kOneByWidthPlus2) *
+ one_by_counter_plus_1;
+ }
+ }
+
+ if (counter_[s] >= kLongStartupPhaseBlocks) {
+ counter_[s] = 0;
+ if (num_updates_ >= kLongStartupPhaseBlocks) {
+ quantile_index_to_return = k;
+ }
+ }
+
+ ++counter_[s];
+ }
+
+ // Sequentially update the noise during startup.
+ if (num_updates_ < kLongStartupPhaseBlocks) {
+ // Use the last "s" to get noise during startup that differ from zero.
+ quantile_index_to_return = kFftSizeBy2Plus1 * (kSimult - 1);
+ ++num_updates_;
+ }
+
+ if (quantile_index_to_return >= 0) {
+ ExpApproximation(
+ rtc::ArrayView<const float>(&log_quantile_[quantile_index_to_return],
+ kFftSizeBy2Plus1),
+ quantile_);
+ }
+
+ std::copy(quantile_.begin(), quantile_.end(), noise_spectrum.begin());
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/quantile_noise_estimator.h b/modules/audio_processing/ns/quantile_noise_estimator.h
new file mode 100644
index 0000000..67d1512
--- /dev/null
+++ b/modules/audio_processing/ns/quantile_noise_estimator.h
@@ -0,0 +1,45 @@
+/*
+ * 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_NS_QUANTILE_NOISE_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_NS_QUANTILE_NOISE_ESTIMATOR_H_
+
+#include <math.h>
+#include <array>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/ns_common.h"
+
+namespace webrtc {
+
+constexpr int kSimult = 3;
+
+// For quantile noise estimation.
+class QuantileNoiseEstimator {
+ public:
+ QuantileNoiseEstimator();
+ QuantileNoiseEstimator(const QuantileNoiseEstimator&) = delete;
+ QuantileNoiseEstimator& operator=(const QuantileNoiseEstimator&) = delete;
+
+ // Estimate noise.
+ void Estimate(rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ rtc::ArrayView<float, kFftSizeBy2Plus1> noise_spectrum);
+
+ private:
+ std::array<float, kSimult * kFftSizeBy2Plus1> density_;
+ std::array<float, kSimult * kFftSizeBy2Plus1> log_quantile_;
+ std::array<float, kFftSizeBy2Plus1> quantile_;
+ std::array<int, kSimult> counter_;
+ int num_updates_ = 1;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_QUANTILE_NOISE_ESTIMATOR_H_
diff --git a/modules/audio_processing/ns/signal_model.cc b/modules/audio_processing/ns/signal_model.cc
new file mode 100644
index 0000000..364bfd0
--- /dev/null
+++ b/modules/audio_processing/ns/signal_model.cc
@@ -0,0 +1,24 @@
+/*
+ * 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/ns/signal_model.h"
+
+namespace webrtc {
+
+SignalModel::SignalModel() {
+ constexpr float kSfFeatureThr = 0.5f;
+
+ lrt = kLtrFeatureThr;
+ spectral_flatness = kSfFeatureThr;
+ spectral_diff = kSfFeatureThr;
+ avg_log_lrt.fill(kLtrFeatureThr);
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/signal_model.h b/modules/audio_processing/ns/signal_model.h
new file mode 100644
index 0000000..6614d38
--- /dev/null
+++ b/modules/audio_processing/ns/signal_model.h
@@ -0,0 +1,34 @@
+/*
+ * 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_NS_SIGNAL_MODEL_H_
+#define MODULES_AUDIO_PROCESSING_NS_SIGNAL_MODEL_H_
+
+#include <array>
+
+#include "modules/audio_processing/ns/ns_common.h"
+
+namespace webrtc {
+
+struct SignalModel {
+ SignalModel();
+ SignalModel(const SignalModel&) = delete;
+ SignalModel& operator=(const SignalModel&) = delete;
+
+ float lrt;
+ float spectral_diff;
+ float spectral_flatness;
+ // Log LRT factor with time-smoothing.
+ std::array<float, kFftSizeBy2Plus1> avg_log_lrt;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_SIGNAL_MODEL_H_
diff --git a/modules/audio_processing/ns/signal_model_estimator.cc b/modules/audio_processing/ns/signal_model_estimator.cc
new file mode 100644
index 0000000..67dd3bb
--- /dev/null
+++ b/modules/audio_processing/ns/signal_model_estimator.cc
@@ -0,0 +1,175 @@
+/*
+ * 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/ns/signal_model_estimator.h"
+
+#include "modules/audio_processing/ns/fast_math.h"
+
+namespace webrtc {
+
+namespace {
+
+constexpr float kOneByFftSizeBy2Plus1 = 1.f / kFftSizeBy2Plus1;
+
+// Computes the difference measure between input spectrum and a template/learned
+// noise spectrum.
+float ComputeSpectralDiff(
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> conservative_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum,
+ float diff_normalization) {
+ // spectral_diff = var(signal_spectrum) - cov(signal_spectrum, magnAvgPause)^2
+ // / var(magnAvgPause)
+
+ // Compute average quantities.
+ float noise_average = 0.f;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ // Conservative smooth noise spectrum from pause frames.
+ noise_average += conservative_noise_spectrum[i];
+ }
+ noise_average = noise_average * kOneByFftSizeBy2Plus1;
+ float signal_average = signal_spectral_sum * kOneByFftSizeBy2Plus1;
+
+ // Compute variance and covariance quantities.
+ float covariance = 0.f;
+ float noise_variance = 0.f;
+ float signal_variance = 0.f;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ float signal_diff = signal_spectrum[i] - signal_average;
+ float noise_diff = conservative_noise_spectrum[i] - noise_average;
+ covariance += signal_diff * noise_diff;
+ noise_variance += noise_diff * noise_diff;
+ signal_variance += signal_diff * signal_diff;
+ }
+ covariance *= kOneByFftSizeBy2Plus1;
+ noise_variance *= kOneByFftSizeBy2Plus1;
+ signal_variance *= kOneByFftSizeBy2Plus1;
+
+ // Update of average magnitude spectrum.
+ float spectral_diff =
+ signal_variance - (covariance * covariance) / (noise_variance + 0.0001f);
+ // Normalize.
+ return spectral_diff / (diff_normalization + 0.0001f);
+}
+
+// Updates the spectral flatness based on the input spectrum.
+void UpdateSpectralFlatness(
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum,
+ float* spectral_flatness) {
+ RTC_DCHECK(spectral_flatness);
+
+ // Compute log of ratio of the geometric to arithmetic mean (handle the log(0)
+ // separately).
+ constexpr float kAveraging = 0.3f;
+ float avg_spect_flatness_num = 0.f;
+ for (size_t i = 1; i < kFftSizeBy2Plus1; ++i) {
+ if (signal_spectrum[i] == 0.f) {
+ *spectral_flatness -= kAveraging * (*spectral_flatness);
+ return;
+ }
+ }
+
+ for (size_t i = 1; i < kFftSizeBy2Plus1; ++i) {
+ avg_spect_flatness_num += LogApproximation(signal_spectrum[i]);
+ }
+
+ float avg_spect_flatness_denom = signal_spectral_sum - signal_spectrum[0];
+
+ avg_spect_flatness_denom = avg_spect_flatness_denom * kOneByFftSizeBy2Plus1;
+ avg_spect_flatness_num = avg_spect_flatness_num * kOneByFftSizeBy2Plus1;
+
+ float spectral_tmp =
+ ExpApproximation(avg_spect_flatness_num) / avg_spect_flatness_denom;
+
+ // Time-avg update of spectral flatness feature.
+ *spectral_flatness += kAveraging * (spectral_tmp - *spectral_flatness);
+}
+
+// Updates the log LRT measures.
+void UpdateSpectralLrt(rtc::ArrayView<const float, kFftSizeBy2Plus1> prior_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> post_snr,
+ rtc::ArrayView<float, kFftSizeBy2Plus1> avg_log_lrt,
+ float* lrt) {
+ RTC_DCHECK(lrt);
+
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ float tmp1 = 1.f + 2.f * prior_snr[i];
+ float tmp2 = 2.f * prior_snr[i] / (tmp1 + 0.0001f);
+ float bessel_tmp = (post_snr[i] + 1.f) * tmp2;
+ avg_log_lrt[i] +=
+ .5f * (bessel_tmp - LogApproximation(tmp1) - avg_log_lrt[i]);
+ }
+
+ float log_lrt_time_avg_k_sum = 0.f;
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ log_lrt_time_avg_k_sum += avg_log_lrt[i];
+ }
+ *lrt = log_lrt_time_avg_k_sum * kOneByFftSizeBy2Plus1;
+}
+
+} // namespace
+
+SignalModelEstimator::SignalModelEstimator()
+ : prior_model_estimator_(kLtrFeatureThr) {}
+
+void SignalModelEstimator::AdjustNormalization(int32_t num_analyzed_frames,
+ float signal_energy) {
+ diff_normalization_ *= num_analyzed_frames;
+ diff_normalization_ += signal_energy;
+ diff_normalization_ /= (num_analyzed_frames + 1);
+}
+
+// Update the noise features.
+void SignalModelEstimator::Update(
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prior_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> post_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> conservative_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum,
+ float signal_energy) {
+ // Compute spectral flatness on input spectrum.
+ UpdateSpectralFlatness(signal_spectrum, signal_spectral_sum,
+ &features_.spectral_flatness);
+
+ // Compute difference of input spectrum with learned/estimated noise spectrum.
+ float spectral_diff =
+ ComputeSpectralDiff(conservative_noise_spectrum, signal_spectrum,
+ signal_spectral_sum, diff_normalization_);
+ // Compute time-avg update of difference feature.
+ features_.spectral_diff += 0.3f * (spectral_diff - features_.spectral_diff);
+
+ signal_energy_sum_ += signal_energy;
+
+ // Compute histograms for parameter decisions (thresholds and weights for
+ // features). Parameters are extracted periodically.
+ if (--histogram_analysis_counter_ > 0) {
+ histograms_.Update(features_);
+ } else {
+ // Compute model parameters.
+ prior_model_estimator_.Update(histograms_);
+
+ // Clear histograms for next update.
+ histograms_.Clear();
+
+ histogram_analysis_counter_ = kFeatureUpdateWindowSize;
+
+ // Update every window:
+ // Compute normalization for the spectral difference for next estimation.
+ signal_energy_sum_ = signal_energy_sum_ / kFeatureUpdateWindowSize;
+ diff_normalization_ = 0.5f * (signal_energy_sum_ + diff_normalization_);
+ signal_energy_sum_ = 0.f;
+ }
+
+ // Compute the LRT.
+ UpdateSpectralLrt(prior_snr, post_snr, features_.avg_log_lrt, &features_.lrt);
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/signal_model_estimator.h b/modules/audio_processing/ns/signal_model_estimator.h
new file mode 100644
index 0000000..58ce00a
--- /dev/null
+++ b/modules/audio_processing/ns/signal_model_estimator.h
@@ -0,0 +1,58 @@
+/*
+ * 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_NS_SIGNAL_MODEL_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_NS_SIGNAL_MODEL_ESTIMATOR_H_
+
+#include <array>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/histograms.h"
+#include "modules/audio_processing/ns/ns_common.h"
+#include "modules/audio_processing/ns/prior_signal_model.h"
+#include "modules/audio_processing/ns/prior_signal_model_estimator.h"
+#include "modules/audio_processing/ns/signal_model.h"
+
+namespace webrtc {
+
+class SignalModelEstimator {
+ public:
+ SignalModelEstimator();
+ SignalModelEstimator(const SignalModelEstimator&) = delete;
+ SignalModelEstimator& operator=(const SignalModelEstimator&) = delete;
+
+ // Compute signal normalization during the initial startup phase.
+ void AdjustNormalization(int32_t num_analyzed_frames, float signal_energy);
+
+ void Update(
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prior_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> post_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> conservative_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum,
+ float signal_energy);
+
+ const PriorSignalModel& get_prior_model() const {
+ return prior_model_estimator_.get_prior_model();
+ }
+ const SignalModel& get_model() { return features_; }
+
+ private:
+ float diff_normalization_ = 0.f;
+ float signal_energy_sum_ = 0.f;
+ Histograms histograms_;
+ int histogram_analysis_counter_ = 500;
+ PriorSignalModelEstimator prior_model_estimator_;
+ SignalModel features_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_SIGNAL_MODEL_ESTIMATOR_H_
diff --git a/modules/audio_processing/ns/speech_probability_estimator.cc b/modules/audio_processing/ns/speech_probability_estimator.cc
new file mode 100644
index 0000000..fce9bc8
--- /dev/null
+++ b/modules/audio_processing/ns/speech_probability_estimator.cc
@@ -0,0 +1,103 @@
+/*
+ * 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/ns/speech_probability_estimator.h"
+
+#include <math.h>
+#include <algorithm>
+
+#include "modules/audio_processing/ns/fast_math.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+SpeechProbabilityEstimator::SpeechProbabilityEstimator() {
+ speech_probability_.fill(0.f);
+}
+
+void SpeechProbabilityEstimator::Update(
+ int32_t num_analyzed_frames,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prior_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> post_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> conservative_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum,
+ float signal_energy) {
+ // Update models.
+ if (num_analyzed_frames < kLongStartupPhaseBlocks) {
+ signal_model_estimator_.AdjustNormalization(num_analyzed_frames,
+ signal_energy);
+ }
+ signal_model_estimator_.Update(prior_snr, post_snr,
+ conservative_noise_spectrum, signal_spectrum,
+ signal_spectral_sum, signal_energy);
+
+ const SignalModel& model = signal_model_estimator_.get_model();
+ const PriorSignalModel& prior_model =
+ signal_model_estimator_.get_prior_model();
+
+ // Width parameter in sigmoid map for prior model.
+ constexpr float kWidthPrior0 = 4.f;
+ // Width for pause region: lower range, so increase width in tanh map.
+ constexpr float kWidthPrior1 = 2.f * kWidthPrior0;
+
+ // Average LRT feature: use larger width in tanh map for pause regions.
+ float width_prior = model.lrt < prior_model.lrt ? kWidthPrior1 : kWidthPrior0;
+
+ // Compute indicator function: sigmoid map.
+ float indicator0 =
+ 0.5f * (tanh(width_prior * (model.lrt - prior_model.lrt)) + 1.f);
+
+ // Spectral flatness feature: use larger width in tanh map for pause regions.
+ width_prior = model.spectral_flatness > prior_model.flatness_threshold
+ ? kWidthPrior1
+ : kWidthPrior0;
+
+ // Compute indicator function: sigmoid map.
+ float indicator1 =
+ 0.5f * (tanh(1.f * width_prior *
+ (prior_model.flatness_threshold - model.spectral_flatness)) +
+ 1.f);
+
+ // For template spectrum-difference : use larger width in tanh map for pause
+ // regions.
+ width_prior = model.spectral_diff < prior_model.template_diff_threshold
+ ? kWidthPrior1
+ : kWidthPrior0;
+
+ // Compute indicator function: sigmoid map.
+ float indicator2 =
+ 0.5f * (tanh(width_prior * (model.spectral_diff -
+ prior_model.template_diff_threshold)) +
+ 1.f);
+
+ // Combine the indicator function with the feature weights.
+ float ind_prior = prior_model.lrt_weighting * indicator0 +
+ prior_model.flatness_weighting * indicator1 +
+ prior_model.difference_weighting * indicator2;
+
+ // Compute the prior probability.
+ prior_speech_prob_ += 0.1f * (ind_prior - prior_speech_prob_);
+
+ // Make sure probabilities are within range: keep floor to 0.01.
+ prior_speech_prob_ = std::max(std::min(prior_speech_prob_, 1.f), 0.01f);
+
+ // Final speech probability: combine prior model with LR factor:.
+ float gain_prior =
+ (1.f - prior_speech_prob_) / (prior_speech_prob_ + 0.0001f);
+
+ std::array<float, kFftSizeBy2Plus1> inv_lrt;
+ ExpApproximationSignFlip(model.avg_log_lrt, inv_lrt);
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ speech_probability_[i] = 1.f / (1.f + gain_prior * inv_lrt[i]);
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/speech_probability_estimator.h b/modules/audio_processing/ns/speech_probability_estimator.h
new file mode 100644
index 0000000..259c3b6
--- /dev/null
+++ b/modules/audio_processing/ns/speech_probability_estimator.h
@@ -0,0 +1,51 @@
+/*
+ * 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_NS_SPEECH_PROBABILITY_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_NS_SPEECH_PROBABILITY_ESTIMATOR_H_
+
+#include <array>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/ns_common.h"
+#include "modules/audio_processing/ns/signal_model_estimator.h"
+
+namespace webrtc {
+
+// Class for estimating the probability of speech.
+class SpeechProbabilityEstimator {
+ public:
+ SpeechProbabilityEstimator();
+ SpeechProbabilityEstimator(const SpeechProbabilityEstimator&) = delete;
+ SpeechProbabilityEstimator& operator=(const SpeechProbabilityEstimator&) =
+ delete;
+
+ // Compute speech probability.
+ void Update(
+ int32_t num_analyzed_frames,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prior_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> post_snr,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> conservative_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum,
+ float signal_spectral_sum,
+ float signal_energy);
+
+ float get_prior_probability() const { return prior_speech_prob_; }
+ rtc::ArrayView<const float> get_probability() { return speech_probability_; }
+
+ private:
+ SignalModelEstimator signal_model_estimator_;
+ float prior_speech_prob_ = .5f;
+ std::array<float, kFftSizeBy2Plus1> speech_probability_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_SPEECH_PROBABILITY_ESTIMATOR_H_
diff --git a/modules/audio_processing/ns/suppression_params.cc b/modules/audio_processing/ns/suppression_params.cc
new file mode 100644
index 0000000..9a6bd5a
--- /dev/null
+++ b/modules/audio_processing/ns/suppression_params.cc
@@ -0,0 +1,49 @@
+/*
+ * 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/ns/suppression_params.h"
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+SuppressionParams::SuppressionParams(
+ NsConfig::SuppressionLevel suppression_level) {
+ switch (suppression_level) {
+ case NsConfig::SuppressionLevel::k6dB:
+ over_subtraction_factor = 1.f;
+ // 6 dB attenuation.
+ minimum_attenuating_gain = 0.5f;
+ use_attenuation_adjustment = false;
+ break;
+ case NsConfig::SuppressionLevel::k12dB:
+ over_subtraction_factor = 1.f;
+ // 12 dB attenuation.
+ minimum_attenuating_gain = 0.25f;
+ use_attenuation_adjustment = true;
+ break;
+ case NsConfig::SuppressionLevel::k18dB:
+ over_subtraction_factor = 1.1f;
+ // 18 dB attenuation.
+ minimum_attenuating_gain = 0.125f;
+ use_attenuation_adjustment = true;
+ break;
+ case NsConfig::SuppressionLevel::k21dB:
+ over_subtraction_factor = 1.25f;
+ // 20.9 dB attenuation.
+ minimum_attenuating_gain = 0.09f;
+ use_attenuation_adjustment = true;
+ break;
+ default:
+ RTC_NOTREACHED();
+ }
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/suppression_params.h b/modules/audio_processing/ns/suppression_params.h
new file mode 100644
index 0000000..ad11977
--- /dev/null
+++ b/modules/audio_processing/ns/suppression_params.h
@@ -0,0 +1,30 @@
+/*
+ * 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_NS_SUPPRESSION_PARAMS_H_
+#define MODULES_AUDIO_PROCESSING_NS_SUPPRESSION_PARAMS_H_
+
+#include "modules/audio_processing/ns/ns_config.h"
+
+namespace webrtc {
+
+struct SuppressionParams {
+ explicit SuppressionParams(NsConfig::SuppressionLevel suppression_level);
+ SuppressionParams(const SuppressionParams&) = delete;
+ SuppressionParams& operator=(const SuppressionParams&) = delete;
+
+ float over_subtraction_factor;
+ float minimum_attenuating_gain;
+ bool use_attenuation_adjustment;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_SUPPRESSION_PARAMS_H_
diff --git a/modules/audio_processing/ns/wiener_filter.cc b/modules/audio_processing/ns/wiener_filter.cc
new file mode 100644
index 0000000..e14b797
--- /dev/null
+++ b/modules/audio_processing/ns/wiener_filter.cc
@@ -0,0 +1,120 @@
+/*
+ * 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/ns/wiener_filter.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+#include "modules/audio_processing/ns/fast_math.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+WienerFilter::WienerFilter(const SuppressionParams& suppression_params)
+ : suppression_params_(suppression_params) {
+ filter_.fill(1.f);
+ initial_spectral_estimate_.fill(0.f);
+ spectrum_prev_process_.fill(0.f);
+}
+
+void WienerFilter::Update(
+ int32_t num_analyzed_frames,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prev_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> parametric_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum) {
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ // Previous estimate based on previous frame with gain filter.
+ float prev_tsa = spectrum_prev_process_[i] /
+ (prev_noise_spectrum[i] + 0.0001f) * filter_[i];
+
+ // Current estimate.
+ float current_tsa;
+ if (signal_spectrum[i] > noise_spectrum[i]) {
+ current_tsa = signal_spectrum[i] / (noise_spectrum[i] + 0.0001f) - 1.f;
+ } else {
+ current_tsa = 0.f;
+ }
+
+ // Directed decision estimate is sum of two terms: current estimate and
+ // previous estimate.
+ float snr_prior = 0.98f * prev_tsa + (1.f - 0.98f) * current_tsa;
+ filter_[i] =
+ snr_prior / (suppression_params_.over_subtraction_factor + snr_prior);
+ filter_[i] = std::max(std::min(filter_[i], 1.f),
+ suppression_params_.minimum_attenuating_gain);
+ }
+
+ if (num_analyzed_frames < kShortStartupPhaseBlocks) {
+ for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
+ initial_spectral_estimate_[i] += signal_spectrum[i];
+ float filter_initial = initial_spectral_estimate_[i] -
+ suppression_params_.over_subtraction_factor *
+ parametric_noise_spectrum[i];
+ filter_initial /= initial_spectral_estimate_[i] + 0.0001f;
+
+ filter_initial = std::max(std::min(filter_initial, 1.f),
+ suppression_params_.minimum_attenuating_gain);
+
+ // Weight the two suppression filters.
+ constexpr float kOnyByShortStartupPhaseBlocks =
+ 1.f / kShortStartupPhaseBlocks;
+ filter_initial *= kShortStartupPhaseBlocks - num_analyzed_frames;
+ filter_[i] *= num_analyzed_frames;
+ filter_[i] += filter_initial;
+ filter_[i] *= kOnyByShortStartupPhaseBlocks;
+ }
+ }
+
+ std::copy(signal_spectrum.begin(), signal_spectrum.end(),
+ spectrum_prev_process_.begin());
+}
+
+float WienerFilter::ComputeOverallScalingFactor(
+ int32_t num_analyzed_frames,
+ float prior_speech_probability,
+ float energy_before_filtering,
+ float energy_after_filtering) const {
+ if (!suppression_params_.use_attenuation_adjustment ||
+ num_analyzed_frames <= kLongStartupPhaseBlocks) {
+ return 1.f;
+ }
+
+ float gain = SqrtFastApproximation(energy_after_filtering /
+ (energy_before_filtering + 1.f));
+
+ // Scaling for new version. Threshold in final energy gain factor calculation.
+ constexpr float kBLim = 0.5f;
+ float scale_factor1 = 1.f;
+ if (gain > kBLim) {
+ scale_factor1 = 1.f + 1.3f * (gain - kBLim);
+ if (gain * scale_factor1 > 1.f) {
+ scale_factor1 = 1.f / gain;
+ }
+ }
+
+ float scale_factor2 = 1.f;
+ if (gain < kBLim) {
+ // Do not reduce scale too much for pause regions: attenuation here should
+ // be controlled by flooring.
+ gain = std::max(gain, suppression_params_.minimum_attenuating_gain);
+ scale_factor2 = 1.f - 0.3f * (kBLim - gain);
+ }
+
+ // Combine both scales with speech/noise prob: note prior
+ // (prior_speech_probability) is not frequency dependent.
+ return prior_speech_probability * scale_factor1 +
+ (1.f - prior_speech_probability) * scale_factor2;
+}
+
+} // namespace webrtc
diff --git a/modules/audio_processing/ns/wiener_filter.h b/modules/audio_processing/ns/wiener_filter.h
new file mode 100644
index 0000000..b55c5dc
--- /dev/null
+++ b/modules/audio_processing/ns/wiener_filter.h
@@ -0,0 +1,57 @@
+/*
+ * 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_NS_WIENER_FILTER_H_
+#define MODULES_AUDIO_PROCESSING_NS_WIENER_FILTER_H_
+
+#include <array>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/ns/ns_common.h"
+#include "modules/audio_processing/ns/suppression_params.h"
+
+namespace webrtc {
+
+// Estimates a Wiener-filter based frequency domain noise reduction filter.
+class WienerFilter {
+ public:
+ explicit WienerFilter(const SuppressionParams& suppression_params);
+ WienerFilter(const WienerFilter&) = delete;
+ WienerFilter& operator=(const WienerFilter&) = delete;
+
+ // Updates the filter estimate.
+ void Update(
+ int32_t num_analyzed_frames,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> prev_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> parametric_noise_spectrum,
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> signal_spectrum);
+
+ // Compute an overall gain scaling factor.
+ float ComputeOverallScalingFactor(int32_t num_analyzed_frames,
+ float prior_speech_probability,
+ float energy_before_filtering,
+ float energy_after_filtering) const;
+
+ // Returns the filter.
+ rtc::ArrayView<const float, kFftSizeBy2Plus1> get_filter() const {
+ return filter_;
+ }
+
+ private:
+ const SuppressionParams& suppression_params_;
+ std::array<float, kFftSizeBy2Plus1> spectrum_prev_process_;
+ std::array<float, kFftSizeBy2Plus1> initial_spectral_estimate_;
+ std::array<float, kFftSizeBy2Plus1> filter_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_NS_WIENER_FILTER_H_
diff --git a/modules/audio_processing/ns/windows_private.h b/modules/audio_processing/ns/windows_private.h
deleted file mode 100644
index 17792ec..0000000
--- a/modules/audio_processing/ns/windows_private.h
+++ /dev/null
@@ -1,672 +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_NS_MAIN_SOURCE_WINDOWS_PRIVATE_H_
-#define MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_WINDOWS_PRIVATE_H_
-
-// Hanning window for 4ms 16kHz
-static const float kHanning64w128[128] = {
- 0.00000000000000f, 0.02454122852291f, 0.04906767432742f, 0.07356456359967f,
- 0.09801714032956f, 0.12241067519922f, 0.14673047445536f, 0.17096188876030f,
- 0.19509032201613f, 0.21910124015687f, 0.24298017990326f, 0.26671275747490f,
- 0.29028467725446f, 0.31368174039889f, 0.33688985339222f, 0.35989503653499f,
- 0.38268343236509f, 0.40524131400499f, 0.42755509343028f, 0.44961132965461f,
- 0.47139673682600f, 0.49289819222978f, 0.51410274419322f, 0.53499761988710f,
- 0.55557023301960f, 0.57580819141785f, 0.59569930449243f, 0.61523159058063f,
- 0.63439328416365f, 0.65317284295378f, 0.67155895484702f, 0.68954054473707f,
- 0.70710678118655f, 0.72424708295147f, 0.74095112535496f, 0.75720884650648f,
- 0.77301045336274f, 0.78834642762661f, 0.80320753148064f, 0.81758481315158f,
- 0.83146961230255f, 0.84485356524971f, 0.85772861000027f, 0.87008699110871f,
- 0.88192126434835f, 0.89322430119552f, 0.90398929312344f, 0.91420975570353f,
- 0.92387953251129f, 0.93299279883474f, 0.94154406518302f, 0.94952818059304f,
- 0.95694033573221f, 0.96377606579544f, 0.97003125319454f, 0.97570213003853f,
- 0.98078528040323f, 0.98527764238894f, 0.98917650996478f, 0.99247953459871f,
- 0.99518472667220f, 0.99729045667869f, 0.99879545620517f, 0.99969881869620f,
- 1.00000000000000f, 0.99969881869620f, 0.99879545620517f, 0.99729045667869f,
- 0.99518472667220f, 0.99247953459871f, 0.98917650996478f, 0.98527764238894f,
- 0.98078528040323f, 0.97570213003853f, 0.97003125319454f, 0.96377606579544f,
- 0.95694033573221f, 0.94952818059304f, 0.94154406518302f, 0.93299279883474f,
- 0.92387953251129f, 0.91420975570353f, 0.90398929312344f, 0.89322430119552f,
- 0.88192126434835f, 0.87008699110871f, 0.85772861000027f, 0.84485356524971f,
- 0.83146961230255f, 0.81758481315158f, 0.80320753148064f, 0.78834642762661f,
- 0.77301045336274f, 0.75720884650648f, 0.74095112535496f, 0.72424708295147f,
- 0.70710678118655f, 0.68954054473707f, 0.67155895484702f, 0.65317284295378f,
- 0.63439328416365f, 0.61523159058063f, 0.59569930449243f, 0.57580819141785f,
- 0.55557023301960f, 0.53499761988710f, 0.51410274419322f, 0.49289819222978f,
- 0.47139673682600f, 0.44961132965461f, 0.42755509343028f, 0.40524131400499f,
- 0.38268343236509f, 0.35989503653499f, 0.33688985339222f, 0.31368174039889f,
- 0.29028467725446f, 0.26671275747490f, 0.24298017990326f, 0.21910124015687f,
- 0.19509032201613f, 0.17096188876030f, 0.14673047445536f, 0.12241067519922f,
- 0.09801714032956f, 0.07356456359967f, 0.04906767432742f, 0.02454122852291f};
-
-// hybrib Hanning & flat window
-static const float kBlocks80w128[128] = {
- (float)0.00000000, (float)0.03271908, (float)0.06540313, (float)0.09801714,
- (float)0.13052619, (float)0.16289547, (float)0.19509032, (float)0.22707626,
- (float)0.25881905, (float)0.29028468, (float)0.32143947, (float)0.35225005,
- (float)0.38268343, (float)0.41270703, (float)0.44228869, (float)0.47139674,
- (float)0.50000000, (float)0.52806785, (float)0.55557023, (float)0.58247770,
- (float)0.60876143, (float)0.63439328, (float)0.65934582, (float)0.68359230,
- (float)0.70710678, (float)0.72986407, (float)0.75183981, (float)0.77301045,
- (float)0.79335334, (float)0.81284668, (float)0.83146961, (float)0.84920218,
- (float)0.86602540, (float)0.88192126, (float)0.89687274, (float)0.91086382,
- (float)0.92387953, (float)0.93590593, (float)0.94693013, (float)0.95694034,
- (float)0.96592583, (float)0.97387698, (float)0.98078528, (float)0.98664333,
- (float)0.99144486, (float)0.99518473, (float)0.99785892, (float)0.99946459,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)0.99946459, (float)0.99785892, (float)0.99518473,
- (float)0.99144486, (float)0.98664333, (float)0.98078528, (float)0.97387698,
- (float)0.96592583, (float)0.95694034, (float)0.94693013, (float)0.93590593,
- (float)0.92387953, (float)0.91086382, (float)0.89687274, (float)0.88192126,
- (float)0.86602540, (float)0.84920218, (float)0.83146961, (float)0.81284668,
- (float)0.79335334, (float)0.77301045, (float)0.75183981, (float)0.72986407,
- (float)0.70710678, (float)0.68359230, (float)0.65934582, (float)0.63439328,
- (float)0.60876143, (float)0.58247770, (float)0.55557023, (float)0.52806785,
- (float)0.50000000, (float)0.47139674, (float)0.44228869, (float)0.41270703,
- (float)0.38268343, (float)0.35225005, (float)0.32143947, (float)0.29028468,
- (float)0.25881905, (float)0.22707626, (float)0.19509032, (float)0.16289547,
- (float)0.13052619, (float)0.09801714, (float)0.06540313, (float)0.03271908};
-
-// hybrib Hanning & flat window
-static const float kBlocks160w256[256] = {
- (float)0.00000000, (float)0.01636173, (float)0.03271908, (float)0.04906767,
- (float)0.06540313, (float)0.08172107, (float)0.09801714, (float)0.11428696,
- (float)0.13052619, (float)0.14673047, (float)0.16289547, (float)0.17901686,
- (float)0.19509032, (float)0.21111155, (float)0.22707626, (float)0.24298018,
- (float)0.25881905, (float)0.27458862, (float)0.29028468, (float)0.30590302,
- (float)0.32143947, (float)0.33688985, (float)0.35225005, (float)0.36751594,
- (float)0.38268343, (float)0.39774847, (float)0.41270703, (float)0.42755509,
- (float)0.44228869, (float)0.45690388, (float)0.47139674, (float)0.48576339,
- (float)0.50000000, (float)0.51410274, (float)0.52806785, (float)0.54189158,
- (float)0.55557023, (float)0.56910015, (float)0.58247770, (float)0.59569930,
- (float)0.60876143, (float)0.62166057, (float)0.63439328, (float)0.64695615,
- (float)0.65934582, (float)0.67155895, (float)0.68359230, (float)0.69544264,
- (float)0.70710678, (float)0.71858162, (float)0.72986407, (float)0.74095113,
- (float)0.75183981, (float)0.76252720, (float)0.77301045, (float)0.78328675,
- (float)0.79335334, (float)0.80320753, (float)0.81284668, (float)0.82226822,
- (float)0.83146961, (float)0.84044840, (float)0.84920218, (float)0.85772861,
- (float)0.86602540, (float)0.87409034, (float)0.88192126, (float)0.88951608,
- (float)0.89687274, (float)0.90398929, (float)0.91086382, (float)0.91749450,
- (float)0.92387953, (float)0.93001722, (float)0.93590593, (float)0.94154407,
- (float)0.94693013, (float)0.95206268, (float)0.95694034, (float)0.96156180,
- (float)0.96592583, (float)0.97003125, (float)0.97387698, (float)0.97746197,
- (float)0.98078528, (float)0.98384601, (float)0.98664333, (float)0.98917651,
- (float)0.99144486, (float)0.99344778, (float)0.99518473, (float)0.99665524,
- (float)0.99785892, (float)0.99879546, (float)0.99946459, (float)0.99986614,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)0.99986614, (float)0.99946459, (float)0.99879546,
- (float)0.99785892, (float)0.99665524, (float)0.99518473, (float)0.99344778,
- (float)0.99144486, (float)0.98917651, (float)0.98664333, (float)0.98384601,
- (float)0.98078528, (float)0.97746197, (float)0.97387698, (float)0.97003125,
- (float)0.96592583, (float)0.96156180, (float)0.95694034, (float)0.95206268,
- (float)0.94693013, (float)0.94154407, (float)0.93590593, (float)0.93001722,
- (float)0.92387953, (float)0.91749450, (float)0.91086382, (float)0.90398929,
- (float)0.89687274, (float)0.88951608, (float)0.88192126, (float)0.87409034,
- (float)0.86602540, (float)0.85772861, (float)0.84920218, (float)0.84044840,
- (float)0.83146961, (float)0.82226822, (float)0.81284668, (float)0.80320753,
- (float)0.79335334, (float)0.78328675, (float)0.77301045, (float)0.76252720,
- (float)0.75183981, (float)0.74095113, (float)0.72986407, (float)0.71858162,
- (float)0.70710678, (float)0.69544264, (float)0.68359230, (float)0.67155895,
- (float)0.65934582, (float)0.64695615, (float)0.63439328, (float)0.62166057,
- (float)0.60876143, (float)0.59569930, (float)0.58247770, (float)0.56910015,
- (float)0.55557023, (float)0.54189158, (float)0.52806785, (float)0.51410274,
- (float)0.50000000, (float)0.48576339, (float)0.47139674, (float)0.45690388,
- (float)0.44228869, (float)0.42755509, (float)0.41270703, (float)0.39774847,
- (float)0.38268343, (float)0.36751594, (float)0.35225005, (float)0.33688985,
- (float)0.32143947, (float)0.30590302, (float)0.29028468, (float)0.27458862,
- (float)0.25881905, (float)0.24298018, (float)0.22707626, (float)0.21111155,
- (float)0.19509032, (float)0.17901686, (float)0.16289547, (float)0.14673047,
- (float)0.13052619, (float)0.11428696, (float)0.09801714, (float)0.08172107,
- (float)0.06540313, (float)0.04906767, (float)0.03271908, (float)0.01636173};
-
-// hybrib Hanning & flat window: for 20ms
-static const float kBlocks320w512[512] = {
- (float)0.00000000, (float)0.00818114, (float)0.01636173, (float)0.02454123,
- (float)0.03271908, (float)0.04089475, (float)0.04906767, (float)0.05723732,
- (float)0.06540313, (float)0.07356456, (float)0.08172107, (float)0.08987211,
- (float)0.09801714, (float)0.10615561, (float)0.11428696, (float)0.12241068,
- (float)0.13052619, (float)0.13863297, (float)0.14673047, (float)0.15481816,
- (float)0.16289547, (float)0.17096189, (float)0.17901686, (float)0.18705985,
- (float)0.19509032, (float)0.20310773, (float)0.21111155, (float)0.21910124,
- (float)0.22707626, (float)0.23503609, (float)0.24298018, (float)0.25090801,
- (float)0.25881905, (float)0.26671276, (float)0.27458862, (float)0.28244610,
- (float)0.29028468, (float)0.29810383, (float)0.30590302, (float)0.31368174,
- (float)0.32143947, (float)0.32917568, (float)0.33688985, (float)0.34458148,
- (float)0.35225005, (float)0.35989504, (float)0.36751594, (float)0.37511224,
- (float)0.38268343, (float)0.39022901, (float)0.39774847, (float)0.40524131,
- (float)0.41270703, (float)0.42014512, (float)0.42755509, (float)0.43493645,
- (float)0.44228869, (float)0.44961133, (float)0.45690388, (float)0.46416584,
- (float)0.47139674, (float)0.47859608, (float)0.48576339, (float)0.49289819,
- (float)0.50000000, (float)0.50706834, (float)0.51410274, (float)0.52110274,
- (float)0.52806785, (float)0.53499762, (float)0.54189158, (float)0.54874927,
- (float)0.55557023, (float)0.56235401, (float)0.56910015, (float)0.57580819,
- (float)0.58247770, (float)0.58910822, (float)0.59569930, (float)0.60225052,
- (float)0.60876143, (float)0.61523159, (float)0.62166057, (float)0.62804795,
- (float)0.63439328, (float)0.64069616, (float)0.64695615, (float)0.65317284,
- (float)0.65934582, (float)0.66547466, (float)0.67155895, (float)0.67759830,
- (float)0.68359230, (float)0.68954054, (float)0.69544264, (float)0.70129818,
- (float)0.70710678, (float)0.71286806, (float)0.71858162, (float)0.72424708,
- (float)0.72986407, (float)0.73543221, (float)0.74095113, (float)0.74642045,
- (float)0.75183981, (float)0.75720885, (float)0.76252720, (float)0.76779452,
- (float)0.77301045, (float)0.77817464, (float)0.78328675, (float)0.78834643,
- (float)0.79335334, (float)0.79830715, (float)0.80320753, (float)0.80805415,
- (float)0.81284668, (float)0.81758481, (float)0.82226822, (float)0.82689659,
- (float)0.83146961, (float)0.83598698, (float)0.84044840, (float)0.84485357,
- (float)0.84920218, (float)0.85349396, (float)0.85772861, (float)0.86190585,
- (float)0.86602540, (float)0.87008699, (float)0.87409034, (float)0.87803519,
- (float)0.88192126, (float)0.88574831, (float)0.88951608, (float)0.89322430,
- (float)0.89687274, (float)0.90046115, (float)0.90398929, (float)0.90745693,
- (float)0.91086382, (float)0.91420976, (float)0.91749450, (float)0.92071783,
- (float)0.92387953, (float)0.92697940, (float)0.93001722, (float)0.93299280,
- (float)0.93590593, (float)0.93875641, (float)0.94154407, (float)0.94426870,
- (float)0.94693013, (float)0.94952818, (float)0.95206268, (float)0.95453345,
- (float)0.95694034, (float)0.95928317, (float)0.96156180, (float)0.96377607,
- (float)0.96592583, (float)0.96801094, (float)0.97003125, (float)0.97198664,
- (float)0.97387698, (float)0.97570213, (float)0.97746197, (float)0.97915640,
- (float)0.98078528, (float)0.98234852, (float)0.98384601, (float)0.98527764,
- (float)0.98664333, (float)0.98794298, (float)0.98917651, (float)0.99034383,
- (float)0.99144486, (float)0.99247953, (float)0.99344778, (float)0.99434953,
- (float)0.99518473, (float)0.99595331, (float)0.99665524, (float)0.99729046,
- (float)0.99785892, (float)0.99836060, (float)0.99879546, (float)0.99916346,
- (float)0.99946459, (float)0.99969882, (float)0.99986614, (float)0.99996653,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)1.00000000, (float)1.00000000, (float)1.00000000,
- (float)1.00000000, (float)0.99996653, (float)0.99986614, (float)0.99969882,
- (float)0.99946459, (float)0.99916346, (float)0.99879546, (float)0.99836060,
- (float)0.99785892, (float)0.99729046, (float)0.99665524, (float)0.99595331,
- (float)0.99518473, (float)0.99434953, (float)0.99344778, (float)0.99247953,
- (float)0.99144486, (float)0.99034383, (float)0.98917651, (float)0.98794298,
- (float)0.98664333, (float)0.98527764, (float)0.98384601, (float)0.98234852,
- (float)0.98078528, (float)0.97915640, (float)0.97746197, (float)0.97570213,
- (float)0.97387698, (float)0.97198664, (float)0.97003125, (float)0.96801094,
- (float)0.96592583, (float)0.96377607, (float)0.96156180, (float)0.95928317,
- (float)0.95694034, (float)0.95453345, (float)0.95206268, (float)0.94952818,
- (float)0.94693013, (float)0.94426870, (float)0.94154407, (float)0.93875641,
- (float)0.93590593, (float)0.93299280, (float)0.93001722, (float)0.92697940,
- (float)0.92387953, (float)0.92071783, (float)0.91749450, (float)0.91420976,
- (float)0.91086382, (float)0.90745693, (float)0.90398929, (float)0.90046115,
- (float)0.89687274, (float)0.89322430, (float)0.88951608, (float)0.88574831,
- (float)0.88192126, (float)0.87803519, (float)0.87409034, (float)0.87008699,
- (float)0.86602540, (float)0.86190585, (float)0.85772861, (float)0.85349396,
- (float)0.84920218, (float)0.84485357, (float)0.84044840, (float)0.83598698,
- (float)0.83146961, (float)0.82689659, (float)0.82226822, (float)0.81758481,
- (float)0.81284668, (float)0.80805415, (float)0.80320753, (float)0.79830715,
- (float)0.79335334, (float)0.78834643, (float)0.78328675, (float)0.77817464,
- (float)0.77301045, (float)0.76779452, (float)0.76252720, (float)0.75720885,
- (float)0.75183981, (float)0.74642045, (float)0.74095113, (float)0.73543221,
- (float)0.72986407, (float)0.72424708, (float)0.71858162, (float)0.71286806,
- (float)0.70710678, (float)0.70129818, (float)0.69544264, (float)0.68954054,
- (float)0.68359230, (float)0.67759830, (float)0.67155895, (float)0.66547466,
- (float)0.65934582, (float)0.65317284, (float)0.64695615, (float)0.64069616,
- (float)0.63439328, (float)0.62804795, (float)0.62166057, (float)0.61523159,
- (float)0.60876143, (float)0.60225052, (float)0.59569930, (float)0.58910822,
- (float)0.58247770, (float)0.57580819, (float)0.56910015, (float)0.56235401,
- (float)0.55557023, (float)0.54874927, (float)0.54189158, (float)0.53499762,
- (float)0.52806785, (float)0.52110274, (float)0.51410274, (float)0.50706834,
- (float)0.50000000, (float)0.49289819, (float)0.48576339, (float)0.47859608,
- (float)0.47139674, (float)0.46416584, (float)0.45690388, (float)0.44961133,
- (float)0.44228869, (float)0.43493645, (float)0.42755509, (float)0.42014512,
- (float)0.41270703, (float)0.40524131, (float)0.39774847, (float)0.39022901,
- (float)0.38268343, (float)0.37511224, (float)0.36751594, (float)0.35989504,
- (float)0.35225005, (float)0.34458148, (float)0.33688985, (float)0.32917568,
- (float)0.32143947, (float)0.31368174, (float)0.30590302, (float)0.29810383,
- (float)0.29028468, (float)0.28244610, (float)0.27458862, (float)0.26671276,
- (float)0.25881905, (float)0.25090801, (float)0.24298018, (float)0.23503609,
- (float)0.22707626, (float)0.21910124, (float)0.21111155, (float)0.20310773,
- (float)0.19509032, (float)0.18705985, (float)0.17901686, (float)0.17096189,
- (float)0.16289547, (float)0.15481816, (float)0.14673047, (float)0.13863297,
- (float)0.13052619, (float)0.12241068, (float)0.11428696, (float)0.10615561,
- (float)0.09801714, (float)0.08987211, (float)0.08172107, (float)0.07356456,
- (float)0.06540313, (float)0.05723732, (float)0.04906767, (float)0.04089475,
- (float)0.03271908, (float)0.02454123, (float)0.01636173, (float)0.00818114};
-
-// Hanning window: for 15ms at 16kHz with symmetric zeros
-static const float kBlocks240w512[512] = {
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00654494, (float)0.01308960, (float)0.01963369,
- (float)0.02617695, (float)0.03271908, (float)0.03925982, (float)0.04579887,
- (float)0.05233596, (float)0.05887080, (float)0.06540313, (float)0.07193266,
- (float)0.07845910, (float)0.08498218, (float)0.09150162, (float)0.09801714,
- (float)0.10452846, (float)0.11103531, (float)0.11753740, (float)0.12403446,
- (float)0.13052620, (float)0.13701233, (float)0.14349262, (float)0.14996676,
- (float)0.15643448, (float)0.16289547, (float)0.16934951, (float)0.17579629,
- (float)0.18223552, (float)0.18866697, (float)0.19509032, (float)0.20150533,
- (float)0.20791170, (float)0.21430916, (float)0.22069745, (float)0.22707628,
- (float)0.23344538, (float)0.23980446, (float)0.24615330, (float)0.25249159,
- (float)0.25881904, (float)0.26513544, (float)0.27144045, (float)0.27773386,
- (float)0.28401536, (float)0.29028466, (float)0.29654160, (float)0.30278578,
- (float)0.30901700, (float)0.31523499, (float)0.32143945, (float)0.32763019,
- (float)0.33380687, (float)0.33996925, (float)0.34611708, (float)0.35225007,
- (float)0.35836795, (float)0.36447051, (float)0.37055743, (float)0.37662852,
- (float)0.38268346, (float)0.38872197, (float)0.39474389, (float)0.40074885,
- (float)0.40673664, (float)0.41270703, (float)0.41865975, (float)0.42459452,
- (float)0.43051112, (float)0.43640924, (float)0.44228873, (float)0.44814920,
- (float)0.45399052, (float)0.45981237, (float)0.46561453, (float)0.47139674,
- (float)0.47715878, (float)0.48290035, (float)0.48862126, (float)0.49432120,
- (float)0.50000000, (float)0.50565743, (float)0.51129311, (float)0.51690692,
- (float)0.52249855, (float)0.52806789, (float)0.53361452, (float)0.53913832,
- (float)0.54463905, (float)0.55011642, (float)0.55557024, (float)0.56100029,
- (float)0.56640625, (float)0.57178795, (float)0.57714522, (float)0.58247769,
- (float)0.58778524, (float)0.59306765, (float)0.59832460, (float)0.60355598,
- (float)0.60876143, (float)0.61394083, (float)0.61909395, (float)0.62422055,
- (float)0.62932038, (float)0.63439333, (float)0.63943899, (float)0.64445734,
- (float)0.64944810, (float)0.65441096, (float)0.65934587, (float)0.66425246,
- (float)0.66913062, (float)0.67398012, (float)0.67880076, (float)0.68359232,
- (float)0.68835455, (float)0.69308740, (float)0.69779050, (float)0.70246369,
- (float)0.70710677, (float)0.71171963, (float)0.71630198, (float)0.72085363,
- (float)0.72537440, (float)0.72986406, (float)0.73432255, (float)0.73874950,
- (float)0.74314487, (float)0.74750835, (float)0.75183982, (float)0.75613910,
- (float)0.76040596, (float)0.76464027, (float)0.76884186, (float)0.77301043,
- (float)0.77714598, (float)0.78124821, (float)0.78531694, (float)0.78935206,
- (float)0.79335338, (float)0.79732066, (float)0.80125386, (float)0.80515265,
- (float)0.80901700, (float)0.81284672, (float)0.81664157, (float)0.82040149,
- (float)0.82412618, (float)0.82781565, (float)0.83146966, (float)0.83508795,
- (float)0.83867061, (float)0.84221727, (float)0.84572780, (float)0.84920216,
- (float)0.85264021, (float)0.85604161, (float)0.85940641, (float)0.86273444,
- (float)0.86602545, (float)0.86927933, (float)0.87249607, (float)0.87567532,
- (float)0.87881714, (float)0.88192129, (float)0.88498765, (float)0.88801610,
- (float)0.89100653, (float)0.89395881, (float)0.89687276, (float)0.89974827,
- (float)0.90258533, (float)0.90538365, (float)0.90814316, (float)0.91086388,
- (float)0.91354549, (float)0.91618794, (float)0.91879123, (float)0.92135513,
- (float)0.92387950, (float)0.92636442, (float)0.92880958, (float)0.93121493,
- (float)0.93358046, (float)0.93590593, (float)0.93819135, (float)0.94043654,
- (float)0.94264150, (float)0.94480604, (float)0.94693011, (float)0.94901365,
- (float)0.95105654, (float)0.95305866, (float)0.95501995, (float)0.95694035,
- (float)0.95881975, (float)0.96065807, (float)0.96245527, (float)0.96421117,
- (float)0.96592581, (float)0.96759909, (float)0.96923089, (float)0.97082120,
- (float)0.97236991, (float)0.97387701, (float)0.97534233, (float)0.97676587,
- (float)0.97814763, (float)0.97948742, (float)0.98078531, (float)0.98204112,
- (float)0.98325491, (float)0.98442656, (float)0.98555607, (float)0.98664331,
- (float)0.98768836, (float)0.98869103, (float)0.98965138, (float)0.99056935,
- (float)0.99144489, (float)0.99227792, (float)0.99306846, (float)0.99381649,
- (float)0.99452192, (float)0.99518472, (float)0.99580491, (float)0.99638247,
- (float)0.99691731, (float)0.99740952, (float)0.99785894, (float)0.99826562,
- (float)0.99862951, (float)0.99895066, (float)0.99922901, (float)0.99946457,
- (float)0.99965733, (float)0.99980724, (float)0.99991435, (float)0.99997860,
- (float)1.00000000, (float)0.99997860, (float)0.99991435, (float)0.99980724,
- (float)0.99965733, (float)0.99946457, (float)0.99922901, (float)0.99895066,
- (float)0.99862951, (float)0.99826562, (float)0.99785894, (float)0.99740946,
- (float)0.99691731, (float)0.99638247, (float)0.99580491, (float)0.99518472,
- (float)0.99452192, (float)0.99381644, (float)0.99306846, (float)0.99227792,
- (float)0.99144489, (float)0.99056935, (float)0.98965138, (float)0.98869103,
- (float)0.98768836, (float)0.98664331, (float)0.98555607, (float)0.98442656,
- (float)0.98325491, (float)0.98204112, (float)0.98078525, (float)0.97948742,
- (float)0.97814757, (float)0.97676587, (float)0.97534227, (float)0.97387695,
- (float)0.97236991, (float)0.97082120, (float)0.96923089, (float)0.96759909,
- (float)0.96592581, (float)0.96421117, (float)0.96245521, (float)0.96065807,
- (float)0.95881969, (float)0.95694029, (float)0.95501995, (float)0.95305860,
- (float)0.95105648, (float)0.94901365, (float)0.94693011, (float)0.94480604,
- (float)0.94264150, (float)0.94043654, (float)0.93819129, (float)0.93590593,
- (float)0.93358046, (float)0.93121493, (float)0.92880952, (float)0.92636436,
- (float)0.92387950, (float)0.92135507, (float)0.91879123, (float)0.91618794,
- (float)0.91354543, (float)0.91086382, (float)0.90814310, (float)0.90538365,
- (float)0.90258527, (float)0.89974827, (float)0.89687276, (float)0.89395875,
- (float)0.89100647, (float)0.88801610, (float)0.88498759, (float)0.88192123,
- (float)0.87881714, (float)0.87567532, (float)0.87249595, (float)0.86927933,
- (float)0.86602539, (float)0.86273432, (float)0.85940641, (float)0.85604161,
- (float)0.85264009, (float)0.84920216, (float)0.84572780, (float)0.84221715,
- (float)0.83867055, (float)0.83508795, (float)0.83146954, (float)0.82781565,
- (float)0.82412612, (float)0.82040137, (float)0.81664157, (float)0.81284660,
- (float)0.80901700, (float)0.80515265, (float)0.80125374, (float)0.79732066,
- (float)0.79335332, (float)0.78935200, (float)0.78531694, (float)0.78124815,
- (float)0.77714586, (float)0.77301049, (float)0.76884180, (float)0.76464021,
- (float)0.76040596, (float)0.75613904, (float)0.75183970, (float)0.74750835,
- (float)0.74314481, (float)0.73874938, (float)0.73432249, (float)0.72986400,
- (float)0.72537428, (float)0.72085363, (float)0.71630186, (float)0.71171951,
- (float)0.70710677, (float)0.70246363, (float)0.69779032, (float)0.69308734,
- (float)0.68835449, (float)0.68359220, (float)0.67880070, (float)0.67398006,
- (float)0.66913044, (float)0.66425240, (float)0.65934575, (float)0.65441096,
- (float)0.64944804, (float)0.64445722, (float)0.63943905, (float)0.63439327,
- (float)0.62932026, (float)0.62422055, (float)0.61909389, (float)0.61394072,
- (float)0.60876143, (float)0.60355592, (float)0.59832448, (float)0.59306765,
- (float)0.58778518, (float)0.58247757, (float)0.57714522, (float)0.57178789,
- (float)0.56640613, (float)0.56100023, (float)0.55557019, (float)0.55011630,
- (float)0.54463905, (float)0.53913826, (float)0.53361434, (float)0.52806783,
- (float)0.52249849, (float)0.51690674, (float)0.51129305, (float)0.50565726,
- (float)0.50000006, (float)0.49432117, (float)0.48862115, (float)0.48290038,
- (float)0.47715873, (float)0.47139663, (float)0.46561456, (float)0.45981231,
- (float)0.45399037, (float)0.44814920, (float)0.44228864, (float)0.43640912,
- (float)0.43051112, (float)0.42459446, (float)0.41865960, (float)0.41270703,
- (float)0.40673658, (float)0.40074870, (float)0.39474386, (float)0.38872188,
- (float)0.38268328, (float)0.37662849, (float)0.37055734, (float)0.36447033,
- (float)0.35836792, (float)0.35224995, (float)0.34611690, (float)0.33996922,
- (float)0.33380675, (float)0.32763001, (float)0.32143945, (float)0.31523487,
- (float)0.30901679, (float)0.30278572, (float)0.29654145, (float)0.29028472,
- (float)0.28401530, (float)0.27773371, (float)0.27144048, (float)0.26513538,
- (float)0.25881892, (float)0.25249159, (float)0.24615324, (float)0.23980433,
- (float)0.23344538, (float)0.22707619, (float)0.22069728, (float)0.21430916,
- (float)0.20791161, (float)0.20150517, (float)0.19509031, (float)0.18866688,
- (float)0.18223536, (float)0.17579627, (float)0.16934940, (float)0.16289529,
- (float)0.15643445, (float)0.14996666, (float)0.14349243, (float)0.13701232,
- (float)0.13052608, (float)0.12403426, (float)0.11753736, (float)0.11103519,
- (float)0.10452849, (float)0.09801710, (float)0.09150149, (float)0.08498220,
- (float)0.07845904, (float)0.07193252, (float)0.06540315, (float)0.05887074,
- (float)0.05233581, (float)0.04579888, (float)0.03925974, (float)0.03271893,
- (float)0.02617695, (float)0.01963361, (float)0.01308943, (float)0.00654493,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000};
-
-// Hanning window: for 30ms with 1024 fft with symmetric zeros at 16kHz
-static const float kBlocks480w1024[1024] = {
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00327249, (float)0.00654494, (float)0.00981732,
- (float)0.01308960, (float)0.01636173, (float)0.01963369, (float)0.02290544,
- (float)0.02617695, (float)0.02944817, (float)0.03271908, (float)0.03598964,
- (float)0.03925982, (float)0.04252957, (float)0.04579887, (float)0.04906768,
- (float)0.05233596, (float)0.05560368, (float)0.05887080, (float)0.06213730,
- (float)0.06540313, (float)0.06866825, (float)0.07193266, (float)0.07519628,
- (float)0.07845910, (float)0.08172107, (float)0.08498218, (float)0.08824237,
- (float)0.09150162, (float)0.09475989, (float)0.09801714, (float)0.10127335,
- (float)0.10452846, (float)0.10778246, (float)0.11103531, (float)0.11428697,
- (float)0.11753740, (float)0.12078657, (float)0.12403446, (float)0.12728101,
- (float)0.13052620, (float)0.13376999, (float)0.13701233, (float)0.14025325,
- (float)0.14349262, (float)0.14673047, (float)0.14996676, (float)0.15320145,
- (float)0.15643448, (float)0.15966582, (float)0.16289547, (float)0.16612339,
- (float)0.16934951, (float)0.17257382, (float)0.17579629, (float)0.17901687,
- (float)0.18223552, (float)0.18545224, (float)0.18866697, (float)0.19187967,
- (float)0.19509032, (float)0.19829889, (float)0.20150533, (float)0.20470962,
- (float)0.20791170, (float)0.21111156, (float)0.21430916, (float)0.21750447,
- (float)0.22069745, (float)0.22388805, (float)0.22707628, (float)0.23026206,
- (float)0.23344538, (float)0.23662618, (float)0.23980446, (float)0.24298020,
- (float)0.24615330, (float)0.24932377, (float)0.25249159, (float)0.25565669,
- (float)0.25881904, (float)0.26197866, (float)0.26513544, (float)0.26828939,
- (float)0.27144045, (float)0.27458861, (float)0.27773386, (float)0.28087610,
- (float)0.28401536, (float)0.28715158, (float)0.29028466, (float)0.29341471,
- (float)0.29654160, (float)0.29966527, (float)0.30278578, (float)0.30590302,
- (float)0.30901700, (float)0.31212768, (float)0.31523499, (float)0.31833893,
- (float)0.32143945, (float)0.32453656, (float)0.32763019, (float)0.33072028,
- (float)0.33380687, (float)0.33688986, (float)0.33996925, (float)0.34304500,
- (float)0.34611708, (float)0.34918544, (float)0.35225007, (float)0.35531089,
- (float)0.35836795, (float)0.36142117, (float)0.36447051, (float)0.36751595,
- (float)0.37055743, (float)0.37359497, (float)0.37662852, (float)0.37965801,
- (float)0.38268346, (float)0.38570479, (float)0.38872197, (float)0.39173502,
- (float)0.39474389, (float)0.39774847, (float)0.40074885, (float)0.40374491,
- (float)0.40673664, (float)0.40972406, (float)0.41270703, (float)0.41568562,
- (float)0.41865975, (float)0.42162940, (float)0.42459452, (float)0.42755508,
- (float)0.43051112, (float)0.43346250, (float)0.43640924, (float)0.43935132,
- (float)0.44228873, (float)0.44522133, (float)0.44814920, (float)0.45107228,
- (float)0.45399052, (float)0.45690390, (float)0.45981237, (float)0.46271592,
- (float)0.46561453, (float)0.46850815, (float)0.47139674, (float)0.47428030,
- (float)0.47715878, (float)0.48003215, (float)0.48290035, (float)0.48576337,
- (float)0.48862126, (float)0.49147385, (float)0.49432120, (float)0.49716330,
- (float)0.50000000, (float)0.50283140, (float)0.50565743, (float)0.50847799,
- (float)0.51129311, (float)0.51410276, (float)0.51690692, (float)0.51970553,
- (float)0.52249855, (float)0.52528602, (float)0.52806789, (float)0.53084403,
- (float)0.53361452, (float)0.53637928, (float)0.53913832, (float)0.54189163,
- (float)0.54463905, (float)0.54738063, (float)0.55011642, (float)0.55284631,
- (float)0.55557024, (float)0.55828828, (float)0.56100029, (float)0.56370628,
- (float)0.56640625, (float)0.56910014, (float)0.57178795, (float)0.57446963,
- (float)0.57714522, (float)0.57981455, (float)0.58247769, (float)0.58513463,
- (float)0.58778524, (float)0.59042960, (float)0.59306765, (float)0.59569931,
- (float)0.59832460, (float)0.60094351, (float)0.60355598, (float)0.60616195,
- (float)0.60876143, (float)0.61135441, (float)0.61394083, (float)0.61652070,
- (float)0.61909395, (float)0.62166059, (float)0.62422055, (float)0.62677383,
- (float)0.62932038, (float)0.63186020, (float)0.63439333, (float)0.63691956,
- (float)0.63943899, (float)0.64195162, (float)0.64445734, (float)0.64695615,
- (float)0.64944810, (float)0.65193301, (float)0.65441096, (float)0.65688187,
- (float)0.65934587, (float)0.66180271, (float)0.66425246, (float)0.66669512,
- (float)0.66913062, (float)0.67155898, (float)0.67398012, (float)0.67639405,
- (float)0.67880076, (float)0.68120021, (float)0.68359232, (float)0.68597710,
- (float)0.68835455, (float)0.69072467, (float)0.69308740, (float)0.69544262,
- (float)0.69779050, (float)0.70013082, (float)0.70246369, (float)0.70478904,
- (float)0.70710677, (float)0.70941699, (float)0.71171963, (float)0.71401459,
- (float)0.71630198, (float)0.71858168, (float)0.72085363, (float)0.72311789,
- (float)0.72537440, (float)0.72762316, (float)0.72986406, (float)0.73209721,
- (float)0.73432255, (float)0.73653996, (float)0.73874950, (float)0.74095118,
- (float)0.74314487, (float)0.74533057, (float)0.74750835, (float)0.74967808,
- (float)0.75183982, (float)0.75399351, (float)0.75613910, (float)0.75827658,
- (float)0.76040596, (float)0.76252723, (float)0.76464027, (float)0.76674515,
- (float)0.76884186, (float)0.77093029, (float)0.77301043, (float)0.77508241,
- (float)0.77714598, (float)0.77920127, (float)0.78124821, (float)0.78328675,
- (float)0.78531694, (float)0.78733873, (float)0.78935206, (float)0.79135692,
- (float)0.79335338, (float)0.79534125, (float)0.79732066, (float)0.79929149,
- (float)0.80125386, (float)0.80320752, (float)0.80515265, (float)0.80708915,
- (float)0.80901700, (float)0.81093621, (float)0.81284672, (float)0.81474853,
- (float)0.81664157, (float)0.81852591, (float)0.82040149, (float)0.82226825,
- (float)0.82412618, (float)0.82597536, (float)0.82781565, (float)0.82964706,
- (float)0.83146966, (float)0.83328325, (float)0.83508795, (float)0.83688378,
- (float)0.83867061, (float)0.84044838, (float)0.84221727, (float)0.84397703,
- (float)0.84572780, (float)0.84746957, (float)0.84920216, (float)0.85092574,
- (float)0.85264021, (float)0.85434544, (float)0.85604161, (float)0.85772866,
- (float)0.85940641, (float)0.86107504, (float)0.86273444, (float)0.86438453,
- (float)0.86602545, (float)0.86765707, (float)0.86927933, (float)0.87089235,
- (float)0.87249607, (float)0.87409031, (float)0.87567532, (float)0.87725097,
- (float)0.87881714, (float)0.88037390, (float)0.88192129, (float)0.88345921,
- (float)0.88498765, (float)0.88650668, (float)0.88801610, (float)0.88951612,
- (float)0.89100653, (float)0.89248741, (float)0.89395881, (float)0.89542055,
- (float)0.89687276, (float)0.89831537, (float)0.89974827, (float)0.90117162,
- (float)0.90258533, (float)0.90398932, (float)0.90538365, (float)0.90676826,
- (float)0.90814316, (float)0.90950841, (float)0.91086388, (float)0.91220951,
- (float)0.91354549, (float)0.91487163, (float)0.91618794, (float)0.91749454,
- (float)0.91879123, (float)0.92007810, (float)0.92135513, (float)0.92262226,
- (float)0.92387950, (float)0.92512691, (float)0.92636442, (float)0.92759192,
- (float)0.92880958, (float)0.93001723, (float)0.93121493, (float)0.93240267,
- (float)0.93358046, (float)0.93474817, (float)0.93590593, (float)0.93705362,
- (float)0.93819135, (float)0.93931901, (float)0.94043654, (float)0.94154406,
- (float)0.94264150, (float)0.94372880, (float)0.94480604, (float)0.94587320,
- (float)0.94693011, (float)0.94797695, (float)0.94901365, (float)0.95004016,
- (float)0.95105654, (float)0.95206273, (float)0.95305866, (float)0.95404440,
- (float)0.95501995, (float)0.95598525, (float)0.95694035, (float)0.95788521,
- (float)0.95881975, (float)0.95974404, (float)0.96065807, (float)0.96156180,
- (float)0.96245527, (float)0.96333838, (float)0.96421117, (float)0.96507370,
- (float)0.96592581, (float)0.96676767, (float)0.96759909, (float)0.96842021,
- (float)0.96923089, (float)0.97003126, (float)0.97082120, (float)0.97160077,
- (float)0.97236991, (float)0.97312868, (float)0.97387701, (float)0.97461486,
- (float)0.97534233, (float)0.97605932, (float)0.97676587, (float)0.97746199,
- (float)0.97814763, (float)0.97882277, (float)0.97948742, (float)0.98014158,
- (float)0.98078531, (float)0.98141843, (float)0.98204112, (float)0.98265332,
- (float)0.98325491, (float)0.98384601, (float)0.98442656, (float)0.98499662,
- (float)0.98555607, (float)0.98610497, (float)0.98664331, (float)0.98717111,
- (float)0.98768836, (float)0.98819500, (float)0.98869103, (float)0.98917651,
- (float)0.98965138, (float)0.99011570, (float)0.99056935, (float)0.99101239,
- (float)0.99144489, (float)0.99186671, (float)0.99227792, (float)0.99267852,
- (float)0.99306846, (float)0.99344778, (float)0.99381649, (float)0.99417448,
- (float)0.99452192, (float)0.99485862, (float)0.99518472, (float)0.99550015,
- (float)0.99580491, (float)0.99609905, (float)0.99638247, (float)0.99665523,
- (float)0.99691731, (float)0.99716878, (float)0.99740952, (float)0.99763954,
- (float)0.99785894, (float)0.99806762, (float)0.99826562, (float)0.99845290,
- (float)0.99862951, (float)0.99879545, (float)0.99895066, (float)0.99909520,
- (float)0.99922901, (float)0.99935216, (float)0.99946457, (float)0.99956632,
- (float)0.99965733, (float)0.99973762, (float)0.99980724, (float)0.99986613,
- (float)0.99991435, (float)0.99995178, (float)0.99997860, (float)0.99999464,
- (float)1.00000000, (float)0.99999464, (float)0.99997860, (float)0.99995178,
- (float)0.99991435, (float)0.99986613, (float)0.99980724, (float)0.99973762,
- (float)0.99965733, (float)0.99956632, (float)0.99946457, (float)0.99935216,
- (float)0.99922901, (float)0.99909520, (float)0.99895066, (float)0.99879545,
- (float)0.99862951, (float)0.99845290, (float)0.99826562, (float)0.99806762,
- (float)0.99785894, (float)0.99763954, (float)0.99740946, (float)0.99716872,
- (float)0.99691731, (float)0.99665523, (float)0.99638247, (float)0.99609905,
- (float)0.99580491, (float)0.99550015, (float)0.99518472, (float)0.99485862,
- (float)0.99452192, (float)0.99417448, (float)0.99381644, (float)0.99344778,
- (float)0.99306846, (float)0.99267852, (float)0.99227792, (float)0.99186671,
- (float)0.99144489, (float)0.99101239, (float)0.99056935, (float)0.99011564,
- (float)0.98965138, (float)0.98917651, (float)0.98869103, (float)0.98819494,
- (float)0.98768836, (float)0.98717111, (float)0.98664331, (float)0.98610497,
- (float)0.98555607, (float)0.98499656, (float)0.98442656, (float)0.98384601,
- (float)0.98325491, (float)0.98265326, (float)0.98204112, (float)0.98141843,
- (float)0.98078525, (float)0.98014158, (float)0.97948742, (float)0.97882277,
- (float)0.97814757, (float)0.97746193, (float)0.97676587, (float)0.97605932,
- (float)0.97534227, (float)0.97461486, (float)0.97387695, (float)0.97312862,
- (float)0.97236991, (float)0.97160077, (float)0.97082120, (float)0.97003126,
- (float)0.96923089, (float)0.96842015, (float)0.96759909, (float)0.96676761,
- (float)0.96592581, (float)0.96507365, (float)0.96421117, (float)0.96333838,
- (float)0.96245521, (float)0.96156180, (float)0.96065807, (float)0.95974404,
- (float)0.95881969, (float)0.95788515, (float)0.95694029, (float)0.95598525,
- (float)0.95501995, (float)0.95404440, (float)0.95305860, (float)0.95206267,
- (float)0.95105648, (float)0.95004016, (float)0.94901365, (float)0.94797695,
- (float)0.94693011, (float)0.94587314, (float)0.94480604, (float)0.94372880,
- (float)0.94264150, (float)0.94154406, (float)0.94043654, (float)0.93931895,
- (float)0.93819129, (float)0.93705362, (float)0.93590593, (float)0.93474817,
- (float)0.93358046, (float)0.93240267, (float)0.93121493, (float)0.93001723,
- (float)0.92880952, (float)0.92759192, (float)0.92636436, (float)0.92512691,
- (float)0.92387950, (float)0.92262226, (float)0.92135507, (float)0.92007804,
- (float)0.91879123, (float)0.91749448, (float)0.91618794, (float)0.91487157,
- (float)0.91354543, (float)0.91220951, (float)0.91086382, (float)0.90950835,
- (float)0.90814310, (float)0.90676820, (float)0.90538365, (float)0.90398932,
- (float)0.90258527, (float)0.90117157, (float)0.89974827, (float)0.89831525,
- (float)0.89687276, (float)0.89542055, (float)0.89395875, (float)0.89248741,
- (float)0.89100647, (float)0.88951600, (float)0.88801610, (float)0.88650662,
- (float)0.88498759, (float)0.88345915, (float)0.88192123, (float)0.88037384,
- (float)0.87881714, (float)0.87725091, (float)0.87567532, (float)0.87409031,
- (float)0.87249595, (float)0.87089223, (float)0.86927933, (float)0.86765701,
- (float)0.86602539, (float)0.86438447, (float)0.86273432, (float)0.86107504,
- (float)0.85940641, (float)0.85772860, (float)0.85604161, (float)0.85434544,
- (float)0.85264009, (float)0.85092574, (float)0.84920216, (float)0.84746951,
- (float)0.84572780, (float)0.84397697, (float)0.84221715, (float)0.84044844,
- (float)0.83867055, (float)0.83688372, (float)0.83508795, (float)0.83328319,
- (float)0.83146954, (float)0.82964706, (float)0.82781565, (float)0.82597530,
- (float)0.82412612, (float)0.82226813, (float)0.82040137, (float)0.81852591,
- (float)0.81664157, (float)0.81474847, (float)0.81284660, (float)0.81093609,
- (float)0.80901700, (float)0.80708915, (float)0.80515265, (float)0.80320752,
- (float)0.80125374, (float)0.79929143, (float)0.79732066, (float)0.79534125,
- (float)0.79335332, (float)0.79135686, (float)0.78935200, (float)0.78733861,
- (float)0.78531694, (float)0.78328675, (float)0.78124815, (float)0.77920121,
- (float)0.77714586, (float)0.77508223, (float)0.77301049, (float)0.77093029,
- (float)0.76884180, (float)0.76674509, (float)0.76464021, (float)0.76252711,
- (float)0.76040596, (float)0.75827658, (float)0.75613904, (float)0.75399339,
- (float)0.75183970, (float)0.74967796, (float)0.74750835, (float)0.74533057,
- (float)0.74314481, (float)0.74095106, (float)0.73874938, (float)0.73653996,
- (float)0.73432249, (float)0.73209721, (float)0.72986400, (float)0.72762305,
- (float)0.72537428, (float)0.72311789, (float)0.72085363, (float)0.71858162,
- (float)0.71630186, (float)0.71401453, (float)0.71171951, (float)0.70941705,
- (float)0.70710677, (float)0.70478898, (float)0.70246363, (float)0.70013070,
- (float)0.69779032, (float)0.69544268, (float)0.69308734, (float)0.69072461,
- (float)0.68835449, (float)0.68597704, (float)0.68359220, (float)0.68120021,
- (float)0.67880070, (float)0.67639399, (float)0.67398006, (float)0.67155886,
- (float)0.66913044, (float)0.66669512, (float)0.66425240, (float)0.66180259,
- (float)0.65934575, (float)0.65688181, (float)0.65441096, (float)0.65193301,
- (float)0.64944804, (float)0.64695609, (float)0.64445722, (float)0.64195150,
- (float)0.63943905, (float)0.63691956, (float)0.63439327, (float)0.63186014,
- (float)0.62932026, (float)0.62677372, (float)0.62422055, (float)0.62166059,
- (float)0.61909389, (float)0.61652064, (float)0.61394072, (float)0.61135429,
- (float)0.60876143, (float)0.60616189, (float)0.60355592, (float)0.60094339,
- (float)0.59832448, (float)0.59569913, (float)0.59306765, (float)0.59042960,
- (float)0.58778518, (float)0.58513451, (float)0.58247757, (float)0.57981461,
- (float)0.57714522, (float)0.57446963, (float)0.57178789, (float)0.56910002,
- (float)0.56640613, (float)0.56370628, (float)0.56100023, (float)0.55828822,
- (float)0.55557019, (float)0.55284619, (float)0.55011630, (float)0.54738069,
- (float)0.54463905, (float)0.54189152, (float)0.53913826, (float)0.53637916,
- (float)0.53361434, (float)0.53084403, (float)0.52806783, (float)0.52528596,
- (float)0.52249849, (float)0.51970541, (float)0.51690674, (float)0.51410276,
- (float)0.51129305, (float)0.50847787, (float)0.50565726, (float)0.50283122,
- (float)0.50000006, (float)0.49716327, (float)0.49432117, (float)0.49147379,
- (float)0.48862115, (float)0.48576325, (float)0.48290038, (float)0.48003212,
- (float)0.47715873, (float)0.47428021, (float)0.47139663, (float)0.46850798,
- (float)0.46561456, (float)0.46271589, (float)0.45981231, (float)0.45690379,
- (float)0.45399037, (float)0.45107210, (float)0.44814920, (float)0.44522130,
- (float)0.44228864, (float)0.43935123, (float)0.43640912, (float)0.43346232,
- (float)0.43051112, (float)0.42755505, (float)0.42459446, (float)0.42162928,
- (float)0.41865960, (float)0.41568545, (float)0.41270703, (float)0.40972400,
- (float)0.40673658, (float)0.40374479, (float)0.40074870, (float)0.39774850,
- (float)0.39474386, (float)0.39173496, (float)0.38872188, (float)0.38570464,
- (float)0.38268328, (float)0.37965804, (float)0.37662849, (float)0.37359491,
- (float)0.37055734, (float)0.36751580, (float)0.36447033, (float)0.36142117,
- (float)0.35836792, (float)0.35531086, (float)0.35224995, (float)0.34918529,
- (float)0.34611690, (float)0.34304500, (float)0.33996922, (float)0.33688980,
- (float)0.33380675, (float)0.33072016, (float)0.32763001, (float)0.32453656,
- (float)0.32143945, (float)0.31833887, (float)0.31523487, (float)0.31212750,
- (float)0.30901679, (float)0.30590302, (float)0.30278572, (float)0.29966521,
- (float)0.29654145, (float)0.29341453, (float)0.29028472, (float)0.28715155,
- (float)0.28401530, (float)0.28087601, (float)0.27773371, (float)0.27458847,
- (float)0.27144048, (float)0.26828936, (float)0.26513538, (float)0.26197854,
- (float)0.25881892, (float)0.25565651, (float)0.25249159, (float)0.24932374,
- (float)0.24615324, (float)0.24298008, (float)0.23980433, (float)0.23662600,
- (float)0.23344538, (float)0.23026201, (float)0.22707619, (float)0.22388794,
- (float)0.22069728, (float)0.21750426, (float)0.21430916, (float)0.21111152,
- (float)0.20791161, (float)0.20470949, (float)0.20150517, (float)0.19829892,
- (float)0.19509031, (float)0.19187963, (float)0.18866688, (float)0.18545210,
- (float)0.18223536, (float)0.17901689, (float)0.17579627, (float)0.17257376,
- (float)0.16934940, (float)0.16612324, (float)0.16289529, (float)0.15966584,
- (float)0.15643445, (float)0.15320137, (float)0.14996666, (float)0.14673033,
- (float)0.14349243, (float)0.14025325, (float)0.13701232, (float)0.13376991,
- (float)0.13052608, (float)0.12728085, (float)0.12403426, (float)0.12078657,
- (float)0.11753736, (float)0.11428688, (float)0.11103519, (float)0.10778230,
- (float)0.10452849, (float)0.10127334, (float)0.09801710, (float)0.09475980,
- (float)0.09150149, (float)0.08824220, (float)0.08498220, (float)0.08172106,
- (float)0.07845904, (float)0.07519618, (float)0.07193252, (float)0.06866808,
- (float)0.06540315, (float)0.06213728, (float)0.05887074, (float)0.05560357,
- (float)0.05233581, (float)0.04906749, (float)0.04579888, (float)0.04252954,
- (float)0.03925974, (float)0.03598953, (float)0.03271893, (float)0.02944798,
- (float)0.02617695, (float)0.02290541, (float)0.01963361, (float)0.01636161,
- (float)0.01308943, (float)0.00981712, (float)0.00654493, (float)0.00327244,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000,
- (float)0.00000000, (float)0.00000000, (float)0.00000000, (float)0.00000000};
-
-#endif // MODULES_AUDIO_PROCESSING_NS_MAIN_SOURCE_WINDOWS_PRIVATE_H_
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index 8c6a46d..7f354a9 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -504,6 +504,12 @@
*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 340c9d3..bf718b2 100644
--- a/modules/audio_processing/test/audio_processing_simulator.h
+++ b/modules/audio_processing/test/audio_processing_simulator.h
@@ -65,6 +65,7 @@
absl::optional<bool> use_extended_filter;
absl::optional<bool> use_drift_compensation;
absl::optional<bool> use_legacy_aec;
+ absl::optional<bool> use_legacy_ns;
absl::optional<bool> use_experimental_agc;
absl::optional<bool> use_experimental_agc_agc2_level_estimator;
absl::optional<bool> experimental_agc_disable_digital_adaptive;
diff --git a/modules/audio_processing/test/audioproc_float_impl.cc b/modules/audio_processing/test/audioproc_float_impl.cc
index 6428e9d..3e755b5 100644
--- a/modules/audio_processing/test/audioproc_float_impl.cc
+++ b/modules/audio_processing/test/audioproc_float_impl.cc
@@ -130,6 +130,10 @@
kParameterNotSpecifiedValue,
"Activate (1) or deactivate(0) the legacy AEC");
ABSL_FLAG(int,
+ use_legacy_ns,
+ kParameterNotSpecifiedValue,
+ "Activate (1) or deactivate(0) the legacy AEC");
+ABSL_FLAG(int,
experimental_agc,
kParameterNotSpecifiedValue,
"Activate (1) or deactivate(0) the experimental AGC");
@@ -393,6 +397,8 @@
SetSettingIfFlagSet(absl::GetFlag(FLAGS_use_legacy_aec),
&settings.use_legacy_aec);
+ SetSettingIfFlagSet(absl::GetFlag(FLAGS_use_legacy_ns),
+ &settings.use_legacy_ns);
SetSettingIfFlagSet(absl::GetFlag(FLAGS_experimental_agc),
&settings.use_experimental_agc);
SetSettingIfFlagSet(
diff --git a/modules/audio_processing/transient/transient_suppressor.cc b/modules/audio_processing/transient/transient_suppressor.cc
index 2463efa..b10b055 100644
--- a/modules/audio_processing/transient/transient_suppressor.cc
+++ b/modules/audio_processing/transient/transient_suppressor.cc
@@ -20,7 +20,7 @@
#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/ns/windows_private.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 "rtc_base/checks.h"