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

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

Powered by Google App Engine
This is Rietveld 408576698