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

Side by Side Diff: content/renderer/media/audio_repetition_detector_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698