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