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

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: use std::sort and unique Created 5 years, 1 month 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 // Sample rate used in many tests. We choose a special sample rate in order to
20 // make the test signal obvious.
21 const int kSampleRateHz = 1000;
22
23 }
24
25 class AudioRepetitionDetectorForTest : public AudioRepetitionDetector {
26 public:
27 AudioRepetitionDetectorForTest(int min_length_ms, size_t max_frames,
28 const int* look_back_times,
29 size_t num_look_back)
30 : AudioRepetitionDetector(
31 min_length_ms, max_frames,
32 std::vector<int>(look_back_times, look_back_times + num_look_back),
33 base::Bind(&AudioRepetitionDetectorForTest::OnRepetitionDetected,
34 base::Unretained(this))) {
35 }
36
37 int GetCount(int look_back_ms) {
tommi (sloooow) - chröme 2015/10/30 15:33:01 nit: const?
minyue 2015/10/30 20:17:05 true!
38 auto it = counters_.find(look_back_ms);
39 if (it == counters_.end())
tommi (sloooow) - chröme 2015/10/30 15:33:01 nit: could shorten to return it == counters_.end()
minyue 2015/10/30 20:17:05 yes of course
40 return 0;
41 return it->second;
42 }
43
44 void ResetCounters() {
45 counters_.clear();
46 }
47
48 private:
49 void OnRepetitionDetected(int look_back_ms) {
50 auto it = counters_.find(look_back_ms);
51 if (it == counters_.end()) {
52 counters_.insert(std::pair<int, size_t>(look_back_ms, 1));
53 return;
54 }
55 it->second++;
56 }
57
58 std::map<int, size_t> counters_;
59 };
60
61 class AudioRepetitionDetectorTest : public ::testing::Test {
62 public:
63 AudioRepetitionDetectorTest()
64 : detector_(nullptr) {
65 }
66
67 protected:
68 struct ExpectedCount {
69 int look_back_ms;
70 int count;
71 };
72
73 // Verify if the counts on the repetition patterns match expectation after
74 // injecting a signal. No reset on the counters
75 void Verify(const ExpectedCount* expected_counts, size_t num_patterns,
76 const float* tester, size_t num_frames,
77 int sample_rate_hz, size_t channels = 1) {
78 detector_->Detect(tester, num_frames, channels, sample_rate_hz);
79 for (size_t idx = 0; idx < num_patterns; ++idx) {
80 const int look_back_ms = expected_counts[idx].look_back_ms;
81 EXPECT_EQ(expected_counts[idx].count, detector_->GetCount(look_back_ms))
82 << "Repetition with look back "
83 << look_back_ms
84 << " ms counted wrong.";
85 }
86 }
87
88 void VerifyStereo(const ExpectedCount* expected_counts, size_t num_patterns,
89 const float* tester, size_t num_frames,
90 int sample_rate_hz) {
91 const size_t kNumChannels = 2;
tommi (sloooow) - chröme 2015/10/30 15:33:01 nit: static const size_t kNumChannels = 2;
minyue 2015/10/30 20:17:05 Ok. I did not really use static on const in these
92
93 // Get memory to store interleaved stereo.
94 scoped_ptr<float[]> tester_stereo(
95 new float[num_frames * kNumChannels]);
96
97 for (size_t idx = 0; idx < num_frames; ++idx, ++tester) {
98 for (size_t channel = 0; channel < kNumChannels; ++channel)
99 tester_stereo[idx * kNumChannels + channel] = *tester;
100 }
101
102 Verify(expected_counts, num_patterns, tester_stereo.get(),
103 num_frames, sample_rate_hz, kNumChannels);
104 }
105
106 void SetDetector(int min_length_ms, size_t max_frames,
107 const int* look_back_times, size_t num_look_back) {
108 detector_.reset(new AudioRepetitionDetectorForTest(min_length_ms,
109 max_frames,
110 look_back_times,
111 num_look_back));
112 }
113
114 void ResetCounters() {
115 detector_->ResetCounters();
116 }
117
118 private:
119 scoped_ptr<AudioRepetitionDetectorForTest> detector_;
120 };
121
122 TEST_F(AudioRepetitionDetectorTest, Basic) {
123 // Check that one look back time will registered only once.
124 const int kLookbackTimes[] = {3, 3, 3, 3};
125
126 const float kTestSignal[] = {1, 2, 3, 1, 2, 3};
127 const ExpectedCount kExpectedCounts_1[] = {
128 {3, 1}
129 };
130 const ExpectedCount kExpectedCounts_2[] = {
131 {3, 1}
132 };
133
134
135 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
136 arraysize(kLookbackTimes));
137 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
138 arraysize(kTestSignal), kSampleRateHz);
139 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
140 arraysize(kTestSignal), kSampleRateHz);
141 ResetCounters();
142
143 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
144 arraysize(kTestSignal), kSampleRateHz);
145 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
146 arraysize(kTestSignal), kSampleRateHz);
147 }
148
149 TEST_F(AudioRepetitionDetectorTest, StereoOutOfSync) {
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 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 const int kLookbackTimes[] = {3, 4};
214 const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4};
215 const ExpectedCount kExpectedCounts[] = {
216 // 1,2,3 belongs to both patterns.
217 {3, 1},
218 {4, 1}
219 };
220
221 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
222 arraysize(kLookbackTimes));
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 int kLookbackTimes[] = {3, 4};
235 const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4};
236 const ExpectedCount kExpectedCounts[] = {
237 // 1,2,3 belongs to both patterns.
238 {3, 1},
239 {4, 1}
240 };
241
242 // length of kTestSignal is 11 but I set maximum frames to be 2. The detection
243 // should still work.
244 SetDetector(kDefaultMinLengthMs, 2, kLookbackTimes,arraysize(kLookbackTimes));
245 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
246 arraysize(kTestSignal), kSampleRateHz);
247 ResetCounters();
248 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
249 arraysize(kTestSignal), kSampleRateHz);
250 }
251
252 TEST_F(AudioRepetitionDetectorTest, NestedPatterns) {
253 const int kLookbackTimes[] = {6, 3};
254 const float kTestSignal[] = {1, 2, 3, 1, 2, 3};
255 const ExpectedCount kExpectedCounts_1[] = {
256 {3, 1},
257 {6, 0}
258 };
259 const ExpectedCount kExpectedCounts_2[] = {
260 {3, 1},
261 {6, 1}
262 };
263
264 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
265 arraysize(kLookbackTimes));
266 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
267 arraysize(kTestSignal), kSampleRateHz);
268 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
269 arraysize(kTestSignal), kSampleRateHz);
270 ResetCounters();
271 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
272 arraysize(kTestSignal), kSampleRateHz);
273 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
274 arraysize(kTestSignal), kSampleRateHz);
275 }
276
277 TEST_F(AudioRepetitionDetectorTest, NotFullLengthPattern) {
278 const int kLookbackTimes[] = {4};
279 const float kTestSignal[] = {1, 2, 3, -1, 1, 2, 3, -2};
280 const ExpectedCount kExpectedCounts[] = {
281 {4, 1},
282 };
283
284 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
285 arraysize(kLookbackTimes));
286 Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
287 arraysize(kTestSignal), kSampleRateHz);
288 ResetCounters();
289 VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
290 arraysize(kTestSignal), kSampleRateHz);
291 }
292
293 TEST_F(AudioRepetitionDetectorTest, ZerosCountOrNot) {
294 const int kLookbackTimes[] = {3};
295 const float kTestSignal_1[] = {0, 0, 0, 0, 0, 0};
296 const float kTestSignal_2[] = {0, 1, 2, 0, 1, 2};
297 const ExpectedCount kExpectedCounts_1[] = {
298 // Full zeros won't count.
299 {3, 0},
300 };
301 const ExpectedCount kExpectedCounts_2[] = {
302 // Partial zero will count.
303 {3, 1},
304 };
305
306 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
307 arraysize(kLookbackTimes));
308 Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
309 arraysize(kTestSignal_1), kSampleRateHz);
310 Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
311 arraysize(kTestSignal_2), kSampleRateHz);
312 ResetCounters();
313 VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
314 arraysize(kTestSignal_1), kSampleRateHz);
315 VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
316 arraysize(kTestSignal_2), kSampleRateHz);
317 }
318
319 // Previous tests use short signal to test the detection algorithm, this one
320 // tests a normal frame size
321 TEST_F(AudioRepetitionDetectorTest, NormalSignal) {
322 const int kNormalSampleRateHz = 44100;
323 // Let the signal be "*(4ms)-A(13ms)-*(100ms)-A", where * denotes random
324 // samples.
325 const size_t kPreSamples = kNormalSampleRateHz * 4 / 1000;
326 const size_t kRepSamples = kNormalSampleRateHz * 13 / 1000;
327 const size_t kSkipSamples = kNormalSampleRateHz * 100 / 1000;
328 const size_t kSamples = kPreSamples + kRepSamples * 2 + kSkipSamples;
329
330 const int kLookbackTimes[] = {80, 90, 100, 110, 120};
331
332 float test_signal[kSamples];
333 size_t idx = 0;
334 for (; idx < kPreSamples + kRepSamples + kSkipSamples; ++idx)
335 test_signal[idx] = static_cast<float>(base::RandDouble());
336
337 for (; idx < kSamples; ++idx)
338 test_signal[idx] = test_signal[idx - kSkipSamples];
339
340 ExpectedCount expect_counts[arraysize(kLookbackTimes)];
341 for (size_t i = 0; i < arraysize(kLookbackTimes); ++i) {
342 expect_counts[i].look_back_ms = kLookbackTimes[i];
343 expect_counts[i].count = 0;
344 }
345
346 // We only expect a repetition with 100 ms look back time.
347 expect_counts[2].count = 1;
348
349 SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
350 arraysize(kLookbackTimes));
351 Verify(expect_counts, arraysize(expect_counts), test_signal, kSamples,
352 kNormalSampleRateHz);
353 }
354
355 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698