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 "modules/audio_processing/aec3/echo_remover_metrics.h"
12 
13 #include <math.h>
14 
15 #include "modules/audio_processing/aec3/aec_state.h"
16 #include "modules/audio_processing/aec3/aec3_fft.h"
17 #include "test/gtest.h"
18 
19 namespace webrtc {
20 
21 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
22 
23 // Verifies the check for non-null input.
TEST(UpdateDbMetric,NullValue)24 TEST(UpdateDbMetric, NullValue) {
25   std::array<float, kFftLengthBy2Plus1> value;
26   value.fill(0.f);
27   EXPECT_DEATH(aec3::UpdateDbMetric(value, nullptr), "");
28 }
29 
30 #endif
31 
32 // Verifies the updating functionality of UpdateDbMetric.
TEST(UpdateDbMetric,Updating)33 TEST(UpdateDbMetric, Updating) {
34   std::array<float, kFftLengthBy2Plus1> value;
35   std::array<EchoRemoverMetrics::DbMetric, 2> statistic;
36   statistic.fill(EchoRemoverMetrics::DbMetric(0.f, 100.f, -100.f));
37   constexpr float kValue0 = 10.f;
38   constexpr float kValue1 = 20.f;
39   std::fill(value.begin(), value.begin() + 32, kValue0);
40   std::fill(value.begin() + 32, value.begin() + 64, kValue1);
41 
42   aec3::UpdateDbMetric(value, &statistic);
43   EXPECT_FLOAT_EQ(kValue0, statistic[0].sum_value);
44   EXPECT_FLOAT_EQ(kValue0, statistic[0].ceil_value);
45   EXPECT_FLOAT_EQ(kValue0, statistic[0].floor_value);
46   EXPECT_FLOAT_EQ(kValue1, statistic[1].sum_value);
47   EXPECT_FLOAT_EQ(kValue1, statistic[1].ceil_value);
48   EXPECT_FLOAT_EQ(kValue1, statistic[1].floor_value);
49 
50   aec3::UpdateDbMetric(value, &statistic);
51   EXPECT_FLOAT_EQ(2.f * kValue0, statistic[0].sum_value);
52   EXPECT_FLOAT_EQ(kValue0, statistic[0].ceil_value);
53   EXPECT_FLOAT_EQ(kValue0, statistic[0].floor_value);
54   EXPECT_FLOAT_EQ(2.f * kValue1, statistic[1].sum_value);
55   EXPECT_FLOAT_EQ(kValue1, statistic[1].ceil_value);
56   EXPECT_FLOAT_EQ(kValue1, statistic[1].floor_value);
57 }
58 
59 // Verifies that the TransformDbMetricForReporting method produces the desired
60 // output for values for dBFS.
TEST(TransformDbMetricForReporting,DbFsScaling)61 TEST(TransformDbMetricForReporting, DbFsScaling) {
62   std::array<float, kBlockSize> x;
63   FftData X;
64   std::array<float, kFftLengthBy2Plus1> X2;
65   Aec3Fft fft;
66   x.fill(1000.f);
67   fft.ZeroPaddedFft(x, &X);
68   X.Spectrum(Aec3Optimization::kNone, &X2);
69 
70   float offset = -10.f * log10(32768.f * 32768.f);
71   EXPECT_NEAR(offset, -90.3f, 0.1f);
72   EXPECT_EQ(
73       static_cast<int>(30.3f),
74       aec3::TransformDbMetricForReporting(
75           true, 0.f, 90.f, offset, 1.f / (kBlockSize * kBlockSize), X2[0]));
76 }
77 
78 // Verifies that the TransformDbMetricForReporting method is able to properly
79 // limit the output.
TEST(TransformDbMetricForReporting,Limits)80 TEST(TransformDbMetricForReporting, Limits) {
81   EXPECT_EQ(
82       0,
83       aec3::TransformDbMetricForReporting(false, 0.f, 10.f, 0.f, 1.f, 0.001f));
84   EXPECT_EQ(
85       10,
86       aec3::TransformDbMetricForReporting(false, 0.f, 10.f, 0.f, 1.f, 100.f));
87 }
88 
89 // Verifies that the TransformDbMetricForReporting method is able to properly
90 // negate output.
TEST(TransformDbMetricForReporting,Negate)91 TEST(TransformDbMetricForReporting, Negate) {
92   EXPECT_EQ(
93       10,
94       aec3::TransformDbMetricForReporting(true, -20.f, 20.f, 0.f, 1.f, 0.1f));
95   EXPECT_EQ(
96       -10,
97       aec3::TransformDbMetricForReporting(true, -20.f, 20.f, 0.f, 1.f, 10.f));
98 }
99 
100 // Verify the Update functionality of DbMetric.
TEST(DbMetric,Update)101 TEST(DbMetric, Update) {
102   EchoRemoverMetrics::DbMetric metric(0.f, 20.f, -20.f);
103   constexpr int kNumValues = 100;
104   constexpr float kValue = 10.f;
105   for (int k = 0; k < kNumValues; ++k) {
106     metric.Update(kValue);
107   }
108   EXPECT_FLOAT_EQ(kValue * kNumValues, metric.sum_value);
109   EXPECT_FLOAT_EQ(kValue, metric.ceil_value);
110   EXPECT_FLOAT_EQ(kValue, metric.floor_value);
111 }
112 
113 // Verify the constructor functionality of DbMetric.
TEST(DbMetric,Constructor)114 TEST(DbMetric, Constructor) {
115   EchoRemoverMetrics::DbMetric metric;
116   EXPECT_FLOAT_EQ(0.f, metric.sum_value);
117   EXPECT_FLOAT_EQ(0.f, metric.ceil_value);
118   EXPECT_FLOAT_EQ(0.f, metric.floor_value);
119 
120   metric = EchoRemoverMetrics::DbMetric(1.f, 2.f, 3.f);
121   EXPECT_FLOAT_EQ(1.f, metric.sum_value);
122   EXPECT_FLOAT_EQ(2.f, metric.floor_value);
123   EXPECT_FLOAT_EQ(3.f, metric.ceil_value);
124 }
125 
126 // Verify the general functionality of EchoRemoverMetrics.
TEST(EchoRemoverMetrics,NormalUsage)127 TEST(EchoRemoverMetrics, NormalUsage) {
128   EchoRemoverMetrics metrics;
129   AecState aec_state(EchoCanceller3Config{});
130   std::array<float, kFftLengthBy2Plus1> comfort_noise_spectrum;
131   std::array<float, kFftLengthBy2Plus1> suppressor_gain;
132   comfort_noise_spectrum.fill(10.f);
133   suppressor_gain.fill(1.f);
134   for (int j = 0; j < 3; ++j) {
135     for (int k = 0; k < kMetricsReportingIntervalBlocks - 1; ++k) {
136       metrics.Update(aec_state, comfort_noise_spectrum, suppressor_gain);
137       EXPECT_FALSE(metrics.MetricsReported());
138     }
139     metrics.Update(aec_state, comfort_noise_spectrum, suppressor_gain);
140     EXPECT_TRUE(metrics.MetricsReported());
141   }
142 }
143 
144 }  // namespace webrtc
145