Index: webrtc/modules/audio_processing/aec3/suppression_gain.cc |
diff --git a/webrtc/modules/audio_processing/aec3/suppression_gain.cc b/webrtc/modules/audio_processing/aec3/suppression_gain.cc |
index aa37e8cdbd467ff2ef77c6c13006b3e176e52bdc..5318d7a947ffb2dad99483a84d2ce27107354166 100644 |
--- a/webrtc/modules/audio_processing/aec3/suppression_gain.cc |
+++ b/webrtc/modules/audio_processing/aec3/suppression_gain.cc |
@@ -17,6 +17,7 @@ |
#include <math.h> |
#include <algorithm> |
#include <functional> |
+#include <numeric> |
namespace webrtc { |
namespace { |
@@ -31,7 +32,12 @@ void GainPostProcessing(std::array<float, kFftLengthBy2Plus1>* gain_squared) { |
// filter on the upper-frequency gains influencing the overall achieved |
// gain. TODO(peah): Update this when new anti-aliasing filters are |
// implemented. |
- constexpr size_t kAntiAliasingImpactLimit = 64 * 0.7f; |
+ constexpr size_t kAntiAliasingImpactLimit = (64 * 2000) / 8000; |
+ float minG = (*gain_squared)[2]; |
+ for (size_t k = 2; k < kAntiAliasingImpactLimit; ++k) { |
+ minG = std::min(minG, (*gain_squared)[k]); |
+ } |
aleloi
2017/04/06 14:34:22
This can be simplified to something like this:
mi
peah-webrtc
2017/04/06 21:11:14
True. Furthermore, it turned out that minG was not
|
+ |
std::for_each(gain_squared->begin() + kAntiAliasingImpactLimit, |
gain_squared->end(), |
[gain_squared, kAntiAliasingImpactLimit](float& a) { |
@@ -41,8 +47,8 @@ void GainPostProcessing(std::array<float, kFftLengthBy2Plus1>* gain_squared) { |
} |
constexpr int kNumIterations = 2; |
-constexpr float kEchoMaskingMargin = 1.f / 10.f; |
-constexpr float kBandMaskingFactor = 1.f / 2.f; |
+constexpr float kEchoMaskingMargin = 1.f / 20.f; |
+constexpr float kBandMaskingFactor = 1.f / 10.f; |
constexpr float kTimeMaskingFactor = 1.f / 10.f; |
} // namespace |
@@ -135,8 +141,8 @@ void ComputeGains_SSE2( |
std::transform(gain_squared->begin() + 1, gain_squared->end() - 1, |
previous_gain_squared->begin(), gain_squared->begin() + 1, |
[](float a, float b) { |
- return b < 0.0001f ? std::min(a, 0.0001f) |
- : std::min(a, b * 2.f); |
+ return b < 0.001f ? std::min(a, 0.001f) |
+ : std::min(a, b * 2.f); |
}); |
// Process the gains to avoid artefacts caused by gain realization in the |
@@ -272,6 +278,43 @@ void ComputeGains( |
} // namespace aec3 |
+// Computes an upper bound on the gain to apply for high frequencies. |
+float HighFrequencyGainBound(bool saturated_echo, |
+ const std::vector<std::vector<float>>& render) { |
+ if (render.size() == 1) { |
+ return 1.f; |
+ } |
+ |
+ // Always attenuate the upper bands when there is saturated echo. |
+ if (saturated_echo) { |
+ return 0.001; |
+ } |
+ |
+ // Compute the upper and lower band energies. |
+ float low_band_energy = |
+ std::accumulate(render[0].begin(), render[0].end(), 0.f, |
+ [](float a, float b) -> float { return a + b * b; }); |
+ float high_band_energies = 0.f; |
+ for (size_t k = 1; k < render.size(); ++k) { |
+ high_band_energies = std::max( |
+ high_band_energies, |
+ std::accumulate(render[k].begin(), render[k].end(), 0.f, |
+ [](float a, float b) -> float { return a + b * b; })); |
+ } |
+ |
+ // If there is more power in the lower frequencies than the upper frequencies, |
+ // or if the power in upper frequencies is low, do not bound the gain in the |
+ // upper bands. |
+ if (high_band_energies < low_band_energy || |
+ high_band_energies < kSubBlockSize * 10.f * 10.f) { |
+ return 1.f; |
+ } |
+ |
+ // In all other cases, bound the gain for upper frequencies. |
+ RTC_DCHECK_LE(low_band_energy, high_band_energies); |
+ return 0.01f * sqrtf(low_band_energy / high_band_energies); |
+} |
+ |
SuppressionGain::SuppressionGain(Aec3Optimization optimization) |
: optimization_(optimization) { |
previous_gain_squared_.fill(1.f); |
@@ -282,21 +325,41 @@ void SuppressionGain::GetGain( |
const std::array<float, kFftLengthBy2Plus1>& nearend_power, |
const std::array<float, kFftLengthBy2Plus1>& residual_echo_power, |
const std::array<float, kFftLengthBy2Plus1>& comfort_noise_power, |
- float strong_nearend_margin, |
- std::array<float, kFftLengthBy2Plus1>* gain) { |
- RTC_DCHECK(gain); |
+ bool saturated_echo, |
+ const std::vector<std::vector<float>>& render, |
+ size_t num_capture_bands, |
+ float* high_bands_gain, |
+ std::array<float, kFftLengthBy2Plus1>* low_band_gain) { |
+ RTC_DCHECK(high_bands_gain); |
+ RTC_DCHECK(low_band_gain); |
+ |
+ // Choose margin to use. |
+ const float margin = saturated_echo ? 0.001f : 0.01f; |
switch (optimization_) { |
#if defined(WEBRTC_ARCH_X86_FAMILY) |
case Aec3Optimization::kSse2: |
- aec3::ComputeGains_SSE2(nearend_power, residual_echo_power, |
- comfort_noise_power, strong_nearend_margin, |
- &previous_gain_squared_, &previous_masker_, gain); |
+ aec3::ComputeGains_SSE2( |
+ nearend_power, residual_echo_power, comfort_noise_power, margin, |
+ &previous_gain_squared_, &previous_masker_, low_band_gain); |
break; |
#endif |
default: |
aec3::ComputeGains(nearend_power, residual_echo_power, |
- comfort_noise_power, strong_nearend_margin, |
- &previous_gain_squared_, &previous_masker_, gain); |
+ comfort_noise_power, margin, &previous_gain_squared_, |
+ &previous_masker_, low_band_gain); |
+ } |
+ |
+ if (num_capture_bands > 1) { |
+ // Compute the gain for upper frequencies. |
+ const float min_high_band_gain = |
+ HighFrequencyGainBound(saturated_echo, render); |
+ *high_bands_gain = |
+ *std::min_element(low_band_gain->begin() + 32, low_band_gain->end()); |
+ |
+ *high_bands_gain = std::min(*high_bands_gain, min_high_band_gain); |
+ |
+ } else { |
+ *high_bands_gain = 1.f; |
} |
} |