Adding metrics to AEC3.
This CL adds metrics reporting to AEC3. BUG=webrtc:6018 Review-Url: https://codereview.webrtc.org/2722453002 Cr-Commit-Position: refs/heads/master@{#16929}
This commit is contained in:
@ -38,6 +38,8 @@ rtc_static_library("audio_processing") {
|
||||
"aec3/block_framer.h",
|
||||
"aec3/block_processor.cc",
|
||||
"aec3/block_processor.h",
|
||||
"aec3/block_processor_metrics.cc",
|
||||
"aec3/block_processor_metrics.h",
|
||||
"aec3/cascaded_biquad_filter.cc",
|
||||
"aec3/cascaded_biquad_filter.h",
|
||||
"aec3/comfort_noise_generator.cc",
|
||||
@ -52,6 +54,8 @@ rtc_static_library("audio_processing") {
|
||||
"aec3/echo_path_variability.h",
|
||||
"aec3/echo_remover.cc",
|
||||
"aec3/echo_remover.h",
|
||||
"aec3/echo_remover_metrics.cc",
|
||||
"aec3/echo_remover_metrics.h",
|
||||
"aec3/erl_estimator.cc",
|
||||
"aec3/erl_estimator.h",
|
||||
"aec3/erle_estimator.cc",
|
||||
@ -75,6 +79,8 @@ rtc_static_library("audio_processing") {
|
||||
"aec3/render_delay_buffer.h",
|
||||
"aec3/render_delay_controller.cc",
|
||||
"aec3/render_delay_controller.h",
|
||||
"aec3/render_delay_controller_metrics.cc",
|
||||
"aec3/render_delay_controller_metrics.h",
|
||||
"aec3/render_signal_analyzer.cc",
|
||||
"aec3/render_signal_analyzer.h",
|
||||
"aec3/residual_echo_estimator.cc",
|
||||
@ -563,6 +569,7 @@ if (rtc_include_tests) {
|
||||
"aec3/aec3_fft_unittest.cc",
|
||||
"aec3/aec_state_unittest.cc",
|
||||
"aec3/block_framer_unittest.cc",
|
||||
"aec3/block_processor_metrics_unittest.cc",
|
||||
"aec3/block_processor_unittest.cc",
|
||||
"aec3/cascaded_biquad_filter_unittest.cc",
|
||||
"aec3/comfort_noise_generator_unittest.cc",
|
||||
@ -570,6 +577,7 @@ if (rtc_include_tests) {
|
||||
"aec3/echo_canceller3_unittest.cc",
|
||||
"aec3/echo_path_delay_estimator_unittest.cc",
|
||||
"aec3/echo_path_variability_unittest.cc",
|
||||
"aec3/echo_remover_metrics_unittest.cc",
|
||||
"aec3/echo_remover_unittest.cc",
|
||||
"aec3/erl_estimator_unittest.cc",
|
||||
"aec3/erle_estimator_unittest.cc",
|
||||
@ -582,6 +590,7 @@ if (rtc_include_tests) {
|
||||
"aec3/output_selector_unittest.cc",
|
||||
"aec3/power_echo_model_unittest.cc",
|
||||
"aec3/render_delay_buffer_unittest.cc",
|
||||
"aec3/render_delay_controller_metrics_unittest.cc",
|
||||
"aec3/render_delay_controller_unittest.cc",
|
||||
"aec3/render_signal_analyzer_unittest.cc",
|
||||
"aec3/residual_echo_estimator_unittest.cc",
|
||||
|
||||
@ -26,6 +26,11 @@ namespace webrtc {
|
||||
|
||||
enum class Aec3Optimization { kNone, kSse2 };
|
||||
|
||||
constexpr int kMetricsReportingIntervalBlocks = 10 * 250;
|
||||
constexpr int kMetricsComputationBlocks = 9;
|
||||
constexpr int kMetricsCollectionBlocks =
|
||||
kMetricsReportingIntervalBlocks - kMetricsComputationBlocks;
|
||||
|
||||
constexpr size_t kFftLengthBy2 = 64;
|
||||
constexpr size_t kFftLengthBy2Plus1 = kFftLengthBy2 + 1;
|
||||
constexpr size_t kFftLengthBy2Minus1 = kFftLengthBy2 - 1;
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/optional.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/block_processor_metrics.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h"
|
||||
#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "webrtc/system_wrappers/include/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
@ -44,6 +44,7 @@ class BlockProcessorImpl final : public BlockProcessor {
|
||||
std::unique_ptr<RenderDelayBuffer> render_buffer_;
|
||||
std::unique_ptr<RenderDelayController> delay_controller_;
|
||||
std::unique_ptr<EchoRemover> echo_remover_;
|
||||
BlockProcessorMetrics metrics_;
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
|
||||
};
|
||||
|
||||
@ -88,8 +89,9 @@ void BlockProcessorImpl::ProcessCapture(
|
||||
delay_controller_->AlignmentHeadroomSamples(),
|
||||
EchoPathVariability(echo_path_gain_change, render_delay_change),
|
||||
capture_signal_saturation, render_block, capture_block);
|
||||
metrics_.UpdateCapture(false);
|
||||
} else {
|
||||
LOG(LS_INFO) << "AEC3 empty render buffer";
|
||||
metrics_.UpdateCapture(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,10 +104,10 @@ bool BlockProcessorImpl::BufferRender(std::vector<std::vector<float>>* block) {
|
||||
!delay_controller_->AnalyzeRender((*block)[0]);
|
||||
const bool render_buffer_overrun = !render_buffer_->Insert(block);
|
||||
if (delay_controller_overrun || render_buffer_overrun) {
|
||||
LOG(LS_INFO) << "AEC3 buffer overrrun";
|
||||
metrics_.UpdateRender(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
metrics_.UpdateRender(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
103
webrtc/modules/audio_processing/aec3/block_processor_metrics.cc
Normal file
103
webrtc/modules/audio_processing/aec3/block_processor_metrics.cc
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/block_processor_metrics.h"
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "webrtc/system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
enum class RenderUnderrunCategory {
|
||||
kNone,
|
||||
kFew,
|
||||
kSeveral,
|
||||
kMany,
|
||||
kConstant,
|
||||
kNumCategories
|
||||
};
|
||||
|
||||
enum class RenderOverrunCategory {
|
||||
kNone,
|
||||
kFew,
|
||||
kSeveral,
|
||||
kMany,
|
||||
kConstant,
|
||||
kNumCategories
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void BlockProcessorMetrics::UpdateCapture(bool underrun) {
|
||||
++capture_block_counter_;
|
||||
if (underrun) {
|
||||
++render_buffer_underruns_;
|
||||
}
|
||||
|
||||
if (capture_block_counter_ == kMetricsReportingIntervalBlocks) {
|
||||
metrics_reported_ = true;
|
||||
|
||||
RenderUnderrunCategory underrun_category;
|
||||
if (render_buffer_underruns_ == 0) {
|
||||
underrun_category = RenderUnderrunCategory::kNone;
|
||||
} else if (render_buffer_underruns_ > (capture_block_counter_ >> 1)) {
|
||||
underrun_category = RenderUnderrunCategory::kConstant;
|
||||
} else if (render_buffer_underruns_ > 100) {
|
||||
underrun_category = RenderUnderrunCategory::kMany;
|
||||
} else if (render_buffer_underruns_ > 10) {
|
||||
underrun_category = RenderUnderrunCategory::kSeveral;
|
||||
} else {
|
||||
underrun_category = RenderUnderrunCategory::kFew;
|
||||
}
|
||||
RTC_HISTOGRAM_ENUMERATION(
|
||||
"WebRTC.Audio.EchoCanceller.RenderUnderruns",
|
||||
static_cast<int>(underrun_category),
|
||||
static_cast<int>(RenderUnderrunCategory::kNumCategories));
|
||||
|
||||
RenderOverrunCategory overrun_category;
|
||||
if (render_buffer_overruns_ == 0) {
|
||||
overrun_category = RenderOverrunCategory::kNone;
|
||||
} else if (render_buffer_overruns_ > (buffer_render_calls_ >> 1)) {
|
||||
overrun_category = RenderOverrunCategory::kConstant;
|
||||
} else if (render_buffer_overruns_ > 100) {
|
||||
overrun_category = RenderOverrunCategory::kMany;
|
||||
} else if (render_buffer_overruns_ > 10) {
|
||||
overrun_category = RenderOverrunCategory::kSeveral;
|
||||
} else {
|
||||
overrun_category = RenderOverrunCategory::kFew;
|
||||
}
|
||||
RTC_HISTOGRAM_ENUMERATION(
|
||||
"WebRTC.Audio.EchoCanceller.RenderOverruns",
|
||||
static_cast<int>(overrun_category),
|
||||
static_cast<int>(RenderOverrunCategory::kNumCategories));
|
||||
|
||||
ResetMetrics();
|
||||
capture_block_counter_ = 0;
|
||||
} else {
|
||||
metrics_reported_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockProcessorMetrics::UpdateRender(bool overrun) {
|
||||
++buffer_render_calls_;
|
||||
if (overrun) {
|
||||
++render_buffer_overruns_;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockProcessorMetrics::ResetMetrics() {
|
||||
render_buffer_underruns_ = 0;
|
||||
render_buffer_overruns_ = 0;
|
||||
buffer_render_calls_ = 0;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Handles the reporting of metrics for the block_processor.
|
||||
class BlockProcessorMetrics {
|
||||
public:
|
||||
BlockProcessorMetrics() = default;
|
||||
|
||||
// Updates the metric with new capture data.
|
||||
void UpdateCapture(bool underrun);
|
||||
|
||||
// Updates the metric with new render data.
|
||||
void UpdateRender(bool overrun);
|
||||
|
||||
// Returns true if the metrics have just been reported, otherwise false.
|
||||
bool MetricsReported() { return metrics_reported_; }
|
||||
|
||||
private:
|
||||
// Resets the metrics.
|
||||
void ResetMetrics();
|
||||
|
||||
int capture_block_counter_ = 0;
|
||||
bool metrics_reported_ = false;
|
||||
int render_buffer_underruns_ = 0;
|
||||
int render_buffer_overruns_ = 0;
|
||||
int buffer_render_calls_ = 0;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(BlockProcessorMetrics);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/block_processor_metrics.h"
|
||||
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Verify the general functionality of BlockProcessorMetrics.
|
||||
TEST(BlockProcessorMetrics, NormalUsage) {
|
||||
BlockProcessorMetrics metrics;
|
||||
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
for (int k = 0; k < kMetricsReportingIntervalBlocks - 1; ++k) {
|
||||
metrics.UpdateRender(false);
|
||||
metrics.UpdateRender(false);
|
||||
metrics.UpdateCapture(false);
|
||||
EXPECT_FALSE(metrics.MetricsReported());
|
||||
}
|
||||
metrics.UpdateCapture(false);
|
||||
EXPECT_TRUE(metrics.MetricsReported());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -21,6 +21,7 @@
|
||||
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/comfort_noise_generator.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/echo_remover_metrics.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/fft_buffer.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/fft_data.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/output_selector.h"
|
||||
@ -90,6 +91,7 @@ class EchoRemoverImpl final : public EchoRemover {
|
||||
bool echo_leakage_detected_ = false;
|
||||
std::array<float, kBlockSize> x_old_;
|
||||
AecState aec_state_;
|
||||
EchoRemoverMetrics metrics_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(EchoRemoverImpl);
|
||||
};
|
||||
@ -209,6 +211,9 @@ void EchoRemoverImpl::ProcessBlock(
|
||||
doubletalk ? 0.001f : 0.0001f, &G);
|
||||
suppression_filter_.ApplyGain(comfort_noise, high_band_comfort_noise, G, y);
|
||||
|
||||
// Update the metrics.
|
||||
metrics_.Update(aec_state_, cng_.NoiseSpectrum(), G);
|
||||
|
||||
// Debug outputs for the purpose of development and analysis.
|
||||
data_dumper_->DumpRaw("aec3_N2", cng_.NoiseSpectrum());
|
||||
data_dumper_->DumpRaw("aec3_suppressor_gain", G);
|
||||
|
||||
284
webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc
Normal file
284
webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/echo_remover_metrics.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#include "webrtc/system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr float kOneByMetricsCollectionBlocks = 1.f / kMetricsCollectionBlocks;
|
||||
|
||||
} // namespace
|
||||
|
||||
EchoRemoverMetrics::DbMetric::DbMetric() : DbMetric(0.f, 0.f, 0.f) {}
|
||||
EchoRemoverMetrics::DbMetric::DbMetric(float sum_value,
|
||||
float floor_value,
|
||||
float ceil_value)
|
||||
: sum_value(sum_value), floor_value(floor_value), ceil_value(ceil_value) {}
|
||||
|
||||
void EchoRemoverMetrics::DbMetric::Update(float value) {
|
||||
sum_value += value;
|
||||
floor_value = std::min(floor_value, value);
|
||||
ceil_value = std::max(ceil_value, value);
|
||||
}
|
||||
|
||||
EchoRemoverMetrics::EchoRemoverMetrics() {
|
||||
ResetMetrics();
|
||||
}
|
||||
|
||||
void EchoRemoverMetrics::ResetMetrics() {
|
||||
erl_.fill(DbMetric(0.f, 10000.f, 0.000f));
|
||||
erle_.fill(DbMetric(0.f, 0.f, 1000.f));
|
||||
comfort_noise_.fill(DbMetric(0.f, 100000000.f, 0.f));
|
||||
suppressor_gain_.fill(DbMetric(0.f, 1.f, 0.f));
|
||||
active_render_count_ = 0;
|
||||
saturated_capture_ = false;
|
||||
}
|
||||
|
||||
void EchoRemoverMetrics::Update(
|
||||
const AecState& aec_state,
|
||||
const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
|
||||
const std::array<float, kFftLengthBy2Plus1>& suppressor_gain) {
|
||||
metrics_reported_ = false;
|
||||
if (++block_counter_ <= kMetricsCollectionBlocks) {
|
||||
aec3::UpdateDbMetric(aec_state.Erl(), &erl_);
|
||||
aec3::UpdateDbMetric(aec_state.Erle(), &erle_);
|
||||
aec3::UpdateDbMetric(comfort_noise_spectrum, &comfort_noise_);
|
||||
aec3::UpdateDbMetric(suppressor_gain, &suppressor_gain_);
|
||||
active_render_count_ += (aec_state.ActiveRender() ? 1 : 0);
|
||||
saturated_capture_ = saturated_capture_ || aec_state.SaturatedCapture();
|
||||
} else {
|
||||
// Report the metrics over several frames in order to lower the impact of
|
||||
// the logarithms involved on the computational complexity.
|
||||
constexpr int kMetricsCollectionBlocksBy2 = kMetricsCollectionBlocks / 2;
|
||||
constexpr float kComfortNoiseScaling = 1.f / (kBlockSize * kBlockSize);
|
||||
switch (block_counter_) {
|
||||
case kMetricsCollectionBlocks + 1:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErleBand0.Average",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f,
|
||||
kOneByMetricsCollectionBlocks,
|
||||
erle_[0].sum_value),
|
||||
0, 19, 20);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErleBand0.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
|
||||
erle_[0].ceil_value),
|
||||
0, 19, 20);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErleBand0.Min",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
|
||||
erle_[0].floor_value),
|
||||
0, 19, 20);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 2:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErleBand1.Average",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f,
|
||||
kOneByMetricsCollectionBlocks,
|
||||
erle_[1].sum_value),
|
||||
0, 19, 20);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErleBand1.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
|
||||
erle_[1].ceil_value),
|
||||
0, 19, 20);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErleBand1.Min",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 19.f, 0.f, 1.f,
|
||||
erle_[1].floor_value),
|
||||
0, 19, 20);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 3:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErlBand0.Average",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f,
|
||||
kOneByMetricsCollectionBlocks,
|
||||
erl_[0].sum_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErlBand0.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
|
||||
erl_[0].ceil_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErlBand0.Min",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
|
||||
erl_[0].floor_value),
|
||||
0, 59, 30);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 4:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErlBand1.Average",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f,
|
||||
kOneByMetricsCollectionBlocks,
|
||||
erl_[1].sum_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErlBand1.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
|
||||
erl_[1].ceil_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ErlBand1.Min",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 30.f, 1.f,
|
||||
erl_[1].floor_value),
|
||||
0, 59, 30);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 5:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ComfortNoiseBand0.Average",
|
||||
aec3::TransformDbMetricForReporting(
|
||||
true, 0.f, 89.f, -90.3f,
|
||||
kComfortNoiseScaling * kOneByMetricsCollectionBlocks,
|
||||
comfort_noise_[0].sum_value),
|
||||
0, 89, 45);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ComfortNoiseBand0.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
|
||||
kComfortNoiseScaling,
|
||||
comfort_noise_[0].ceil_value),
|
||||
0, 89, 45);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ComfortNoiseBand0.Min",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
|
||||
kComfortNoiseScaling,
|
||||
comfort_noise_[0].floor_value),
|
||||
0, 89, 45);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 6:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ComfortNoiseBand1.Average",
|
||||
aec3::TransformDbMetricForReporting(
|
||||
true, 0.f, 89.f, -90.3f,
|
||||
kComfortNoiseScaling * kOneByMetricsCollectionBlocks,
|
||||
comfort_noise_[1].sum_value),
|
||||
0, 89, 45);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ComfortNoiseBand1.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
|
||||
kComfortNoiseScaling,
|
||||
comfort_noise_[1].ceil_value),
|
||||
0, 89, 45);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.ComfortNoiseBand1.Min",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 89.f, -90.3f,
|
||||
kComfortNoiseScaling,
|
||||
comfort_noise_[1].floor_value),
|
||||
0, 89, 45);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 7:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.SuppressorGainBand0.Average",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f,
|
||||
kOneByMetricsCollectionBlocks,
|
||||
suppressor_gain_[0].sum_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.SuppressorGainBand0.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, 1.f,
|
||||
suppressor_gain_[0].ceil_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.SuppressorGainBand0.Min",
|
||||
aec3::TransformDbMetricForReporting(
|
||||
true, 0.f, 59.f, 0.f, 1.f, suppressor_gain_[0].floor_value),
|
||||
0, 59, 30);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 8:
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.SuppressorGainBand1.Average",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f,
|
||||
kOneByMetricsCollectionBlocks,
|
||||
suppressor_gain_[1].sum_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.SuppressorGainBand1.Max",
|
||||
aec3::TransformDbMetricForReporting(true, 0.f, 59.f, 0.f, 1.f,
|
||||
suppressor_gain_[1].ceil_value),
|
||||
0, 59, 30);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.SuppressorGainBand1.Min",
|
||||
aec3::TransformDbMetricForReporting(
|
||||
true, 0.f, 59.f, 0.f, 1.f, suppressor_gain_[1].floor_value),
|
||||
0, 59, 30);
|
||||
break;
|
||||
case kMetricsCollectionBlocks + 9:
|
||||
RTC_HISTOGRAM_BOOLEAN(
|
||||
"WebRTC.Audio.EchoCanceller.UsableLinearEstimate",
|
||||
static_cast<int>(aec_state.UsableLinearEstimate() ? 1 : 0));
|
||||
RTC_HISTOGRAM_BOOLEAN(
|
||||
"WebRTC.Audio.EchoCanceller.ModelBasedAecFeasible",
|
||||
static_cast<int>(aec_state.ModelBasedAecFeasible() ? 1 : 0));
|
||||
RTC_HISTOGRAM_BOOLEAN(
|
||||
"WebRTC.Audio.EchoCanceller.ActiveRender",
|
||||
static_cast<int>(
|
||||
active_render_count_ > kMetricsCollectionBlocksBy2 ? 1 : 0));
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR(
|
||||
"WebRTC.Audio.EchoCanceller.FilterDelay",
|
||||
aec_state.FilterDelay() ? *aec_state.FilterDelay() + 1 : 0, 0, 30,
|
||||
31);
|
||||
RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.EchoCanceller.CaptureSaturation",
|
||||
static_cast<int>(saturated_capture_ ? 1 : 0));
|
||||
metrics_reported_ = true;
|
||||
RTC_DCHECK_EQ(kMetricsReportingIntervalBlocks, block_counter_);
|
||||
block_counter_ = 0;
|
||||
ResetMetrics();
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace aec3 {
|
||||
|
||||
void UpdateDbMetric(const std::array<float, kFftLengthBy2Plus1>& value,
|
||||
std::array<EchoRemoverMetrics::DbMetric, 2>* statistic) {
|
||||
RTC_DCHECK(statistic);
|
||||
// Truncation is intended in the band width computation.
|
||||
constexpr int kNumBands = 2;
|
||||
constexpr int kBandWidth = 65 / kNumBands;
|
||||
constexpr float kOneByBandWidth = 1.f / kBandWidth;
|
||||
RTC_DCHECK_EQ(kNumBands, statistic->size());
|
||||
RTC_DCHECK_EQ(65, value.size());
|
||||
for (size_t k = 0; k < statistic->size(); ++k) {
|
||||
float average_band =
|
||||
std::accumulate(value.begin() + kBandWidth * k,
|
||||
value.begin() + kBandWidth * (k + 1), 0.f) *
|
||||
kOneByBandWidth;
|
||||
(*statistic)[k].Update(average_band);
|
||||
}
|
||||
}
|
||||
|
||||
int TransformDbMetricForReporting(bool negate,
|
||||
float min_value,
|
||||
float max_value,
|
||||
float offset,
|
||||
float scaling,
|
||||
float value) {
|
||||
float new_value = 10.f * log10(value * scaling + 1e-10f) + offset;
|
||||
if (negate) {
|
||||
new_value = -new_value;
|
||||
}
|
||||
return static_cast<int>(std::max(min_value, std::min(max_value, new_value)));
|
||||
}
|
||||
|
||||
} // namespace aec3
|
||||
|
||||
} // namespace webrtc
|
||||
77
webrtc/modules/audio_processing/aec3/echo_remover_metrics.h
Normal file
77
webrtc/modules/audio_processing/aec3/echo_remover_metrics.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_METRICS_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_METRICS_H_
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Handles the reporting of metrics for the echo remover.
|
||||
class EchoRemoverMetrics {
|
||||
public:
|
||||
struct DbMetric {
|
||||
DbMetric();
|
||||
DbMetric(float sum_value, float floor_value, float ceil_value);
|
||||
void Update(float value);
|
||||
float sum_value;
|
||||
float floor_value;
|
||||
float ceil_value;
|
||||
};
|
||||
|
||||
EchoRemoverMetrics();
|
||||
|
||||
// Updates the metric with new data.
|
||||
void Update(
|
||||
const AecState& aec_state,
|
||||
const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
|
||||
const std::array<float, kFftLengthBy2Plus1>& suppressor_gain);
|
||||
|
||||
// Returns true if the metrics have just been reported, otherwise false.
|
||||
bool MetricsReported() { return metrics_reported_; }
|
||||
|
||||
private:
|
||||
// Resets the metrics.
|
||||
void ResetMetrics();
|
||||
|
||||
int block_counter_ = 0;
|
||||
std::array<DbMetric, 2> erl_;
|
||||
std::array<DbMetric, 2> erle_;
|
||||
std::array<DbMetric, 2> comfort_noise_;
|
||||
std::array<DbMetric, 2> suppressor_gain_;
|
||||
int active_render_count_ = 0;
|
||||
bool saturated_capture_ = false;
|
||||
bool metrics_reported_ = false;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(EchoRemoverMetrics);
|
||||
};
|
||||
|
||||
namespace aec3 {
|
||||
|
||||
// Updates a banded metric of type DbMetric with the values in the supplied
|
||||
// array.
|
||||
void UpdateDbMetric(const std::array<float, kFftLengthBy2Plus1>& value,
|
||||
std::array<EchoRemoverMetrics::DbMetric, 2>* statistic);
|
||||
|
||||
// Transforms a DbMetric from the linear domain into the logarithmic domain.
|
||||
int TransformDbMetricForReporting(bool negate,
|
||||
float min_value,
|
||||
float max_value,
|
||||
float offset,
|
||||
float scaling,
|
||||
float value);
|
||||
|
||||
} // namespace aec3
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_METRICS_H_
|
||||
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/echo_remover_metrics.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_fft.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
|
||||
// Verifies the check for non-null input.
|
||||
TEST(UpdateDbMetric, NullValue) {
|
||||
std::array<float, kFftLengthBy2Plus1> value;
|
||||
value.fill(0.f);
|
||||
EXPECT_DEATH(aec3::UpdateDbMetric(value, nullptr), "");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Verifies the updating functionality of UpdateDbMetric.
|
||||
TEST(UpdateDbMetric, Updating) {
|
||||
std::array<float, kFftLengthBy2Plus1> value;
|
||||
std::array<EchoRemoverMetrics::DbMetric, 2> statistic;
|
||||
statistic.fill(EchoRemoverMetrics::DbMetric(0.f, 100.f, -100.f));
|
||||
constexpr float kValue0 = 10.f;
|
||||
constexpr float kValue1 = 20.f;
|
||||
std::fill(value.begin(), value.begin() + 32, kValue0);
|
||||
std::fill(value.begin() + 32, value.begin() + 64, kValue1);
|
||||
|
||||
aec3::UpdateDbMetric(value, &statistic);
|
||||
EXPECT_FLOAT_EQ(kValue0, statistic[0].sum_value);
|
||||
EXPECT_FLOAT_EQ(kValue0, statistic[0].ceil_value);
|
||||
EXPECT_FLOAT_EQ(kValue0, statistic[0].floor_value);
|
||||
EXPECT_FLOAT_EQ(kValue1, statistic[1].sum_value);
|
||||
EXPECT_FLOAT_EQ(kValue1, statistic[1].ceil_value);
|
||||
EXPECT_FLOAT_EQ(kValue1, statistic[1].floor_value);
|
||||
|
||||
aec3::UpdateDbMetric(value, &statistic);
|
||||
EXPECT_FLOAT_EQ(2.f * kValue0, statistic[0].sum_value);
|
||||
EXPECT_FLOAT_EQ(kValue0, statistic[0].ceil_value);
|
||||
EXPECT_FLOAT_EQ(kValue0, statistic[0].floor_value);
|
||||
EXPECT_FLOAT_EQ(2.f * kValue1, statistic[1].sum_value);
|
||||
EXPECT_FLOAT_EQ(kValue1, statistic[1].ceil_value);
|
||||
EXPECT_FLOAT_EQ(kValue1, statistic[1].floor_value);
|
||||
}
|
||||
|
||||
// Verifies that the TransformDbMetricForReporting method produces the desired
|
||||
// output for values for dBFS.
|
||||
TEST(TransformDbMetricForReporting, DbFsScaling) {
|
||||
std::array<float, kBlockSize> x;
|
||||
FftData X;
|
||||
std::array<float, kFftLengthBy2Plus1> X2;
|
||||
Aec3Fft fft;
|
||||
x.fill(1000.f);
|
||||
fft.ZeroPaddedFft(x, &X);
|
||||
X.Spectrum(Aec3Optimization::kNone, &X2);
|
||||
|
||||
float offset = -10.f * log10(32768.f * 32768.f);
|
||||
EXPECT_NEAR(offset, -90.3f, 0.1f);
|
||||
EXPECT_EQ(
|
||||
static_cast<int>(30.3f),
|
||||
aec3::TransformDbMetricForReporting(
|
||||
true, 0.f, 90.f, offset, 1.f / (kBlockSize * kBlockSize), X2[0]));
|
||||
}
|
||||
|
||||
// Verifies that the TransformDbMetricForReporting method is able to properly
|
||||
// limit the output.
|
||||
TEST(TransformDbMetricForReporting, Limits) {
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
aec3::TransformDbMetricForReporting(false, 0.f, 10.f, 0.f, 1.f, 0.001f));
|
||||
EXPECT_EQ(
|
||||
10,
|
||||
aec3::TransformDbMetricForReporting(false, 0.f, 10.f, 0.f, 1.f, 100.f));
|
||||
}
|
||||
|
||||
// Verifies that the TransformDbMetricForReporting method is able to properly
|
||||
// negate output.
|
||||
TEST(TransformDbMetricForReporting, Negate) {
|
||||
EXPECT_EQ(
|
||||
10,
|
||||
aec3::TransformDbMetricForReporting(true, -20.f, 20.f, 0.f, 1.f, 0.1f));
|
||||
EXPECT_EQ(
|
||||
-10,
|
||||
aec3::TransformDbMetricForReporting(true, -20.f, 20.f, 0.f, 1.f, 10.f));
|
||||
}
|
||||
|
||||
// Verify the Update functionality of DbMetric.
|
||||
TEST(DbMetric, Update) {
|
||||
EchoRemoverMetrics::DbMetric metric(0.f, 20.f, -20.f);
|
||||
constexpr int kNumValues = 100;
|
||||
constexpr float kValue = 10.f;
|
||||
for (int k = 0; k < kNumValues; ++k) {
|
||||
metric.Update(kValue);
|
||||
}
|
||||
EXPECT_FLOAT_EQ(kValue * kNumValues, metric.sum_value);
|
||||
EXPECT_FLOAT_EQ(kValue, metric.ceil_value);
|
||||
EXPECT_FLOAT_EQ(kValue, metric.floor_value);
|
||||
}
|
||||
|
||||
// Verify the constructor functionality of DbMetric.
|
||||
TEST(DbMetric, Constructor) {
|
||||
EchoRemoverMetrics::DbMetric metric;
|
||||
EXPECT_FLOAT_EQ(0.f, metric.sum_value);
|
||||
EXPECT_FLOAT_EQ(0.f, metric.ceil_value);
|
||||
EXPECT_FLOAT_EQ(0.f, metric.floor_value);
|
||||
|
||||
metric = EchoRemoverMetrics::DbMetric(1.f, 2.f, 3.f);
|
||||
EXPECT_FLOAT_EQ(1.f, metric.sum_value);
|
||||
EXPECT_FLOAT_EQ(2.f, metric.floor_value);
|
||||
EXPECT_FLOAT_EQ(3.f, metric.ceil_value);
|
||||
}
|
||||
|
||||
// Verify the general functionality of EchoRemoverMetrics.
|
||||
TEST(EchoRemoverMetrics, NormalUsage) {
|
||||
EchoRemoverMetrics metrics;
|
||||
AecState aec_state;
|
||||
std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
|
||||
std::array<float, kFftLengthBy2Plus1> suppressor_gain;
|
||||
comfort_noise_spectrum.fill(10.f);
|
||||
suppressor_gain.fill(1.f);
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
for (int k = 0; k < kMetricsReportingIntervalBlocks - 1; ++k) {
|
||||
metrics.Update(aec_state, comfort_noise_spectrum, suppressor_gain);
|
||||
EXPECT_FALSE(metrics.MetricsReported());
|
||||
}
|
||||
metrics.Update(aec_state, comfort_noise_spectrum, suppressor_gain);
|
||||
EXPECT_TRUE(metrics.MetricsReported());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -18,7 +18,7 @@
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/echo_path_delay_estimator.h"
|
||||
#include "webrtc/system_wrappers/include/logging.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -81,6 +81,7 @@ class RenderDelayControllerImpl final : public RenderDelayController {
|
||||
int echo_path_delay_samples_ = 0;
|
||||
size_t align_call_counter_ = 0;
|
||||
rtc::Optional<size_t> headroom_samples_;
|
||||
RenderDelayControllerMetrics metrics_;
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl);
|
||||
};
|
||||
|
||||
@ -151,6 +152,8 @@ size_t RenderDelayControllerImpl::GetDelay(
|
||||
headroom_samples_ = rtc::Optional<size_t>();
|
||||
}
|
||||
|
||||
metrics_.Update(echo_path_delay_samples, delay_);
|
||||
|
||||
data_dumper_->DumpRaw("aec3_render_delay_controller_delay", 1,
|
||||
&echo_path_delay_samples_);
|
||||
data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay", delay_);
|
||||
|
||||
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "webrtc/system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
enum class DelayReliabilityCategory {
|
||||
kNone,
|
||||
kPoor,
|
||||
kMedium,
|
||||
kGood,
|
||||
kExcellent,
|
||||
kNumCategories
|
||||
};
|
||||
enum class DelayChangesCategory {
|
||||
kNone,
|
||||
kFew,
|
||||
kSeveral,
|
||||
kMany,
|
||||
kConstant,
|
||||
kNumCategories
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void RenderDelayControllerMetrics::Update(rtc::Optional<size_t> delay_samples,
|
||||
size_t buffer_delay_blocks) {
|
||||
++call_counter_;
|
||||
|
||||
if (!initial_update) {
|
||||
if (delay_samples) {
|
||||
++reliable_delay_estimate_counter_;
|
||||
size_t delay_blocks = (*delay_samples) / kBlockSize;
|
||||
|
||||
if (delay_blocks != delay_blocks_) {
|
||||
++delay_change_counter_;
|
||||
delay_blocks_ = delay_blocks;
|
||||
}
|
||||
}
|
||||
} else if (++initial_call_counter_ == 5 * 250) {
|
||||
initial_update = false;
|
||||
}
|
||||
|
||||
if (call_counter_ == kMetricsReportingIntervalBlocks) {
|
||||
int value_to_report = static_cast<int>(delay_blocks_);
|
||||
value_to_report = std::min(124, value_to_report);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.EchoCanceller.EchoPathDelay",
|
||||
value_to_report, 0, 124, 125);
|
||||
|
||||
value_to_report = static_cast<int>(buffer_delay_blocks);
|
||||
value_to_report = std::min(124, value_to_report);
|
||||
RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.EchoCanceller.BufferDelay",
|
||||
value_to_report, 0, 124, 125);
|
||||
|
||||
DelayReliabilityCategory delay_reliability;
|
||||
if (reliable_delay_estimate_counter_ == 0) {
|
||||
delay_reliability = DelayReliabilityCategory::kNone;
|
||||
} else if (reliable_delay_estimate_counter_ > (call_counter_ >> 1)) {
|
||||
delay_reliability = DelayReliabilityCategory::kExcellent;
|
||||
} else if (reliable_delay_estimate_counter_ > 100) {
|
||||
delay_reliability = DelayReliabilityCategory::kGood;
|
||||
} else if (reliable_delay_estimate_counter_ > 10) {
|
||||
delay_reliability = DelayReliabilityCategory::kMedium;
|
||||
} else {
|
||||
delay_reliability = DelayReliabilityCategory::kPoor;
|
||||
}
|
||||
RTC_HISTOGRAM_ENUMERATION(
|
||||
"WebRTC.Audio.EchoCanceller.ReliableDelayEstimates",
|
||||
static_cast<int>(delay_reliability),
|
||||
static_cast<int>(DelayReliabilityCategory::kNumCategories));
|
||||
|
||||
DelayChangesCategory delay_changes;
|
||||
if (delay_change_counter_ == 0) {
|
||||
delay_changes = DelayChangesCategory::kNone;
|
||||
} else if (delay_change_counter_ > 10) {
|
||||
delay_changes = DelayChangesCategory::kConstant;
|
||||
} else if (delay_change_counter_ > 5) {
|
||||
delay_changes = DelayChangesCategory::kMany;
|
||||
} else if (delay_change_counter_ > 2) {
|
||||
delay_changes = DelayChangesCategory::kSeveral;
|
||||
} else {
|
||||
delay_changes = DelayChangesCategory::kFew;
|
||||
}
|
||||
RTC_HISTOGRAM_ENUMERATION(
|
||||
"WebRTC.Audio.EchoCanceller.DelayChanges",
|
||||
static_cast<int>(delay_changes),
|
||||
static_cast<int>(DelayChangesCategory::kNumCategories));
|
||||
|
||||
metrics_reported_ = true;
|
||||
call_counter_ = 0;
|
||||
ResetMetrics();
|
||||
} else {
|
||||
metrics_reported_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderDelayControllerMetrics::ResetMetrics() {
|
||||
delay_change_counter_ = 0;
|
||||
reliable_delay_estimate_counter_ = 0;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_METRICS_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_METRICS_H_
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/optional.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Handles the reporting of metrics for the render delay controller.
|
||||
class RenderDelayControllerMetrics {
|
||||
public:
|
||||
RenderDelayControllerMetrics() = default;
|
||||
|
||||
// Updates the metric with new data.
|
||||
void Update(rtc::Optional<size_t> delay_samples, size_t buffer_delay_blocks);
|
||||
|
||||
// Returns true if the metrics have just been reported, otherwise false.
|
||||
bool MetricsReported() { return metrics_reported_; }
|
||||
|
||||
private:
|
||||
// Resets the metrics.
|
||||
void ResetMetrics();
|
||||
|
||||
size_t delay_blocks_ = 0;
|
||||
int reliable_delay_estimate_counter_ = 0;
|
||||
int delay_change_counter_ = 0;
|
||||
int call_counter_ = 0;
|
||||
int initial_call_counter_ = 0;
|
||||
bool metrics_reported_ = false;
|
||||
bool initial_update = true;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RenderDelayControllerMetrics);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_METRICS_H_
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/optional.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h"
|
||||
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Verify the general functionality of RenderDelayControllerMetrics.
|
||||
TEST(RenderDelayControllerMetrics, NormalUsage) {
|
||||
RenderDelayControllerMetrics metrics;
|
||||
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
for (int k = 0; k < kMetricsReportingIntervalBlocks - 1; ++k) {
|
||||
metrics.Update(rtc::Optional<size_t>(), 0);
|
||||
EXPECT_FALSE(metrics.MetricsReported());
|
||||
}
|
||||
metrics.Update(rtc::Optional<size_t>(), 0);
|
||||
EXPECT_TRUE(metrics.MetricsReported());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
Reference in New Issue
Block a user