| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 RTC_DCHECK_NE(0.f, high_band_energy); | 102 RTC_DCHECK_NE(0.f, high_band_energy); |
| 103 anti_howling_gain = 0.01f * sqrtf(low_band_energy / high_band_energy); | 103 anti_howling_gain = 0.01f * sqrtf(low_band_energy / high_band_energy); |
| 104 } | 104 } |
| 105 | 105 |
| 106 // Choose the gain as the minimum of the lower and upper gains. | 106 // Choose the gain as the minimum of the lower and upper gains. |
| 107 return std::min(gain_below_8_khz, anti_howling_gain); | 107 return std::min(gain_below_8_khz, anti_howling_gain); |
| 108 } | 108 } |
| 109 | 109 |
| 110 // Limits the gain increase. | 110 // Limits the gain increase. |
| 111 void UpdateMaxGainIncrease( | 111 void UpdateMaxGainIncrease( |
| 112 const AudioProcessing::Config::EchoCanceller3& config, |
| 112 size_t no_saturation_counter, | 113 size_t no_saturation_counter, |
| 113 bool low_noise_render, | 114 bool low_noise_render, |
| 114 const std::array<float, kFftLengthBy2Plus1>& last_echo, | 115 const std::array<float, kFftLengthBy2Plus1>& last_echo, |
| 115 const std::array<float, kFftLengthBy2Plus1>& echo, | 116 const std::array<float, kFftLengthBy2Plus1>& echo, |
| 116 const std::array<float, kFftLengthBy2Plus1>& last_gain, | 117 const std::array<float, kFftLengthBy2Plus1>& last_gain, |
| 117 const std::array<float, kFftLengthBy2Plus1>& new_gain, | 118 const std::array<float, kFftLengthBy2Plus1>& new_gain, |
| 118 std::array<float, kFftLengthBy2Plus1>* gain_increase) { | 119 std::array<float, kFftLengthBy2Plus1>* gain_increase) { |
| 119 float max_increasing; | 120 float max_increasing; |
| 120 float max_decreasing; | 121 float max_decreasing; |
| 121 float rate_increasing; | 122 float rate_increasing; |
| 122 float rate_decreasing; | 123 float rate_decreasing; |
| 123 float min_increasing; | 124 float min_increasing; |
| 124 float min_decreasing; | 125 float min_decreasing; |
| 125 | 126 |
| 127 auto& param = config.param.gain_updates; |
| 126 if (low_noise_render) { | 128 if (low_noise_render) { |
| 127 max_increasing = 8.f; | 129 max_increasing = param.low_noise.max_inc; |
| 128 max_decreasing = 8.f; | 130 max_decreasing = param.low_noise.max_dec; |
| 129 rate_increasing = 2.f; | 131 rate_increasing = param.low_noise.rate_inc; |
| 130 rate_decreasing = 2.f; | 132 rate_decreasing = param.low_noise.rate_dec; |
| 131 min_increasing = 4.f; | 133 min_increasing = param.low_noise.min_inc; |
| 132 min_decreasing = 4.f; | 134 min_decreasing = param.low_noise.min_dec; |
| 133 } else if (no_saturation_counter > 10) { | 135 } else if (no_saturation_counter > 10) { |
| 134 max_increasing = 4.f; | 136 max_increasing = param.normal.max_inc; |
| 135 max_decreasing = 4.f; | 137 max_decreasing = param.normal.max_dec; |
| 136 rate_increasing = 2.f; | 138 rate_increasing = param.normal.rate_inc; |
| 137 rate_decreasing = 2.f; | 139 rate_decreasing = param.normal.rate_dec; |
| 138 min_increasing = 1.2f; | 140 min_increasing = param.normal.min_inc; |
| 139 min_decreasing = 2.f; | 141 min_decreasing = param.normal.min_dec; |
| 140 } else { | 142 } else { |
| 141 max_increasing = 1.2f; | 143 max_increasing = param.saturation.max_inc; |
| 142 max_decreasing = 1.2f; | 144 max_decreasing = param.saturation.max_dec; |
| 143 rate_increasing = 1.5f; | 145 rate_increasing = param.saturation.rate_inc; |
| 144 rate_decreasing = 1.5f; | 146 rate_decreasing = param.saturation.rate_dec; |
| 145 min_increasing = 1.f; | 147 min_increasing = param.saturation.min_inc; |
| 146 min_decreasing = 1.f; | 148 min_decreasing = param.saturation.min_dec; |
| 147 } | 149 } |
| 148 | 150 |
| 149 for (size_t k = 0; k < new_gain.size(); ++k) { | 151 for (size_t k = 0; k < new_gain.size(); ++k) { |
| 150 if (echo[k] > last_echo[k]) { | 152 if (echo[k] > last_echo[k]) { |
| 151 (*gain_increase)[k] = | 153 (*gain_increase)[k] = |
| 152 new_gain[k] > last_gain[k] | 154 new_gain[k] > last_gain[k] |
| 153 ? std::min(max_increasing, (*gain_increase)[k] * rate_increasing) | 155 ? std::min(max_increasing, (*gain_increase)[k] * rate_increasing) |
| 154 : min_increasing; | 156 : min_increasing; |
| 155 } else { | 157 } else { |
| 156 (*gain_increase)[k] = | 158 (*gain_increase)[k] = |
| 157 new_gain[k] > last_gain[k] | 159 new_gain[k] > last_gain[k] |
| 158 ? std::min(max_decreasing, (*gain_increase)[k] * rate_decreasing) | 160 ? std::min(max_decreasing, (*gain_increase)[k] * rate_decreasing) |
| 159 : min_decreasing; | 161 : min_decreasing; |
| 160 } | 162 } |
| 161 } | 163 } |
| 162 } | 164 } |
| 163 | 165 |
| 164 // Computes the gain to reduce the echo to a non audible level. | 166 // Computes the gain to reduce the echo to a non audible level. |
| 165 void GainToNoAudibleEcho( | 167 void GainToNoAudibleEcho( |
| 168 const AudioProcessing::Config::EchoCanceller3& config, |
| 166 bool low_noise_render, | 169 bool low_noise_render, |
| 167 bool saturated_echo, | 170 bool saturated_echo, |
| 168 const std::array<float, kFftLengthBy2Plus1>& nearend, | 171 const std::array<float, kFftLengthBy2Plus1>& nearend, |
| 169 const std::array<float, kFftLengthBy2Plus1>& echo, | 172 const std::array<float, kFftLengthBy2Plus1>& echo, |
| 170 const std::array<float, kFftLengthBy2Plus1>& masker, | 173 const std::array<float, kFftLengthBy2Plus1>& masker, |
| 171 const std::array<float, kFftLengthBy2Plus1>& min_gain, | 174 const std::array<float, kFftLengthBy2Plus1>& min_gain, |
| 172 const std::array<float, kFftLengthBy2Plus1>& max_gain, | 175 const std::array<float, kFftLengthBy2Plus1>& max_gain, |
| 173 const std::array<float, kFftLengthBy2Plus1>& one_by_echo, | 176 const std::array<float, kFftLengthBy2Plus1>& one_by_echo, |
| 174 std::array<float, kFftLengthBy2Plus1>* gain) { | 177 std::array<float, kFftLengthBy2Plus1>* gain) { |
| 175 constexpr float kEchoMaskingMargin = 1.f / 100.f; | |
| 176 const float nearend_masking_margin = | 178 const float nearend_masking_margin = |
| 177 low_noise_render ? 0.1f : (saturated_echo ? 0.001f : 0.01f); | 179 low_noise_render ? 0.1f |
| 180 : (saturated_echo ? config.param.gain_mask.m2 |
| 181 : config.param.gain_mask.m3); |
| 178 | 182 |
| 179 for (size_t k = 0; k < gain->size(); ++k) { | 183 for (size_t k = 0; k < gain->size(); ++k) { |
| 180 RTC_DCHECK_LE(0.f, nearend_masking_margin * nearend[k]); | 184 RTC_DCHECK_LE(0.f, nearend_masking_margin * nearend[k]); |
| 181 if (echo[k] <= nearend_masking_margin * nearend[k]) { | 185 if (echo[k] <= nearend_masking_margin * nearend[k]) { |
| 182 (*gain)[k] = 1.f; | 186 (*gain)[k] = 1.f; |
| 183 } else { | 187 } else { |
| 184 (*gain)[k] = kEchoMaskingMargin * masker[k] * one_by_echo[k]; | 188 (*gain)[k] = config.param.gain_mask.m1 * masker[k] * one_by_echo[k]; |
| 185 } | 189 } |
| 186 | 190 |
| 187 (*gain)[k] = std::min(std::max((*gain)[k], min_gain[k]), max_gain[k]); | 191 (*gain)[k] = std::min(std::max((*gain)[k], min_gain[k]), max_gain[k]); |
| 188 } | 192 } |
| 189 } | 193 } |
| 190 | 194 |
| 191 // Computes the signal output power that masks the echo signal. | 195 // Computes the signal output power that masks the echo signal. |
| 192 void MaskingPower(const std::array<float, kFftLengthBy2Plus1>& nearend, | 196 void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config, |
| 197 const std::array<float, kFftLengthBy2Plus1>& nearend, |
| 193 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, | 198 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, |
| 194 const std::array<float, kFftLengthBy2Plus1>& last_masker, | 199 const std::array<float, kFftLengthBy2Plus1>& last_masker, |
| 195 const std::array<float, kFftLengthBy2Plus1>& gain, | 200 const std::array<float, kFftLengthBy2Plus1>& gain, |
| 196 std::array<float, kFftLengthBy2Plus1>* masker) { | 201 std::array<float, kFftLengthBy2Plus1>* masker) { |
| 197 std::array<float, kFftLengthBy2Plus1> side_band_masker; | 202 std::array<float, kFftLengthBy2Plus1> side_band_masker; |
| 198 for (size_t k = 0; k < gain.size(); ++k) { | 203 for (size_t k = 0; k < gain.size(); ++k) { |
| 199 side_band_masker[k] = nearend[k] * gain[k] + comfort_noise[k]; | 204 side_band_masker[k] = nearend[k] * gain[k] + comfort_noise[k]; |
| 200 (*masker)[k] = comfort_noise[k] + 0.1f * last_masker[k]; | 205 (*masker)[k] = |
| 206 comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k]; |
| 201 } | 207 } |
| 202 for (size_t k = 1; k < gain.size() - 1; ++k) { | 208 for (size_t k = 1; k < gain.size() - 1; ++k) { |
| 203 (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]); | 209 (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]); |
| 204 } | 210 } |
| 205 } | 211 } |
| 206 | 212 |
| 207 } // namespace | 213 } // namespace |
| 208 | 214 |
| 209 // TODO(peah): Add further optimizations, in particular for the divisions. | 215 // TODO(peah): Add further optimizations, in particular for the divisions. |
| 210 void SuppressionGain::LowerBandGain( | 216 void SuppressionGain::LowerBandGain( |
| 211 bool low_noise_render, | 217 bool low_noise_render, |
| 212 const rtc::Optional<int>& narrow_peak_band, | 218 const rtc::Optional<int>& narrow_peak_band, |
| 213 bool saturated_echo, | 219 bool saturated_echo, |
| 214 const std::array<float, kFftLengthBy2Plus1>& nearend, | 220 const std::array<float, kFftLengthBy2Plus1>& nearend, |
| 215 const std::array<float, kFftLengthBy2Plus1>& echo, | 221 const std::array<float, kFftLengthBy2Plus1>& echo, |
| 216 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, | 222 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, |
| 217 std::array<float, kFftLengthBy2Plus1>* gain) { | 223 std::array<float, kFftLengthBy2Plus1>* gain) { |
| 218 // Count the number of blocks since saturation. | 224 // Count the number of blocks since saturation. |
| 219 no_saturation_counter_ = saturated_echo ? 0 : no_saturation_counter_ + 1; | 225 no_saturation_counter_ = saturated_echo ? 0 : no_saturation_counter_ + 1; |
| 220 | 226 |
| 221 // Precompute 1/echo (note that when the echo is zero, the precomputed value | 227 // Precompute 1/echo (note that when the echo is zero, the precomputed value |
| 222 // is never used). | 228 // is never used). |
| 223 std::array<float, kFftLengthBy2Plus1> one_by_echo; | 229 std::array<float, kFftLengthBy2Plus1> one_by_echo; |
| 224 std::transform(echo.begin(), echo.end(), one_by_echo.begin(), | 230 std::transform(echo.begin(), echo.end(), one_by_echo.begin(), |
| 225 [](float a) { return a > 0.f ? 1.f / a : 1.f; }); | 231 [](float a) { return a > 0.f ? 1.f / a : 1.f; }); |
| 226 | 232 |
| 227 // Compute the minimum gain as the attenuating gain to put the signal just | 233 // Compute the minimum gain as the attenuating gain to put the signal just |
| 228 // above the zero sample values. | 234 // above the zero sample values. |
| 229 std::array<float, kFftLengthBy2Plus1> min_gain; | 235 std::array<float, kFftLengthBy2Plus1> min_gain; |
| 230 const float min_echo_power = low_noise_render ? 192.f : 64.f; | 236 const float min_echo_power = |
| 237 low_noise_render ? config_.param.echo_audibility.low_render_limit |
| 238 : config_.param.echo_audibility.normal_render_limit; |
| 231 if (no_saturation_counter_ > 10) { | 239 if (no_saturation_counter_ > 10) { |
| 232 for (size_t k = 0; k < nearend.size(); ++k) { | 240 for (size_t k = 0; k < nearend.size(); ++k) { |
| 233 const float denom = std::min(nearend[k], echo[k]); | 241 const float denom = std::min(nearend[k], echo[k]); |
| 234 min_gain[k] = denom > 0.f ? min_echo_power / denom : 1.f; | 242 min_gain[k] = denom > 0.f ? min_echo_power / denom : 1.f; |
| 235 min_gain[k] = std::min(min_gain[k], 1.f); | 243 min_gain[k] = std::min(min_gain[k], 1.f); |
| 236 } | 244 } |
| 237 } else { | 245 } else { |
| 238 min_gain.fill(0.f); | 246 min_gain.fill(0.f); |
| 239 } | 247 } |
| 240 | 248 |
| 241 // Compute the maximum gain by limiting the gain increase from the previous | 249 // Compute the maximum gain by limiting the gain increase from the previous |
| 242 // gain. | 250 // gain. |
| 243 std::array<float, kFftLengthBy2Plus1> max_gain; | 251 std::array<float, kFftLengthBy2Plus1> max_gain; |
| 244 for (size_t k = 0; k < gain->size(); ++k) { | 252 for (size_t k = 0; k < gain->size(); ++k) { |
| 245 max_gain[k] = | 253 max_gain[k] = |
| 246 std::min(std::max(last_gain_[k] * gain_increase_[k], 0.001f), 1.f); | 254 std::min(std::max(last_gain_[k] * gain_increase_[k], |
| 255 config_.param.gain_updates.floor_first_increase), |
| 256 1.f); |
| 247 } | 257 } |
| 248 | 258 |
| 249 // Iteratively compute the gain required to attenuate the echo to a non | 259 // Iteratively compute the gain required to attenuate the echo to a non |
| 250 // noticeable level. | 260 // noticeable level. |
| 251 gain->fill(0.f); | 261 gain->fill(0.f); |
| 252 for (int k = 0; k < 2; ++k) { | 262 for (int k = 0; k < 2; ++k) { |
| 253 std::array<float, kFftLengthBy2Plus1> masker; | 263 std::array<float, kFftLengthBy2Plus1> masker; |
| 254 MaskingPower(nearend, comfort_noise, last_masker_, *gain, &masker); | 264 MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker); |
| 255 GainToNoAudibleEcho(low_noise_render, saturated_echo, nearend, echo, masker, | 265 GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, nearend, |
| 256 min_gain, max_gain, one_by_echo, gain); | 266 echo, masker, min_gain, max_gain, one_by_echo, gain); |
| 257 AdjustForExternalFilters(gain); | 267 AdjustForExternalFilters(gain); |
| 258 if (narrow_peak_band) { | 268 if (narrow_peak_band) { |
| 259 NarrowBandAttenuation(*narrow_peak_band, gain); | 269 NarrowBandAttenuation(*narrow_peak_band, gain); |
| 260 } | 270 } |
| 261 } | 271 } |
| 262 | 272 |
| 263 // Update the allowed maximum gain increase. | 273 // Update the allowed maximum gain increase. |
| 264 UpdateMaxGainIncrease(no_saturation_counter_, low_noise_render, last_echo_, | 274 UpdateMaxGainIncrease(config_, no_saturation_counter_, low_noise_render, |
| 265 echo, last_gain_, *gain, &gain_increase_); | 275 last_echo_, echo, last_gain_, *gain, &gain_increase_); |
| 266 | 276 |
| 267 // Store data required for the gain computation of the next block. | 277 // Store data required for the gain computation of the next block. |
| 268 std::copy(echo.begin(), echo.end(), last_echo_.begin()); | 278 std::copy(echo.begin(), echo.end(), last_echo_.begin()); |
| 269 std::copy(gain->begin(), gain->end(), last_gain_.begin()); | 279 std::copy(gain->begin(), gain->end(), last_gain_.begin()); |
| 270 MaskingPower(nearend, comfort_noise, last_masker_, *gain, &last_masker_); | 280 MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, |
| 281 &last_masker_); |
| 271 aec3::VectorMath(optimization_).Sqrt(*gain); | 282 aec3::VectorMath(optimization_).Sqrt(*gain); |
| 272 } | 283 } |
| 273 | 284 |
| 274 SuppressionGain::SuppressionGain(Aec3Optimization optimization) | 285 SuppressionGain::SuppressionGain( |
| 275 : optimization_(optimization) { | 286 const AudioProcessing::Config::EchoCanceller3& config, |
| 287 Aec3Optimization optimization) |
| 288 : optimization_(optimization), config_(config) { |
| 276 last_gain_.fill(1.f); | 289 last_gain_.fill(1.f); |
| 277 last_masker_.fill(0.f); | 290 last_masker_.fill(0.f); |
| 278 gain_increase_.fill(1.f); | 291 gain_increase_.fill(1.f); |
| 279 last_echo_.fill(0.f); | 292 last_echo_.fill(0.f); |
| 280 } | 293 } |
| 281 | 294 |
| 282 void SuppressionGain::GetGain( | 295 void SuppressionGain::GetGain( |
| 283 const std::array<float, kFftLengthBy2Plus1>& nearend, | 296 const std::array<float, kFftLengthBy2Plus1>& nearend, |
| 284 const std::array<float, kFftLengthBy2Plus1>& echo, | 297 const std::array<float, kFftLengthBy2Plus1>& echo, |
| 285 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, | 298 const std::array<float, kFftLengthBy2Plus1>& comfort_noise, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 } | 340 } |
| 328 | 341 |
| 329 constexpr float kThreshold = 50.f * 50.f * 64.f; | 342 constexpr float kThreshold = 50.f * 50.f * 64.f; |
| 330 const bool low_noise_render = | 343 const bool low_noise_render = |
| 331 average_power_ < kThreshold && x2_max < 3 * average_power_; | 344 average_power_ < kThreshold && x2_max < 3 * average_power_; |
| 332 average_power_ = average_power_ * 0.9f + x2_sum * 0.1f; | 345 average_power_ = average_power_ * 0.9f + x2_sum * 0.1f; |
| 333 return low_noise_render; | 346 return low_noise_render; |
| 334 } | 347 } |
| 335 | 348 |
| 336 } // namespace webrtc | 349 } // namespace webrtc |
| OLD | NEW |