Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: webrtc/modules/audio_processing/test/fake_recording_device_unittest.cc

Issue 2834643002: audioproc_f with simulated mic analog gain (Closed)
Patch Set: Merge + comments addressed Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <memory>
12 #include <sstream>
13 #include <string>
14 #include <vector>
15
16 #include "webrtc/base/array_view.h"
17 #include "webrtc/base/optional.h"
18 #include "webrtc/base/ptr_util.h"
19 #include "webrtc/modules/audio_processing/test/fake_recording_device.h"
20 #include "webrtc/test/gtest.h"
21
22 namespace webrtc {
23 namespace test {
24 namespace {
25
26 rtc::Optional<int> kRealDeviceLevelUnknown;
27
28 constexpr int kInitialMicLevel = 100;
29
30 // TODO(alessiob): Add new fake recording device kinds here as they are added to
31 // FakeRecordingDevice::DeviceKind.
32 const std::vector<FakeRecordingDevice::DeviceKind> kFakeRecDeviceKinds = {
33 FakeRecordingDevice::DeviceKind::IDENTITY,
34 FakeRecordingDevice::DeviceKind::LINEAR,
35 };
36
37 const std::vector<std::vector<float>> kTestMultiChannelSamples{
38 std::vector<float>{-10.0, -1.0, -0.1, 0.0, 0.1, 1.0, 10.0}};
39
40 // Writes samples into ChannelBuffer<float>.
41 void WritesDataIntoChannelBuffer(const std::vector<std::vector<float>>& data,
42 ChannelBuffer<float>* buff) {
43 EXPECT_EQ(data.size(), buff->num_channels());
44 EXPECT_EQ(data[0].size(), buff->num_frames());
45 for (size_t c = 0; c < buff->num_channels(); ++c) {
46 for (size_t f = 0; f < buff->num_frames(); ++f) {
47 buff->channels()[c][f] = data[c][f];
48 }
49 }
50 }
51
52 std::unique_ptr<ChannelBuffer<float>> CreateChannelBufferWithData(
53 const std::vector<std::vector<float>>& data) {
54 auto buff =
55 rtc::MakeUnique<ChannelBuffer<float>>(data[0].size(), data.size());
AleBzk 2017/06/29 11:43:37 Just git cl format
56 WritesDataIntoChannelBuffer(data, buff.get());
57 return buff;
58 }
59
60 // Checks that the samples modified using monotonic level values are also
61 // monotonic.
62 void CheckIfMonotoneSamplesModules(const ChannelBuffer<float>* prev,
63 const ChannelBuffer<float>* curr) {
AleBzk 2017/06/29 11:43:37 Just git cl format
64 RTC_DCHECK_EQ(prev->num_channels(), curr->num_channels());
65 RTC_DCHECK_EQ(prev->num_frames(), curr->num_frames());
66 bool valid = true;
67 for (size_t i = 0; i < prev->num_channels(); ++i) {
68 for (size_t j = 0; j < prev->num_frames(); ++j) {
69 valid = std::fabs(prev->channels()[i][j]) <=
70 std::fabs(curr->channels()[i][j]);
71 if (!valid) {
72 break;
73 }
74 }
75 if (!valid) {
76 break;
77 }
AleBzk 2017/06/29 11:43:36 Just git cl format
78 }
79 EXPECT_TRUE(valid);
80 }
81
82 // Checks that the samples in each pair have the same sign unless the sample in
83 // |dst| is zero (because of zero gain).
84 void CheckSameSign(const ChannelBuffer<float>* src,
85 const ChannelBuffer<float>* dst) {
AleBzk 2017/06/29 11:43:36 Just git cl format
86 RTC_DCHECK_EQ(src->num_channels(), dst->num_channels());
87 RTC_DCHECK_EQ(src->num_frames(), dst->num_frames());
88 const auto fsgn = [](float x) { return ((x < 0) ? -1 : (x > 0) ? 1 : 0); };
89 bool valid = true;
90 for (size_t i = 0; i < src->num_channels(); ++i) {
91 for (size_t j = 0; j < src->num_frames(); ++j) {
92 valid = dst->channels()[i][j] == 0.0f ||
93 fsgn(src->channels()[i][j]) == fsgn(dst->channels()[i][j]);
94 if (!valid) {
95 break;
96 }
97 }
98 if (!valid) {
99 break;
100 }
AleBzk 2017/06/29 11:43:37 Just git cl format
101 }
102 EXPECT_TRUE(valid);
103 }
104
105 std::string FakeRecordingDeviceKindToString(
106 FakeRecordingDevice::DeviceKind fake_rec_device_kind) {
107 std::ostringstream ss;
108 ss << "fake recording device: " << static_cast<size_t>(fake_rec_device_kind);
109 return ss.str();
110 }
111
112 std::string AnalogLevelToString(int level) {
113 std::ostringstream ss;
114 ss << "analog level: " << level;
115 return ss.str();
116 }
117
118 } // namespace
119
120 TEST(FakeRecordingDevice, CheckHelperFunctions) {
121 constexpr size_t kC = 0; // Channel index.
122 constexpr size_t kS = 1; // Sample index.
123
124 // Check read.
125 auto buff = CreateChannelBufferWithData(kTestMultiChannelSamples);
126 for (size_t c = 0; c < kTestMultiChannelSamples.size(); ++c) {
127 for (size_t s = 0; s < kTestMultiChannelSamples[0].size(); ++s) {
128 EXPECT_EQ(kTestMultiChannelSamples[c][s], buff->channels()[c][s]);
129 }
130 }
131
132 // Check write.
133 buff->channels()[kC][kS] = -5.0f;
134 RTC_DCHECK_NE(buff->channels()[kC][kS], kTestMultiChannelSamples[kC][kS]);
AleBzk 2017/06/29 11:43:37 Just git cl format
135
136 // Check reset.
137 WritesDataIntoChannelBuffer(kTestMultiChannelSamples, buff.get());
138 EXPECT_EQ(buff->channels()[kC][kS], kTestMultiChannelSamples[kC][kS]);
139 }
140
141 // Implicitly checks that changes to the mic and undo levels are visible to the
142 // FakeRecordingDeviceWorker implementation are injected in FakeRecordingDevice.
143 TEST(FakeRecordingDevice, TestWorkerAbstractClass) {
144 FakeRecordingDevice fake_recording_device(
145 kInitialMicLevel, FakeRecordingDevice::DeviceKind::LINEAR);
146
147 auto buff1 = CreateChannelBufferWithData(kTestMultiChannelSamples);
148 fake_recording_device.set_mic_level(100);
149 fake_recording_device.set_undo_mic_level(rtc::Optional<int>());
150 fake_recording_device.SimulateAnalogGain(buff1.get());
151
152 auto buff2 = CreateChannelBufferWithData(kTestMultiChannelSamples);
153 fake_recording_device.set_mic_level(200);
154 fake_recording_device.set_undo_mic_level(rtc::Optional<int>());
155 fake_recording_device.SimulateAnalogGain(buff2.get());
156
157 for (size_t c = 0; c < kTestMultiChannelSamples.size(); ++c) {
158 for (size_t s = 0; s < kTestMultiChannelSamples[0].size(); ++s) {
159 EXPECT_LE(std::abs(buff1->channels()[c][s]),
160 std::abs(buff2->channels()[c][s]));
161 }
162 }
163
164 auto buff3 = CreateChannelBufferWithData(kTestMultiChannelSamples);
165 fake_recording_device.set_mic_level(200);
166 fake_recording_device.set_undo_mic_level(rtc::Optional<int>(100));
167 fake_recording_device.SimulateAnalogGain(buff3.get());
168
169 for (size_t c = 0; c < kTestMultiChannelSamples.size(); ++c) {
170 for (size_t s = 0; s < kTestMultiChannelSamples[0].size(); ++s) {
171 EXPECT_LE(std::abs(buff1->channels()[c][s]),
172 std::abs(buff3->channels()[c][s]));
173 EXPECT_LE(std::abs(buff2->channels()[c][s]),
174 std::abs(buff3->channels()[c][s]));
175 }
176 }
177 }
178
179 TEST(FakeRecordingDevice, GainCurveShouldBeMonotone) {
180 // Create input-output buffers.
181 auto buff_prev = CreateChannelBufferWithData(kTestMultiChannelSamples);
182 auto buff_curr = CreateChannelBufferWithData(kTestMultiChannelSamples);
183
184 // Test different mappings.
185 for (auto fake_rec_device_kind : kFakeRecDeviceKinds) {
186 SCOPED_TRACE(FakeRecordingDeviceKindToString(fake_rec_device_kind));
187 FakeRecordingDevice fake_recording_device(kInitialMicLevel,
188 fake_rec_device_kind);
AleBzk 2017/06/29 11:43:36 Just git cl format
189 fake_recording_device.set_undo_mic_level(kRealDeviceLevelUnknown);
190 // TODO(alessiob): The test below is designed for state-less recording
191 // devices. If, for instance, a device has memory, the test might need
192 // to be redesigned (e.g., re-initialize fake recording device).
193
194 // Apply lowest analog level.
195 WritesDataIntoChannelBuffer(kTestMultiChannelSamples, buff_prev.get());
196 fake_recording_device.set_mic_level(0);
197 fake_recording_device.SimulateAnalogGain(buff_prev.get());
198
199 // Increment analog level to check monotonicity.
200 for (int i = 1; i <= 255; ++i) {
201 SCOPED_TRACE(AnalogLevelToString(i));
202 WritesDataIntoChannelBuffer(kTestMultiChannelSamples, buff_curr.get());
203 fake_recording_device.set_mic_level(i);
204 fake_recording_device.SimulateAnalogGain(buff_curr.get());
205 CheckIfMonotoneSamplesModules(buff_prev.get(), buff_curr.get());
206
207 // Update prev.
208 buff_prev.swap(buff_curr);
209 }
210 }
211 }
212
213 TEST(FakeRecordingDevice, GainCurveShouldNotChangeSign) {
214 // Create view on orignal samples.
215 std::unique_ptr<const ChannelBuffer<float>> buff_orig =
216 CreateChannelBufferWithData(kTestMultiChannelSamples);
217
218 // Create output buffer.
219 auto buff = CreateChannelBufferWithData(kTestMultiChannelSamples);
220
221 // Test different mappings.
222 for (auto fake_rec_device_kind : kFakeRecDeviceKinds) {
223 SCOPED_TRACE(FakeRecordingDeviceKindToString(fake_rec_device_kind));
224 FakeRecordingDevice fake_recording_device(kInitialMicLevel,
225 fake_rec_device_kind);
AleBzk 2017/06/29 11:43:36 Just git cl format
226 fake_recording_device.set_undo_mic_level(kRealDeviceLevelUnknown);
227 // TODO(alessiob): The test below is designed for state-less recording
228 // devices. If, for instance, a device has memory, the test might need
229 // to be redesigned (e.g., re-initialize fake recording device).
230
231 for (int i = 0; i <= 255; ++i) {
232 SCOPED_TRACE(AnalogLevelToString(i));
233 WritesDataIntoChannelBuffer(kTestMultiChannelSamples, buff.get());
234 fake_recording_device.set_mic_level(i);
235 fake_recording_device.SimulateAnalogGain(buff.get());
236 CheckSameSign(buff_orig.get(), buff.get());
237 }
238 }
239 }
240
241 } // namespace test
242 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698