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/bind.h" | |
8 #include "base/macros.h" | |
9 #include "base/rand_util.h" | |
10 #include "content/renderer/media/audio_repetition_detector.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 namespace content { | |
14 | |
15 namespace { | |
16 const int kDefaultMinLengthMs = 1; | |
17 const size_t kDefaultMaxFrames = 480; // 10 ms * 48 kHz | |
18 } | |
19 | |
20 class AudioRepetitionDetectorForTest : public AudioRepetitionDetector { | |
21 public: | |
22 AudioRepetitionDetectorForTest(int min_length_ms, size_t max_frames, | |
23 const int* look_back_times, | |
24 size_t num_look_back) | |
25 : AudioRepetitionDetector( | |
26 min_length_ms, max_frames, look_back_times, num_look_back, | |
27 base::Bind(&AudioRepetitionDetectorForTest::ReportRepetition, | |
28 base::Unretained(this))) { | |
29 } | |
30 | |
31 int GetCount(int look_back_ms) { | |
32 auto it = counters_.find(look_back_ms); | |
33 if (it == counters_.end()) | |
34 return 0; | |
35 return it->second; | |
36 } | |
37 | |
38 void ResetCounters() { | |
39 counters_.clear(); | |
40 } | |
41 | |
42 private: | |
43 void ReportRepetition(int look_back_ms) { | |
Henrik Grunell
2015/10/23 13:49:02
"RepetitionDetected" is a clearer name.
minyue
2015/10/26 10:41:46
Yes, but may be OnRepetitionDetected
Henrik Grunell
2015/10/28 14:09:23
Acknowledged.
| |
44 auto it = counters_.find(look_back_ms); | |
45 if (it == counters_.end()) { | |
46 counters_.insert(std::pair<int, size_t>(look_back_ms, 1)); | |
47 return; | |
48 } | |
49 it->second++; | |
50 } | |
51 | |
52 std::map<int, size_t> counters_; | |
53 }; | |
54 | |
55 class AudioRepetitionDetectorTest : public ::testing::Test { | |
56 public: | |
57 AudioRepetitionDetectorTest() | |
58 : detector_(nullptr) { | |
59 } | |
60 | |
61 protected: | |
62 struct ExpectedCount { | |
63 int look_back_ms; | |
64 int count; | |
65 }; | |
66 | |
67 // Verify if the counts on the repetition patterns match expectation after | |
68 // injecting a signal. No reset on the counters | |
69 void Verify(const ExpectedCount* expected_counts, size_t num_patterns, | |
70 const float* tester, size_t num_frames, | |
71 int sample_rate_hz, size_t channels = 1) { | |
72 detector_->Detect(tester, num_frames, channels, sample_rate_hz); | |
73 for (size_t idx = 0; idx < num_patterns; ++idx) { | |
74 const int look_back_ms = expected_counts[idx].look_back_ms; | |
75 EXPECT_EQ(expected_counts[idx].count, detector_->GetCount(look_back_ms)) | |
76 << "Repetition with look back " | |
77 << look_back_ms | |
78 << " ms counted wrong."; | |
79 } | |
80 } | |
81 | |
82 void VerifyStereo(const ExpectedCount* expected_counts, size_t num_patterns, | |
83 const float* tester, size_t num_frames, | |
84 int sample_rate_hz) { | |
85 const size_t kNumChannels = 2; | |
86 | |
87 // Get memory to store interleaved stereo. | |
88 scoped_ptr<float[]> tester_stereo( | |
89 new float[num_frames * kNumChannels]); | |
90 | |
91 for (size_t idx = 0; idx < num_frames; ++idx, ++tester) { | |
92 for (size_t channel = 0; channel < kNumChannels; ++channel) | |
93 tester_stereo[idx * kNumChannels + channel] = *tester; | |
94 } | |
95 | |
96 Verify(expected_counts, num_patterns, tester_stereo.get(), | |
97 num_frames, sample_rate_hz, kNumChannels); | |
98 } | |
99 | |
100 void SetDetector(int min_length_ms, size_t max_frames, | |
101 const int* look_back_times, size_t num_look_back) { | |
102 detector_.reset(new AudioRepetitionDetectorForTest(min_length_ms, | |
103 max_frames, | |
104 look_back_times, | |
105 num_look_back)); | |
106 } | |
107 | |
108 void ResetCounters() { | |
109 detector_->ResetCounters(); | |
110 } | |
111 | |
112 private: | |
113 scoped_ptr<AudioRepetitionDetectorForTest> detector_; | |
114 }; | |
115 | |
116 TEST_F(AudioRepetitionDetectorTest, Basic) { | |
117 // To make the test signal most obvious, we choose a special sample rate. | |
Henrik Grunell
2015/10/23 13:49:02
This is duplicated a lot, make it global. Is there
minyue
2015/10/26 10:41:46
I broke this out and did not find more
Henrik Grunell
2015/10/28 14:09:23
Acknowledged.
| |
118 const int kSampleRateHz = 1000; | |
119 | |
120 // Check that one look back time will registered only once. | |
121 const int kLookbackTimes[] = {3, 3, 3, 3}; | |
122 | |
123 const float kTestSignal[] = {1, 2, 3, 1, 2, 3}; | |
124 const ExpectedCount kExpectedCounts_1[] = { | |
125 {3, 1} | |
126 }; | |
127 const ExpectedCount kExpectedCounts_2[] = { | |
128 {3, 1} | |
129 }; | |
130 | |
131 | |
132 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
133 arraysize(kLookbackTimes)); | |
134 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal, | |
135 arraysize(kTestSignal), kSampleRateHz); | |
136 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal, | |
137 arraysize(kTestSignal), kSampleRateHz); | |
138 ResetCounters(); | |
139 | |
140 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal, | |
141 arraysize(kTestSignal), kSampleRateHz); | |
142 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal, | |
143 arraysize(kTestSignal), kSampleRateHz); | |
144 } | |
145 | |
146 TEST_F(AudioRepetitionDetectorTest, StereoOutOfSync) { | |
147 // To make the test signal most obvious, we choose a special sample rate. | |
148 const int kSampleRateHz = 1000; | |
149 | |
150 const int kLookbackTimes[] = {3}; | |
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 {3, 0} | |
160 }; | |
161 | |
162 // By default, any repetition longer than 1 ms (1 sample at 1000 Hz) will be | |
163 // counted as repetition. This test needs to make it longer. | |
164 SetDetector(3, kDefaultMaxFrames, kLookbackTimes, arraysize(kLookbackTimes)); | |
165 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
166 arraysize(kTestSignal) / 2, kSampleRateHz, 2); | |
167 } | |
168 | |
169 TEST_F(AudioRepetitionDetectorTest, IncompletePattern) { | |
170 // To make the test signal most obvious, we choose a special sample rate. | |
171 const int kSampleRateHz = 1000; | |
172 | |
173 const int kLookbackTimes[] = {3}; | |
174 const float kTestSignal[] = {1, 2, 1, 2, 3, 1, 2, 3}; | |
175 const ExpectedCount kExpectedCounts[] = { | |
176 {3, 1}, | |
177 }; | |
178 | |
179 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
180 arraysize(kLookbackTimes)); | |
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(AudioRepetitionDetectorTest, PatternLongerThanFrame) { | |
189 // To make the test signal most obvious, we choose a special sample rate. | |
190 const int kSampleRateHz = 1000; | |
191 | |
192 const int kLookbackTimes[] = {6}; | |
193 const float kTestSignal_1[] = {1, 2, 3, 4, 5}; | |
194 const float kTestSignal_2[] = {6, 1, 2, 3, 4, 5, 6}; | |
195 const ExpectedCount kExpectedCounts_1[] = { | |
196 {6, 0}, | |
197 }; | |
198 const ExpectedCount kExpectedCounts_2[] = { | |
199 {6, 1}, | |
200 }; | |
201 | |
202 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
203 arraysize(kLookbackTimes)); | |
204 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1, | |
205 arraysize(kTestSignal_1), kSampleRateHz); | |
206 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2, | |
207 arraysize(kTestSignal_2), kSampleRateHz); | |
208 ResetCounters(); | |
209 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1, | |
210 arraysize(kTestSignal_1), kSampleRateHz); | |
211 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2, | |
212 arraysize(kTestSignal_2), kSampleRateHz); | |
213 } | |
214 | |
215 TEST_F(AudioRepetitionDetectorTest, TwoPatterns) { | |
216 // To make the test signal most obvious, we choose a special sample rate. | |
217 const int kSampleRateHz = 1000; | |
218 | |
219 const int kLookbackTimes[] = {3, 4}; | |
220 const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4}; | |
221 const ExpectedCount kExpectedCounts[] = { | |
222 // 1,2,3 belongs to both patterns. | |
223 {3, 1}, | |
224 {4, 1} | |
225 }; | |
226 | |
227 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
228 arraysize(kLookbackTimes)); | |
229 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
230 arraysize(kTestSignal), kSampleRateHz); | |
231 ResetCounters(); | |
232 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
233 arraysize(kTestSignal), kSampleRateHz); | |
234 } | |
235 | |
236 TEST_F(AudioRepetitionDetectorTest, MaxFramesShorterThanInput) { | |
237 // To make the test signal most obvious, we choose a special sample rate. | |
238 const int kSampleRateHz = 1000; | |
239 | |
240 const int kLookbackTimes[] = {3, 4}; | |
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 {3, 1}, | |
245 {4, 1} | |
246 }; | |
247 | |
248 // length of kTestSignal is 11 but I set maximum frames to be 2. The detection | |
249 // should still work. | |
250 SetDetector(kDefaultMinLengthMs, 2, kLookbackTimes,arraysize(kLookbackTimes)); | |
251 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
252 arraysize(kTestSignal), kSampleRateHz); | |
253 ResetCounters(); | |
254 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
255 arraysize(kTestSignal), kSampleRateHz); | |
256 } | |
257 | |
258 TEST_F(AudioRepetitionDetectorTest, NestedPatterns) { | |
259 // To make the test signal most obvious, we choose a special sample rate. | |
260 const int kSampleRateHz = 1000; | |
261 | |
262 const int kLookbackTimes[] = {6, 3}; | |
263 const float kTestSignal[] = {1, 2, 3, 1, 2, 3}; | |
264 const ExpectedCount kExpectedCounts_1[] = { | |
265 {3, 1}, | |
266 {6, 0} | |
267 }; | |
268 const ExpectedCount kExpectedCounts_2[] = { | |
269 {3, 1}, | |
270 {6, 1} | |
271 }; | |
272 | |
273 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
274 arraysize(kLookbackTimes)); | |
275 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal, | |
276 arraysize(kTestSignal), kSampleRateHz); | |
277 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal, | |
278 arraysize(kTestSignal), kSampleRateHz); | |
279 ResetCounters(); | |
280 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal, | |
281 arraysize(kTestSignal), kSampleRateHz); | |
282 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal, | |
283 arraysize(kTestSignal), kSampleRateHz); | |
284 } | |
285 | |
286 TEST_F(AudioRepetitionDetectorTest, NotFullLengthPattern) { | |
287 // To make the test signal most obvious, we choose a special sample rate. | |
288 const int kSampleRateHz = 1000; | |
289 | |
290 const int kLookbackTimes[] = {4}; | |
291 const float kTestSignal[] = {1, 2, 3, -1, 1, 2, 3, -2}; | |
292 const ExpectedCount kExpectedCounts[] = { | |
293 {4, 1}, | |
294 }; | |
295 | |
296 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
297 arraysize(kLookbackTimes)); | |
298 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
299 arraysize(kTestSignal), kSampleRateHz); | |
300 ResetCounters(); | |
301 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal, | |
302 arraysize(kTestSignal), kSampleRateHz); | |
303 } | |
304 | |
305 TEST_F(AudioRepetitionDetectorTest, ZerosCountOrNot) { | |
306 // To make the test signal most obvious, we choose a special sample rate. | |
307 const int kSampleRateHz = 1000; | |
308 | |
309 const int kLookbackTimes[] = {3}; | |
310 const float kTestSignal_1[] = {0, 0, 0, 0, 0, 0}; | |
311 const float kTestSignal_2[] = {0, 1, 2, 0, 1, 2}; | |
312 const ExpectedCount kExpectedCounts_1[] = { | |
313 // Full zeros won't count. | |
314 {3, 0}, | |
315 }; | |
316 const ExpectedCount kExpectedCounts_2[] = { | |
317 // Partial zero will count. | |
318 {3, 1}, | |
319 }; | |
320 | |
321 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
322 arraysize(kLookbackTimes)); | |
323 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1, | |
324 arraysize(kTestSignal_1), kSampleRateHz); | |
325 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2, | |
326 arraysize(kTestSignal_2), kSampleRateHz); | |
327 ResetCounters(); | |
328 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1, | |
329 arraysize(kTestSignal_1), kSampleRateHz); | |
330 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2, | |
331 arraysize(kTestSignal_2), kSampleRateHz); | |
332 } | |
333 | |
334 // Previous tests use short signal to test the detection algorithm, this one | |
335 // tests a normal frame size | |
336 TEST_F(AudioRepetitionDetectorTest, NormalSignal) { | |
337 const int kSampleRateHz = 44100; | |
338 // Let the signal be "*(4ms)-A(13ms)-*(100ms)-A", where * denotes random | |
339 // samples. | |
340 const size_t kPreSamples = kSampleRateHz * 4 / 1000; | |
341 const size_t kRepSamples = kSampleRateHz * 13 / 1000; | |
342 const size_t kSkipSamples = kSampleRateHz * 100 / 1000; | |
343 const size_t kSamples = kPreSamples + kRepSamples * 2 + kSkipSamples; | |
344 | |
345 const int kLookbackTimes[] = {80, 90, 100, 110, 120}; | |
346 | |
347 float test_signal[kSamples]; | |
348 size_t idx = 0; | |
349 for (; idx < kPreSamples + kRepSamples + kSkipSamples; ++idx) | |
350 test_signal[idx] = static_cast<float>(base::RandDouble()); | |
351 | |
352 for (; idx < kSamples; ++idx) | |
353 test_signal[idx] = test_signal[idx - kSkipSamples]; | |
354 | |
355 ExpectedCount expect_counts[arraysize(kLookbackTimes)]; | |
356 for (size_t i = 0; i < arraysize(kLookbackTimes); ++i) { | |
357 expect_counts[i].look_back_ms = kLookbackTimes[i]; | |
358 expect_counts[i].count = 0; | |
359 } | |
360 | |
361 // We only expect a repetition with 100 ms look back time. | |
362 expect_counts[2].count = 1; | |
363 | |
364 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes, | |
365 arraysize(kLookbackTimes)); | |
366 Verify(expect_counts, arraysize(expect_counts), test_signal, kSamples, | |
367 kSampleRateHz); | |
368 } | |
369 | |
370 } // namespace content | |
OLD | NEW |