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

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: pure virtual function -> base::Callback 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/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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698