OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 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/agc/agc.h" | |
12 | |
13 #include "testing/gmock/include/gmock/gmock.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 #include "webrtc/modules/include/module_common_types.h" | |
17 #include "webrtc/test/testsupport/fileutils.h" | |
18 #include "webrtc/tools/agc/test_utils.h" | |
19 | |
20 using ::testing::_; | |
21 using ::testing::AllOf; | |
22 using ::testing::AtLeast; | |
23 using ::testing::Eq; | |
24 using ::testing::Gt; | |
25 using ::testing::InSequence; | |
26 using ::testing::Lt; | |
27 using ::testing::Mock; | |
28 using ::testing::SaveArg; | |
29 | |
30 namespace webrtc { | |
31 namespace { | |
32 | |
33 // The tested values depend on this assumed gain. | |
34 const int kMaxGain = 80; | |
35 | |
36 MATCHER_P(GtPointee, p, "") { return arg > *p; } | |
37 MATCHER_P(LtPointee, p, "") { return arg < *p; } | |
38 | |
39 class AgcChecker { | |
40 public: | |
41 MOCK_METHOD2(LevelChanged, void(int iterations, int level)); | |
42 }; | |
43 | |
44 class AgcTest : public ::testing::Test { | |
45 protected: | |
46 AgcTest() | |
47 : agc_(), | |
48 checker_(), | |
49 mic_level_(128) { | |
50 } | |
51 | |
52 // A gain of <= -100 will zero out the signal. | |
53 void RunAgc(int iterations, float gain_db) { | |
54 FILE* input_file = fopen( | |
55 test::ResourcePath("voice_engine/audio_long16", "pcm").c_str(), "rb"); | |
56 ASSERT_TRUE(input_file != NULL); | |
57 | |
58 AudioFrame frame; | |
59 frame.sample_rate_hz_ = 16000; | |
60 frame.num_channels_ = 1; | |
61 frame.samples_per_channel_ = frame.sample_rate_hz_ / 100; | |
62 const size_t length = frame.samples_per_channel_ * frame.num_channels_; | |
63 | |
64 float gain = Db2Linear(gain_db); | |
65 if (gain_db <= -100) { | |
66 gain = 0; | |
67 } | |
68 | |
69 for (int i = 0; i < iterations; ++i) { | |
70 ASSERT_EQ(length, fread(frame.data_, sizeof(int16_t), length, | |
71 input_file)); | |
72 SimulateMic(kMaxGain, mic_level_, &frame); | |
73 ApplyGainLinear(gain, &frame); | |
74 ASSERT_GE(agc_.Process(frame), 0); | |
75 | |
76 int mic_level = agc_.MicLevel(); | |
77 if (mic_level != mic_level_) { | |
78 printf("mic_level=%d\n", mic_level); | |
79 checker_.LevelChanged(i, mic_level); | |
80 } | |
81 mic_level_ = mic_level; | |
82 } | |
83 fclose(input_file); | |
84 } | |
85 | |
86 Agc agc_; | |
87 AgcChecker checker_; | |
88 // Stores mic level between multiple runs of RunAgc in one test. | |
89 int mic_level_; | |
90 }; | |
91 | |
92 TEST_F(AgcTest, UpwardsChangeIsLimited) { | |
93 { | |
94 InSequence seq; | |
95 EXPECT_CALL(checker_, LevelChanged(Lt(500), Eq(179))).Times(1); | |
96 EXPECT_CALL(checker_, LevelChanged(_, Gt(179))).Times(AtLeast(1)); | |
97 } | |
98 RunAgc(1000, -40); | |
99 } | |
100 | |
101 TEST_F(AgcTest, DownwardsChangeIsLimited) { | |
102 { | |
103 InSequence seq; | |
104 EXPECT_CALL(checker_, LevelChanged(Lt(500), Eq(77))).Times(1); | |
105 EXPECT_CALL(checker_, LevelChanged(_, Lt(77))).Times(AtLeast(1)); | |
106 } | |
107 RunAgc(1000, 40); | |
108 } | |
109 | |
110 TEST_F(AgcTest, MovesUpToMaxAndDownToMin) { | |
111 int last_level = 128; | |
112 EXPECT_CALL(checker_, LevelChanged(_, GtPointee(&last_level))) | |
113 .Times(AtLeast(2)) | |
114 .WillRepeatedly(SaveArg<1>(&last_level)); | |
115 RunAgc(1000, -30); | |
116 EXPECT_EQ(255, last_level); | |
117 Mock::VerifyAndClearExpectations(&checker_); | |
118 | |
119 EXPECT_CALL(checker_, LevelChanged(_, LtPointee(&last_level))) | |
120 .Times(AtLeast(2)) | |
121 .WillRepeatedly(SaveArg<1>(&last_level)); | |
122 RunAgc(1000, 50); | |
123 EXPECT_EQ(1, last_level); | |
124 } | |
125 | |
126 TEST_F(AgcTest, HandlesZeroSignal) { | |
127 int last_level = 128; | |
128 // Doesn't respond to a zero signal. | |
129 EXPECT_CALL(checker_, LevelChanged(_, _)).Times(0); | |
130 RunAgc(1000, -100); | |
131 Mock::VerifyAndClearExpectations(&checker_); | |
132 | |
133 // Reacts as usual afterwards. | |
134 EXPECT_CALL(checker_, LevelChanged(_, GtPointee(&last_level))) | |
135 .Times(AtLeast(2)) | |
136 .WillRepeatedly(SaveArg<1>(&last_level)); | |
137 RunAgc(500, -20); | |
138 } | |
139 | |
140 TEST_F(AgcTest, ReachesSteadyState) { | |
141 int last_level = 128; | |
142 EXPECT_CALL(checker_, LevelChanged(_, _)) | |
143 .Times(AtLeast(2)) | |
144 .WillRepeatedly(SaveArg<1>(&last_level)); | |
145 RunAgc(1000, -20); | |
146 Mock::VerifyAndClearExpectations(&checker_); | |
147 | |
148 // If the level changes, it should be in a narrow band around the previous | |
149 // adaptation. | |
150 EXPECT_CALL(checker_, LevelChanged(_, | |
151 AllOf(Gt(last_level * 0.95), Lt(last_level * 1.05)))) | |
152 .Times(AtLeast(0)); | |
153 RunAgc(1000, -20); | |
154 } | |
155 | |
156 // TODO(ajm): Add this test; requires measuring the signal RMS. | |
157 TEST_F(AgcTest, AdaptsToCorrectRMS) { | |
158 } | |
159 | |
160 } // namespace | |
161 } // namespace webrtc | |
162 | |
OLD | NEW |