blob: 0544a5c28b9e9f5fec9948881e78d6d9a60350ef [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_);
Gustaf Ullberg2723fb12017-11-23 14:46:48 +010070 erle_time_domain_.UpdateInstant(aec_state.ErleTimeDomain());
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));
239 RTC_HISTOGRAM_COUNTS_LINEAR(
240 "WebRTC.Audio.EchoCanceller.FilterDelay",
241 aec_state.FilterDelay() ? *aec_state.FilterDelay() + 1 : 0, 0, 30,
242 31);
243 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