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

Side by Side Diff: webrtc/modules/audio_processing/repetition_detector_unittest.cc

Issue 1287663002: Adding audio RepetitionDetector in AudioProcessingModule. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: more comments addressed Created 5 years, 3 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
« no previous file with comments | « webrtc/modules/audio_processing/repetition_detector.cc ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 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 <map>
12
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/base/arraysize.h"
15 #include "webrtc/base/scoped_ptr.h"
16 #include "webrtc/modules/audio_processing/repetition_detector.h"
17 #include "webrtc/modules/remote_bitrate_estimator/test/random.h"
18
19 namespace webrtc {
20
21 class RepetitionDetectorForTest : public RepetitionDetector {
22 public:
23 int GetCount(int id) {
24 auto it = counters_.find(id);
25 if (it == counters_.end()) {
26 return 0;
27 }
28 return counters_[id];
29 }
30
31 void ResetCounters() {
32 for (auto& item : counters_) {
33 item.second = 0;
34 }
35 }
36
37 void ResetRepetitionPattern(const RepetitionDetector::Pattern* patterns,
38 size_t num_patterns) {
39 states_.clear();
40 RegisterRepetitionPatterns(patterns, num_patterns);
41 }
42
43 void set_max_frames(size_t max_frames) { max_frames_ = max_frames; }
44
45 private:
46 void ReportRepetition(int id) override {
47 auto it = counters_.find(id);
48 if (it == counters_.end()) {
49 counters_[id] = 0;
50 }
51 counters_[id]++;
52 }
53
54 std::map<int, size_t> counters_;
55 };
56
57 class RepetitionDetectorTest : public ::testing::Test {
58 protected:
59 struct ExpectedCount {
60 int id_;
61 int count_;
62 };
63
64 // Verify if the counts on the repetition patterns match expectation after
65 // injecting a signal. No reset on the counters
66 void Verify(const ExpectedCount* expected_counts, size_t num_patterns,
67 const float* tester, size_t num_frames,
68 int sample_rate_hz, size_t channels = 1) {
69 detector_.Detect(tester, num_frames, channels, sample_rate_hz);
70 int id;
71 for (size_t idx = 0; idx < num_patterns; idx++) {
72 id = expected_counts[idx].id_;
73 EXPECT_EQ(expected_counts[idx].count_, detector_.GetCount(id)) <<
74 "Repetition #" << id << " counted wrong.";
75 }
76 }
77
78 void VerifyStereo(const ExpectedCount* expected_counts, size_t num_patterns,
79 const float* tester, size_t num_frames,
80 int sample_rate_hz) {
81 const size_t kNumChannels = 2;
82
83 // Get memory to store interleaved stereo.
84 rtc::scoped_ptr<float[]> tester_stereo(
85 new float[num_frames * kNumChannels]);
86
87 for (size_t idx = 0; idx < num_frames; ++idx, ++tester) {
88 for (size_t channel = 0; channel < kNumChannels; ++channel) {
89 tester_stereo[idx * kNumChannels + channel] = *tester;
90 }
91 }
92
93 Verify(expected_counts, num_patterns, tester_stereo.get(),
94 num_frames, sample_rate_hz, kNumChannels);
95 }
96
97 void ResetRepetitionPattern(const RepetitionDetector::Pattern* patterns,
98 size_t num_patterns) {
99 detector_.ResetRepetitionPattern(patterns, num_patterns);
100 }
101
102 void SetMaxFrames(size_t max_frames) {
103 detector_.set_max_frames(max_frames);
104 }
105
106 void ResetCounters() {
107 detector_.ResetCounters();
108 }
109
110 private:
111 RepetitionDetectorForTest detector_;
112 };
113
114 TEST_F(RepetitionDetectorTest, Basic) {
115 // To make the test signal most obvious, we choose a special sample rate.
116 const int kSampleRateHz = 1000;
117
118 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
119 // id, look_back_ms, min_length_ms
120 {0, 3, 3}
121 };
122 const float kTestSignal[] = {1, 2, 3, 1, 2, 3};
123 const ExpectedCount kExpectedCounts_1[] = {
124 {0, 1}
125 };
126 const ExpectedCount kExpectedCounts_2[] = {
127 {0, 1}
128 };
129
130 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
131 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
132 arraysize(kTestSignal), kSampleRateHz);
133 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
134 arraysize(kTestSignal), kSampleRateHz);
135 ResetCounters();
136
137 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
138 arraysize(kTestSignal), kSampleRateHz);
139 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
140 arraysize(kTestSignal), kSampleRateHz);
141 }
142
143 TEST_F(RepetitionDetectorTest, StereoOutOfSync) {
144 // To make the test signal most obvious, we choose a special sample rate.
145 const int kSampleRateHz = 1000;
146
147 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
148 // id, look_back_ms, min_length_ms
149 {0, 3, 3}
150 };
151 const float kTestSignal[] = {
152 1, 1,
153 2, 2,
154 3, 3,
155 1, 1,
156 2, 2,
157 3, 1};
158 const ExpectedCount kExpectedCounts[] = {
159 {0, 0}
160 };
161
162 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
163 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
164 arraysize(kTestSignal) / 2, kSampleRateHz, 2);
165 }
166
167 TEST_F(RepetitionDetectorTest, IncompletePattern) {
168 // To make the test signal most obvious, we choose a special sample rate.
169 const int kSampleRateHz = 1000;
170
171 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
172 // id, look_back_ms, min_length_ms
173 {0, 3, 3},
174 };
175 const float kTestSignal[] = {1, 2, 1, 2, 3, 1, 2, 3};
176 const ExpectedCount kExpectedCounts[] = {
177 {0, 1},
178 };
179
180 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
181 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
182 arraysize(kTestSignal), kSampleRateHz);
183 ResetCounters();
184 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
185 arraysize(kTestSignal), kSampleRateHz);
186 }
187
188 TEST_F(RepetitionDetectorTest, PatternLongerThanFrame) {
189 // To make the test signal most obvious, we choose a special sample rate.
190 const int kSampleRateHz = 1000;
191
192 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
193 // id, look_back_ms, min_length_ms
194 {0, 6, 6},
195 };
196 const float kTestSignal_1[] = {1, 2, 3, 4, 5};
197 const float kTestSignal_2[] = {6, 1, 2, 3, 4, 5, 6};
198 const ExpectedCount kExpectedCounts_1[] = {
199 {0, 0},
200 };
201 const ExpectedCount kExpectedCounts_2[] = {
202 {0, 1},
203 };
204
205 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
206 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
207 arraysize(kTestSignal_1), kSampleRateHz);
208 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
209 arraysize(kTestSignal_2), kSampleRateHz);
210 ResetCounters();
211 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
212 arraysize(kTestSignal_1), kSampleRateHz);
213 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
214 arraysize(kTestSignal_2), kSampleRateHz);
215 }
216
217 TEST_F(RepetitionDetectorTest, TwoPatterns) {
218 // To make the test signal most obvious, we choose a special sample rate.
219 const int kSampleRateHz = 1000;
220
221 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
222 // id, look_back_ms, min_length_ms
223 {0, 3, 3},
224 {1, 4, 4},
225 };
226 const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4};
227 const ExpectedCount kExpectedCounts[] = {
228 // 1,2,3 belongs to both patterns.
229 {0, 1},
230 {1, 1}
231 };
232
233 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
234 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
235 arraysize(kTestSignal), kSampleRateHz);
236 ResetCounters();
237 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
238 arraysize(kTestSignal), kSampleRateHz);
239 }
240
241 TEST_F(RepetitionDetectorTest, MaxFramesShorterThanInput) {
242 // To make the test signal most obvious, we choose a special sample rate.
243 const int kSampleRateHz = 1000;
244
245 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
246 // id, look_back_ms, min_length_ms
247 {0, 3, 3},
248 {1, 4, 4},
249 };
250 const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4};
251 const ExpectedCount kExpectedCounts[] = {
252 // 1,2,3 belongs to both patterns.
253 {0, 1},
254 {1, 1}
255 };
256
257 // length of kTestSignal is 11 but I set maximum frames to be 2. The detection
258 // should still work.
259 SetMaxFrames(2);
260 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
261 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
262 arraysize(kTestSignal), kSampleRateHz);
263 ResetCounters();
264 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
265 arraysize(kTestSignal), kSampleRateHz);
266 }
267
268 TEST_F(RepetitionDetectorTest, NestedPatterns) {
269 // To make the test signal most obvious, we choose a special sample rate.
270 const int kSampleRateHz = 1000;
271
272 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
273 // id, look_back_ms, min_length_ms
274 {0, 3, 3},
275 {1, 6, 6}, // When a triplet repeated 3 times, this is triggered.
276 };
277 const float kTestSignal[] = {1, 2, 3, 1, 2, 3};
278 const ExpectedCount kExpectedCounts_1[] = {
279 {0, 1},
280 {1, 0}
281 };
282 const ExpectedCount kExpectedCounts_2[] = {
283 {0, 1},
284 {1, 1}
285 };
286
287 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
288 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
289 arraysize(kTestSignal), kSampleRateHz);
290 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
291 arraysize(kTestSignal), kSampleRateHz);
292 ResetCounters();
293 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
294 arraysize(kTestSignal), kSampleRateHz);
295 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
296 arraysize(kTestSignal), kSampleRateHz);
297 }
298
299 TEST_F(RepetitionDetectorTest, NotFullLengthPattern) {
300 // To make the test signal most obvious, we choose a special sample rate.
301 const int kSampleRateHz = 1000;
302
303 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
304 // id, look_back_ms, min_length_ms
305 {0, 4, 3},
306 };
307 const float kTestSignal[] = {1, 2, 3, -1, 1, 2, 3, -2};
308 const ExpectedCount kExpectedCounts[] = {
309 {0, 1},
310 };
311
312 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
313 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
314 arraysize(kTestSignal), kSampleRateHz);
315 ResetCounters();
316 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
317 arraysize(kTestSignal), kSampleRateHz);
318 }
319
320 TEST_F(RepetitionDetectorTest, ZerosCountOrNot) {
321 // To make the test signal most obvious, we choose a special sample rate.
322 const int kSampleRateHz = 1000;
323
324 const RepetitionDetector::Pattern kRepetitionPatterns[] = {
325 // id, look_back_ms, min_length_ms
326 {0, 3, 3},
327 };
328 const float kTestSignal_1[] = {0, 0, 0, 0, 0, 0};
329 const float kTestSignal_2[] = {0, 1, 2, 0, 1, 2};
330 const ExpectedCount kExpectedCounts_1[] = {
331 // Full zeros won't count.
332 {0, 0},
333 };
334 const ExpectedCount kExpectedCounts_2[] = {
335 // Partial zero will count.
336 {0, 1},
337 };
338
339 ResetRepetitionPattern(kRepetitionPatterns, arraysize(kRepetitionPatterns));
340 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
341 arraysize(kTestSignal_1), kSampleRateHz);
342 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
343 arraysize(kTestSignal_2), kSampleRateHz);
344 ResetCounters();
345 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
346 arraysize(kTestSignal_1), kSampleRateHz);
347 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
348 arraysize(kTestSignal_2), kSampleRateHz);
349 }
350
351 // Previous tests use short signal to test the detection algorithm, this one
352 // tests the built-in pattern in RepetitionDetector.
353 TEST_F(RepetitionDetectorTest, BuiltInPattern) {
354 const int kSampleRateHz = 44100;
355 // Let the signal be "*(4ms)-A(13ms)-*(100ms)-A", where * denotes random
356 // samples.
357 const size_t kPreSamples = kSampleRateHz * 4 / 1000;
358 const size_t kRepSamples = kSampleRateHz * 13 / 1000;
359 const size_t kSkipSamples = kSampleRateHz * 100 / 1000;
360 const size_t kSamples = kPreSamples + kRepSamples * 2 + kSkipSamples;
361 float test_signal[kSamples];
362 Random random(0x12345678);
363 size_t idx = 0;
364 for (; idx < kPreSamples + kRepSamples + kSkipSamples; ++idx) {
365 test_signal[idx] = random.Rand();
366 }
367 for (; idx < kSamples; ++idx) {
368 test_signal[idx] = test_signal[idx - kSkipSamples];
369 }
370 const ExpectedCount kExpectedCounts[] = {
371 // Partial zero will count.
372 {0, 0}, // 10 ms look back
373 {1, 1} // 100 ms look back
374 };
375 Verify(kExpectedCounts, arraysize(kExpectedCounts), test_signal, kSamples,
376 kSampleRateHz);
377 }
378
379 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/repetition_detector.cc ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698