OLD | NEW |
---|---|
(Empty) | |
1 /* | |
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 | |
11 #include "webrtc/modules/audio_processing/aec3/echo_remover_metrics.h" | |
12 | |
13 #include <math.h> | |
14 #include <algorithm> | |
15 #include <numeric> | |
16 | |
17 #include "webrtc/system_wrappers/include/metrics.h" | |
18 | |
19 namespace webrtc { | |
20 | |
21 namespace { | |
22 | |
23 constexpr float kOneByMetricsCollectionBlocks = 1.f / kMetricsCollectionBlocks; | |
24 | |
25 enum class BooleanCategory { kFalse, kTrue, kNumCategories }; | |
26 | |
27 } // namespace | |
28 | |
29 EchoRemoverMetrics::DbMetric::DbMetric() : DbMetric(0.f, 0.f, 0.f) {} | |
30 EchoRemoverMetrics::DbMetric::DbMetric(float sum_value, | |
31 float floor_value, | |
32 float ceil_value) | |
33 : sum_value(sum_value), floor_value(floor_value), ceil_value(ceil_value) {} | |
34 | |
35 void EchoRemoverMetrics::DbMetric::Update(float value) { | |
36 sum_value += value; | |
37 floor_value = std::min(floor_value, value); | |
38 ceil_value = std::max(ceil_value, value); | |
39 } | |
40 | |
41 EchoRemoverMetrics::EchoRemoverMetrics() { | |
42 ResetMetrics(); | |
43 } | |
44 | |
45 void EchoRemoverMetrics::ResetMetrics() { | |
46 erl_.fill(DbMetric(0.f, 10000.f, 0.000f)); | |
47 erle_.fill(DbMetric(0.f, 0.f, 1000.f)); | |
48 comfort_noise_.fill(DbMetric(0.f, 100000000.f, 0.f)); | |
49 suppressor_gain_.fill(DbMetric(0.f, 1.f, 0.f)); | |
50 active_render_count_ = 0; | |
51 saturated_capture_ = false; | |
52 } | |
53 | |
54 void EchoRemoverMetrics::Update( | |
55 const AecState& aec_state, | |
56 const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum, | |
57 const std::array<float, kFftLengthBy2Plus1>& suppressor_gain) { | |
58 metrics_reported_ = false; | |
59 if (++block_counter_ <= kMetricsCollectionBlocks) { | |
60 aec3::UpdateDbMetric(aec_state.Erl(), &erl_); | |
61 aec3::UpdateDbMetric(aec_state.Erle(), &erle_); | |
62 aec3::UpdateDbMetric(comfort_noise_spectrum, &comfort_noise_); | |
63 aec3::UpdateDbMetric(suppressor_gain, &suppressor_gain_); | |
64 active_render_count_ += (aec_state.ActiveRender() ? 1 : 0); | |
65 saturated_capture_ = saturated_capture_ || aec_state.SaturatedCapture(); | |
66 } else { | |
67 // Report the metrics over several frames in order to lower the impact of | |
68 // the logarithms involved on the computational complexity. | |
69 constexpr int kMetricsCollectionBlocksBy2 = kMetricsCollectionBlocks / 2; | |
70 constexpr float kComfortNoiseScaling = 1.f / (kBlockSize * kBlockSize); | |
71 switch (block_counter_) { | |
72 case kMetricsCollectionBlocks + 1: | |
73 RTC_HISTOGRAM_COUNTS_LINEAR( | |
74 "WebRTC.Audio.EchoCanceller.AverageErleBand0", | |
75 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, | |
76 kOneByMetricsCollectionBlocks, | |
77 erle_[0].sum_value), | |
78 0, 19, 20); | |
79 RTC_HISTOGRAM_COUNTS_LINEAR( | |
80 "WebRTC.Audio.EchoCanceller.MaxErleBand0", | |
81 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f, | |
82 erle_[0].ceil_value), | |
83 0, 19, 20); | |
84 RTC_HISTOGRAM_COUNTS_LINEAR( | |
85 "WebRTC.Audio.EchoCanceller.MinErleBand0", | |
86 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f, | |
87 erle_[0].floor_value), | |
88 0, 19, 20); | |
89 break; | |
90 case kMetricsCollectionBlocks + 2: | |
91 RTC_HISTOGRAM_COUNTS_LINEAR( | |
92 "WebRTC.Audio.EchoCanceller.AverageErleBand1", | |
93 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, | |
94 kOneByMetricsCollectionBlocks, | |
95 erle_[1].sum_value), | |
96 0, 19, 20); | |
97 RTC_HISTOGRAM_COUNTS_LINEAR( | |
98 "WebRTC.Audio.EchoCanceller.MaxErleBand1", | |
99 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f, | |
100 erle_[1].ceil_value), | |
101 0, 19, 20); | |
102 RTC_HISTOGRAM_COUNTS_LINEAR( | |
103 "WebRTC.Audio.EchoCanceller.MinErleBand1", | |
104 aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f, | |
105 erle_[1].floor_value), | |
106 0, 19, 20); | |
107 break; | |
108 case kMetricsCollectionBlocks + 3: | |
109 RTC_HISTOGRAM_COUNTS_LINEAR( | |
110 "WebRTC.Audio.EchoCanceller.AverageErlBand0", | |
111 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, | |
112 kOneByMetricsCollectionBlocks, | |
113 erl_[0].sum_value), | |
114 0, 59, 30); | |
115 RTC_HISTOGRAM_COUNTS_LINEAR( | |
116 "WebRTC.Audio.EchoCanceller.MaxErlBand0", | |
117 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f, | |
118 erl_[0].ceil_value), | |
119 0, 59, 30); | |
120 RTC_HISTOGRAM_COUNTS_LINEAR( | |
121 "WebRTC.Audio.EchoCanceller.MinErlBand0", | |
122 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f, | |
123 erl_[0].floor_value), | |
124 0, 59, 30); | |
125 break; | |
126 case kMetricsCollectionBlocks + 4: | |
127 RTC_HISTOGRAM_COUNTS_LINEAR( | |
128 "WebRTC.Audio.EchoCanceller.AverageErlBand1", | |
129 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, | |
130 kOneByMetricsCollectionBlocks, | |
131 erl_[1].sum_value), | |
132 0, 59, 30); | |
133 RTC_HISTOGRAM_COUNTS_LINEAR( | |
134 "WebRTC.Audio.EchoCanceller.MaxErlBand1", | |
135 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f, | |
136 erl_[1].ceil_value), | |
137 0, 59, 30); | |
138 RTC_HISTOGRAM_COUNTS_LINEAR( | |
139 "WebRTC.Audio.EchoCanceller.MinErlBand1", | |
140 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f, | |
141 erl_[1].floor_value), | |
142 0, 59, 30); | |
143 break; | |
144 case kMetricsCollectionBlocks + 5: | |
145 RTC_HISTOGRAM_COUNTS_LINEAR( | |
146 "WebRTC.Audio.EchoCanceller.AverageComfortNoiseBand0", | |
147 aec3::TransformDbMetricForReporting( | |
148 true, 0.f, 89.f, -90.3f, | |
149 kComfortNoiseScaling * kOneByMetricsCollectionBlocks, | |
150 comfort_noise_[0].sum_value), | |
151 0, 89, 45); | |
152 RTC_HISTOGRAM_COUNTS_LINEAR( | |
153 "WebRTC.Audio.EchoCanceller.MaxComfortNoiseBand0", | |
154 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f, | |
155 kComfortNoiseScaling, | |
156 comfort_noise_[0].ceil_value), | |
157 0, 89, 45); | |
158 RTC_HISTOGRAM_COUNTS_LINEAR( | |
159 "WebRTC.Audio.EchoCanceller.MinComfortNoiseBand0", | |
160 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f, | |
161 kComfortNoiseScaling, | |
162 comfort_noise_[0].floor_value), | |
163 0, 89, 45); | |
164 break; | |
165 case kMetricsCollectionBlocks + 6: | |
166 RTC_HISTOGRAM_COUNTS_LINEAR( | |
167 "WebRTC.Audio.EchoCanceller.AverageComfortNoiseBand1", | |
168 aec3::TransformDbMetricForReporting( | |
169 true, 0.f, 89.f, -90.3f, | |
170 kComfortNoiseScaling * kOneByMetricsCollectionBlocks, | |
171 comfort_noise_[1].sum_value), | |
172 0, 89, 45); | |
173 RTC_HISTOGRAM_COUNTS_LINEAR( | |
174 "WebRTC.Audio.EchoCanceller.MaxComfortNoiseBand1", | |
175 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f, | |
176 kComfortNoiseScaling, | |
177 comfort_noise_[1].ceil_value), | |
178 0, 89, 45); | |
179 RTC_HISTOGRAM_COUNTS_LINEAR( | |
180 "WebRTC.Audio.EchoCanceller.MinComfortNoiseBand1", | |
181 aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f, | |
182 kComfortNoiseScaling, | |
183 comfort_noise_[1].floor_value), | |
184 0, 89, 45); | |
185 break; | |
186 case kMetricsCollectionBlocks + 7: | |
187 RTC_HISTOGRAM_COUNTS_LINEAR( | |
188 "WebRTC.Audio.EchoCanceller.AverageSuppressorGainBand0", | |
189 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, | |
190 kOneByMetricsCollectionBlocks, | |
191 suppressor_gain_[0].sum_value), | |
192 0, 59, 30); | |
193 RTC_HISTOGRAM_COUNTS_LINEAR( | |
194 "WebRTC.Audio.EchoCanceller.MaxSuppressorGainBand0", | |
195 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, 1.f, | |
196 suppressor_gain_[0].ceil_value), | |
197 0, 59, 30); | |
198 RTC_HISTOGRAM_COUNTS_LINEAR( | |
199 "WebRTC.Audio.EchoCanceller.MinSuppressorGainBand0", | |
200 aec3::TransformDbMetricForReporting( | |
201 true, 0.f, 59.f, 0.f, 1.f, suppressor_gain_[0].floor_value), | |
202 0, 59, 30); | |
203 break; | |
204 case kMetricsCollectionBlocks + 8: | |
205 RTC_HISTOGRAM_COUNTS_LINEAR( | |
206 "WebRTC.Audio.EchoCanceller.AverageSuppressorGainBand1", | |
207 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, | |
208 kOneByMetricsCollectionBlocks, | |
209 suppressor_gain_[1].sum_value), | |
210 0, 59, 30); | |
211 RTC_HISTOGRAM_COUNTS_LINEAR( | |
212 "WebRTC.Audio.EchoCanceller.MaxSuppressorGainBand1", | |
213 aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, 1.f, | |
214 suppressor_gain_[1].ceil_value), | |
215 0, 59, 30); | |
216 RTC_HISTOGRAM_COUNTS_LINEAR( | |
217 "WebRTC.Audio.EchoCanceller.MinSuppressorGainBand1", | |
218 aec3::TransformDbMetricForReporting( | |
219 true, 0.f, 59.f, 0.f, 1.f, suppressor_gain_[1].floor_value), | |
220 0, 59, 30); | |
221 break; | |
222 case kMetricsCollectionBlocks + 9: | |
223 RTC_HISTOGRAM_ENUMERATION( | |
hlundin-webrtc
2017/02/28 13:10:03
If it is just true or false, use RTC_HISTOGRAM_BOO
peah-webrtc
2017/02/28 13:19:06
Done.
| |
224 "WebRTC.Audio.EchoCanceller.UsableLinearEstimate", | |
225 static_cast<int>(aec_state.UsableLinearEstimate() | |
226 ? BooleanCategory::kTrue | |
227 : BooleanCategory::kFalse), | |
228 static_cast<int>(BooleanCategory::kNumCategories)); | |
229 RTC_HISTOGRAM_ENUMERATION( | |
230 "WebRTC.Audio.EchoCanceller.ModelBasedAecFeasible", | |
231 static_cast<int>(aec_state.ModelBasedAecFeasible() | |
232 ? BooleanCategory::kTrue | |
233 : BooleanCategory::kFalse), | |
234 static_cast<int>(BooleanCategory::kNumCategories)); | |
235 RTC_HISTOGRAM_ENUMERATION( | |
236 "WebRTC.Audio.EchoCanceller.ActiveRender", | |
237 static_cast<int>(active_render_count_ > kMetricsCollectionBlocksBy2 | |
238 ? BooleanCategory::kTrue | |
239 : BooleanCategory::kFalse), | |
240 static_cast<int>(BooleanCategory::kNumCategories)); | |
241 RTC_HISTOGRAM_COUNTS_LINEAR( | |
242 "WebRTC.Audio.EchoCanceller.FilterDelay", | |
243 aec_state.FilterDelay() ? *aec_state.FilterDelay() + 1 : 0, 0, 30, | |
244 31); | |
245 RTC_HISTOGRAM_ENUMERATION( | |
246 "WebRTC.Audio.EchoCanceller.CaptureSaturation", | |
247 static_cast<int>(saturated_capture_ ? BooleanCategory::kTrue | |
248 : BooleanCategory::kFalse), | |
249 static_cast<int>(BooleanCategory::kNumCategories)); | |
250 metrics_reported_ = true; | |
251 RTC_DCHECK_EQ(kMetricsReportingIntervalBlocks, block_counter_); | |
252 block_counter_ = 0; | |
253 ResetMetrics(); | |
254 break; | |
255 default: | |
256 RTC_NOTREACHED(); | |
257 break; | |
258 } | |
259 } | |
260 } | |
261 | |
262 namespace aec3 { | |
263 | |
264 void UpdateDbMetric(const std::array<float, kFftLengthBy2Plus1>& value, | |
265 std::array<EchoRemoverMetrics::DbMetric, 2>* statistic) { | |
266 RTC_DCHECK(statistic); | |
267 // Truncation is intended in the band width computation. | |
268 constexpr int kNumBands = 2; | |
269 constexpr int kBandWidth = 65 / kNumBands; | |
270 constexpr float kOneByBandWidth = 1.f / kBandWidth; | |
271 RTC_DCHECK_EQ(kNumBands, statistic->size()); | |
272 RTC_DCHECK_EQ(65, value.size()); | |
273 for (size_t k = 0; k < statistic->size(); ++k) { | |
274 float average_band = | |
275 std::accumulate(value.begin() + kBandWidth * k, | |
276 value.begin() + kBandWidth * (k + 1), 0.f) * | |
277 kOneByBandWidth; | |
278 (*statistic)[k].Update(average_band); | |
279 } | |
280 } | |
281 | |
282 int TransformDbMetricForReporting(bool negate, | |
283 float min_value, | |
284 float max_value, | |
285 float offset, | |
286 float scaling, | |
287 float value) { | |
288 float new_value = 10.f * log10(value * scaling + 1e-10f) + offset; | |
289 if (negate) { | |
290 new_value = -new_value; | |
291 } | |
292 return static_cast<int>(std::max(min_value, std::min(max_value, new_value))); | |
293 } | |
294 | |
295 } // namespace aec3 | |
296 | |
297 } // namespace webrtc | |
OLD | NEW |