OLD | NEW |
---|---|
(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 | |
OLD | NEW |