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