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

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

Powered by Google App Engine
This is Rietveld 408576698