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

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

Powered by Google App Engine
This is Rietveld 408576698