blob: da7a224e863a64630b8cea29801097f9dce69681 [file] [log] [blame]
peahe985b3f2017-02-28 22:08:53 -08001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec3/echo_remover_metrics.h"
peahe985b3f2017-02-28 22:08:53 -080012
13#include <math.h>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stddef.h>
peahe985b3f2017-02-28 22:08:53 -080015#include <algorithm>
16#include <numeric>
17
Yves Gerey988cc082018-10-23 12:03:01 +020018#include "rtc_base/checks.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010019#include "rtc_base/numerics/safe_minmax.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "system_wrappers/include/metrics.h"
peahe985b3f2017-02-28 22:08:53 -080021
22namespace webrtc {
23
24namespace {
25
26constexpr float kOneByMetricsCollectionBlocks = 1.f / kMetricsCollectionBlocks;
27
28} // namespace
29
30EchoRemoverMetrics::DbMetric::DbMetric() : DbMetric(0.f, 0.f, 0.f) {}
31EchoRemoverMetrics::DbMetric::DbMetric(float sum_value,
32 float floor_value,
33 float ceil_value)
34 : sum_value(sum_value), floor_value(floor_value), ceil_value(ceil_value) {}
35
36void EchoRemoverMetrics::DbMetric::Update(float value) {
37 sum_value += value;
38 floor_value = std::min(floor_value, value);
39 ceil_value = std::max(ceil_value, value);
40}
41
Gustaf Ullberg2723fb12017-11-23 14:46:48 +010042void EchoRemoverMetrics::DbMetric::UpdateInstant(float value) {
43 sum_value = value;
44 floor_value = std::min(floor_value, value);
45 ceil_value = std::max(ceil_value, value);
46}
47
peahe985b3f2017-02-28 22:08:53 -080048EchoRemoverMetrics::EchoRemoverMetrics() {
49 ResetMetrics();
50}
51
52void EchoRemoverMetrics::ResetMetrics() {
53 erl_.fill(DbMetric(0.f, 10000.f, 0.000f));
Gustaf Ullberg2723fb12017-11-23 14:46:48 +010054 erl_time_domain_ = DbMetric(0.f, 10000.f, 0.000f);
peahe985b3f2017-02-28 22:08:53 -080055 erle_.fill(DbMetric(0.f, 0.f, 1000.f));
Gustaf Ullberg2723fb12017-11-23 14:46:48 +010056 erle_time_domain_ = DbMetric(0.f, 0.f, 1000.f);
peahe985b3f2017-02-28 22:08:53 -080057 comfort_noise_.fill(DbMetric(0.f, 100000000.f, 0.f));
58 suppressor_gain_.fill(DbMetric(0.f, 1.f, 0.f));
59 active_render_count_ = 0;
60 saturated_capture_ = false;
61}
62
63void EchoRemoverMetrics::Update(
64 const AecState& aec_state,
65 const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
66 const std::array<float, kFftLengthBy2Plus1>& suppressor_gain) {
67 metrics_reported_ = false;
68 if (++block_counter_ <= kMetricsCollectionBlocks) {
69 aec3::UpdateDbMetric(aec_state.Erl(), &erl_);
Gustaf Ullberg2723fb12017-11-23 14:46:48 +010070 erl_time_domain_.UpdateInstant(aec_state.ErlTimeDomain());
peahe985b3f2017-02-28 22:08:53 -080071 aec3::UpdateDbMetric(aec_state.Erle(), &erle_);
Jesús de Vicente Peñae9a7e902018-09-27 11:49:39 +020072 erle_time_domain_.UpdateInstant(aec_state.FullBandErleLog2());
peahe985b3f2017-02-28 22:08:53 -080073 aec3::UpdateDbMetric(comfort_noise_spectrum, &comfort_noise_);
74 aec3::UpdateDbMetric(suppressor_gain, &suppressor_gain_);
75 active_render_count_ += (aec_state.ActiveRender() ? 1 : 0);
76 saturated_capture_ = saturated_capture_ || aec_state.SaturatedCapture();
77 } else {
78 // Report the metrics over several frames in order to lower the impact of
79 // the logarithms involved on the computational complexity.
80 constexpr int kMetricsCollectionBlocksBy2 = kMetricsCollectionBlocks / 2;
81 constexpr float kComfortNoiseScaling = 1.f / (kBlockSize * kBlockSize);
82 switch (block_counter_) {
83 case kMetricsCollectionBlocks + 1:
84 RTC_HISTOGRAM_COUNTS_LINEAR(
85 "WebRTC.Audio.EchoCanceller.ErleBand0.Average",
86 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f,
87 kOneByMetricsCollectionBlocks,
88 erle_[0].sum_value),
89 0, 19, 20);
90 RTC_HISTOGRAM_COUNTS_LINEAR(
91 "WebRTC.Audio.EchoCanceller.ErleBand0.Max",
92 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
93 erle_[0].ceil_value),
94 0, 19, 20);
95 RTC_HISTOGRAM_COUNTS_LINEAR(
96 "WebRTC.Audio.EchoCanceller.ErleBand0.Min",
97 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
98 erle_[0].floor_value),
99 0, 19, 20);
100 break;
101 case kMetricsCollectionBlocks + 2:
102 RTC_HISTOGRAM_COUNTS_LINEAR(
103 "WebRTC.Audio.EchoCanceller.ErleBand1.Average",
104 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f,
105 kOneByMetricsCollectionBlocks,
106 erle_[1].sum_value),
107 0, 19, 20);
108 RTC_HISTOGRAM_COUNTS_LINEAR(
109 "WebRTC.Audio.EchoCanceller.ErleBand1.Max",
110 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
111 erle_[1].ceil_value),
112 0, 19, 20);
113 RTC_HISTOGRAM_COUNTS_LINEAR(
114 "WebRTC.Audio.EchoCanceller.ErleBand1.Min",
115 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
116 erle_[1].floor_value),
117 0, 19, 20);
118 break;
119 case kMetricsCollectionBlocks + 3:
120 RTC_HISTOGRAM_COUNTS_LINEAR(
121 "WebRTC.Audio.EchoCanceller.ErlBand0.Average",
122 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f,
123 kOneByMetricsCollectionBlocks,
124 erl_[0].sum_value),
125 0, 59, 30);
126 RTC_HISTOGRAM_COUNTS_LINEAR(
127 "WebRTC.Audio.EchoCanceller.ErlBand0.Max",
128 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
129 erl_[0].ceil_value),
130 0, 59, 30);
131 RTC_HISTOGRAM_COUNTS_LINEAR(
132 "WebRTC.Audio.EchoCanceller.ErlBand0.Min",
133 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
134 erl_[0].floor_value),
135 0, 59, 30);
136 break;
137 case kMetricsCollectionBlocks + 4:
138 RTC_HISTOGRAM_COUNTS_LINEAR(
139 "WebRTC.Audio.EchoCanceller.ErlBand1.Average",
140 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f,
141 kOneByMetricsCollectionBlocks,
142 erl_[1].sum_value),
143 0, 59, 30);
144 RTC_HISTOGRAM_COUNTS_LINEAR(
145 "WebRTC.Audio.EchoCanceller.ErlBand1.Max",
146 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
147 erl_[1].ceil_value),
148 0, 59, 30);
149 RTC_HISTOGRAM_COUNTS_LINEAR(
150 "WebRTC.Audio.EchoCanceller.ErlBand1.Min",
151 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
152 erl_[1].floor_value),
153 0, 59, 30);
154 break;
155 case kMetricsCollectionBlocks + 5:
156 RTC_HISTOGRAM_COUNTS_LINEAR(
157 "WebRTC.Audio.EchoCanceller.ComfortNoiseBand0.Average",
158 aec3::TransformDbMetricForReporting(
159 true, 0.f, 89.f, -90.3f,
160 kComfortNoiseScaling * kOneByMetricsCollectionBlocks,
161 comfort_noise_[0].sum_value),
162 0, 89, 45);
163 RTC_HISTOGRAM_COUNTS_LINEAR(
164 "WebRTC.Audio.EchoCanceller.ComfortNoiseBand0.Max",
165 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
166 kComfortNoiseScaling,
167 comfort_noise_[0].ceil_value),
168 0, 89, 45);
169 RTC_HISTOGRAM_COUNTS_LINEAR(
170 "WebRTC.Audio.EchoCanceller.ComfortNoiseBand0.Min",
171 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
172 kComfortNoiseScaling,
173 comfort_noise_[0].floor_value),
174 0, 89, 45);
175 break;
176 case kMetricsCollectionBlocks + 6:
177 RTC_HISTOGRAM_COUNTS_LINEAR(
178 "WebRTC.Audio.EchoCanceller.ComfortNoiseBand1.Average",
179 aec3::TransformDbMetricForReporting(
180 true, 0.f, 89.f, -90.3f,
181 kComfortNoiseScaling * kOneByMetricsCollectionBlocks,
182 comfort_noise_[1].sum_value),
183 0, 89, 45);
184 RTC_HISTOGRAM_COUNTS_LINEAR(
185 "WebRTC.Audio.EchoCanceller.ComfortNoiseBand1.Max",
186 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
187 kComfortNoiseScaling,
188 comfort_noise_[1].ceil_value),
189 0, 89, 45);
190 RTC_HISTOGRAM_COUNTS_LINEAR(
191 "WebRTC.Audio.EchoCanceller.ComfortNoiseBand1.Min",
192 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
193 kComfortNoiseScaling,
194 comfort_noise_[1].floor_value),
195 0, 89, 45);
196 break;
197 case kMetricsCollectionBlocks + 7:
198 RTC_HISTOGRAM_COUNTS_LINEAR(
199 "WebRTC.Audio.EchoCanceller.SuppressorGainBand0.Average",
200 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f,
201 kOneByMetricsCollectionBlocks,
202 suppressor_gain_[0].sum_value),
203 0, 59, 30);
204 RTC_HISTOGRAM_COUNTS_LINEAR(
205 "WebRTC.Audio.EchoCanceller.SuppressorGainBand0.Max",
206 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, 1.f,
207 suppressor_gain_[0].ceil_value),
208 0, 59, 30);
209 RTC_HISTOGRAM_COUNTS_LINEAR(
210 "WebRTC.Audio.EchoCanceller.SuppressorGainBand0.Min",
211 aec3::TransformDbMetricForReporting(
212 true, 0.f, 59.f, 0.f, 1.f, suppressor_gain_[0].floor_value),
213 0, 59, 30);
214 break;
215 case kMetricsCollectionBlocks + 8:
216 RTC_HISTOGRAM_COUNTS_LINEAR(
217 "WebRTC.Audio.EchoCanceller.SuppressorGainBand1.Average",
218 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f,
219 kOneByMetricsCollectionBlocks,
220 suppressor_gain_[1].sum_value),
221 0, 59, 30);
222 RTC_HISTOGRAM_COUNTS_LINEAR(
223 "WebRTC.Audio.EchoCanceller.SuppressorGainBand1.Max",
224 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, 1.f,
225 suppressor_gain_[1].ceil_value),
226 0, 59, 30);
227 RTC_HISTOGRAM_COUNTS_LINEAR(
228 "WebRTC.Audio.EchoCanceller.SuppressorGainBand1.Min",
229 aec3::TransformDbMetricForReporting(
230 true, 0.f, 59.f, 0.f, 1.f, suppressor_gain_[1].floor_value),
231 0, 59, 30);
232 break;
233 case kMetricsCollectionBlocks + 9:
234 RTC_HISTOGRAM_BOOLEAN(
235 "WebRTC.Audio.EchoCanceller.UsableLinearEstimate",
236 static_cast<int>(aec_state.UsableLinearEstimate() ? 1 : 0));
237 RTC_HISTOGRAM_BOOLEAN(
peahe985b3f2017-02-28 22:08:53 -0800238 "WebRTC.Audio.EchoCanceller.ActiveRender",
239 static_cast<int>(
240 active_render_count_ > kMetricsCollectionBlocksBy2 ? 1 : 0));
Per Åhgren0e6d2f52017-12-20 22:19:56 +0100241 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.EchoCanceller.FilterDelay",
Per Åhgren5c532d32018-03-22 00:29:25 +0100242 aec_state.FilterDelayBlocks(), 0, 30, 31);
peahe985b3f2017-02-28 22:08:53 -0800243 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.EchoCanceller.CaptureSaturation",
244 static_cast<int>(saturated_capture_ ? 1 : 0));
Gustaf Ullberg2723fb12017-11-23 14:46:48 +0100245 break;
246 case kMetricsCollectionBlocks + 10:
247 RTC_HISTOGRAM_COUNTS_LINEAR(
248 "WebRTC.Audio.EchoCanceller.Erl.Value",
249 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
250 erl_time_domain_.sum_value),
251 0, 59, 30);
252 RTC_HISTOGRAM_COUNTS_LINEAR(
253 "WebRTC.Audio.EchoCanceller.Erl.Max",
254 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
255 erl_time_domain_.ceil_value),
256 0, 59, 30);
257 RTC_HISTOGRAM_COUNTS_LINEAR(
258 "WebRTC.Audio.EchoCanceller.Erl.Min",
259 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
260 erl_time_domain_.floor_value),
261 0, 59, 30);
262 break;
263 case kMetricsCollectionBlocks + 11:
264 RTC_HISTOGRAM_COUNTS_LINEAR(
265 "WebRTC.Audio.EchoCanceller.Erle.Value",
266 aec3::TransformDbMetricForReporting(false, 0.f, 19.f, 0.f, 1.f,
267 erle_time_domain_.sum_value),
268 0, 19, 20);
269 RTC_HISTOGRAM_COUNTS_LINEAR(
270 "WebRTC.Audio.EchoCanceller.Erle.Max",
271 aec3::TransformDbMetricForReporting(false, 0.f, 19.f, 0.f, 1.f,
272 erle_time_domain_.ceil_value),
273 0, 19, 20);
274 RTC_HISTOGRAM_COUNTS_LINEAR(
275 "WebRTC.Audio.EchoCanceller.Erle.Min",
276 aec3::TransformDbMetricForReporting(false, 0.f, 19.f, 0.f, 1.f,
277 erle_time_domain_.floor_value),
278 0, 19, 20);
peahe985b3f2017-02-28 22:08:53 -0800279 metrics_reported_ = true;
280 RTC_DCHECK_EQ(kMetricsReportingIntervalBlocks, block_counter_);
281 block_counter_ = 0;
282 ResetMetrics();
283 break;
284 default:
285 RTC_NOTREACHED();
286 break;
287 }
288 }
289}
290
291namespace aec3 {
292
293void UpdateDbMetric(const std::array<float, kFftLengthBy2Plus1>& value,
294 std::array<EchoRemoverMetrics::DbMetric, 2>* statistic) {
295 RTC_DCHECK(statistic);
296 // Truncation is intended in the band width computation.
297 constexpr int kNumBands = 2;
298 constexpr int kBandWidth = 65 / kNumBands;
299 constexpr float kOneByBandWidth = 1.f / kBandWidth;
300 RTC_DCHECK_EQ(kNumBands, statistic->size());
301 RTC_DCHECK_EQ(65, value.size());
302 for (size_t k = 0; k < statistic->size(); ++k) {
303 float average_band =
304 std::accumulate(value.begin() + kBandWidth * k,
305 value.begin() + kBandWidth * (k + 1), 0.f) *
306 kOneByBandWidth;
307 (*statistic)[k].Update(average_band);
308 }
309}
310
311int TransformDbMetricForReporting(bool negate,
312 float min_value,
313 float max_value,
314 float offset,
315 float scaling,
316 float value) {
317 float new_value = 10.f * log10(value * scaling + 1e-10f) + offset;
318 if (negate) {
319 new_value = -new_value;
320 }
kwiberg07038562017-06-12 11:40:47 -0700321 return static_cast<int>(rtc::SafeClamp(new_value, min_value, max_value));
peahe985b3f2017-02-28 22:08:53 -0800322}
323
324} // namespace aec3
325
326} // namespace webrtc