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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/audio_repetition_detector_unittest.cc
diff --git a/content/renderer/media/audio_repetition_detector_unittest.cc b/content/renderer/media/audio_repetition_detector_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cdb49b2f1a4143b34c4712434c724359b24c9e53
--- /dev/null
+++ b/content/renderer/media/audio_repetition_detector_unittest.cc
@@ -0,0 +1,353 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/rand_util.h"
+#include "content/renderer/media/audio_repetition_detector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+const int kDefaultMinLengthMs = 1;
+const size_t kDefaultMaxFrames = 480; // 10 ms * 48 kHz
+
+// Sample rate used in many tests. We choose a special sample rate in order to
+// make the test signal obvious.
+const int kSampleRateHz = 1000;
+
+}
+
+class AudioRepetitionDetectorForTest : public AudioRepetitionDetector {
+ public:
+ AudioRepetitionDetectorForTest(int min_length_ms, size_t max_frames,
+ const int* look_back_times,
+ size_t num_look_back)
+ : AudioRepetitionDetector(
+ min_length_ms, max_frames,
+ std::vector<int>(look_back_times, look_back_times + num_look_back),
+ base::Bind(&AudioRepetitionDetectorForTest::OnRepetitionDetected,
+ base::Unretained(this))) {
+ }
+
+ int GetCount(int look_back_ms) const {
+ auto it = counters_.find(look_back_ms);
+ return it == counters_.end() ? 0 : it->second;
+ }
+
+ void ResetCounters() {
+ counters_.clear();
+ }
+
+ private:
+ void OnRepetitionDetected(int look_back_ms) {
+ auto it = counters_.find(look_back_ms);
+ if (it == counters_.end()) {
+ counters_.insert(std::pair<int, size_t>(look_back_ms, 1));
+ return;
+ }
+ it->second++;
+ }
+
+ std::map<int, size_t> counters_;
+};
+
+class AudioRepetitionDetectorTest : public ::testing::Test {
+ public:
+ AudioRepetitionDetectorTest()
+ : detector_(nullptr) {
+ }
+
+ protected:
+ struct ExpectedCount {
+ int look_back_ms;
+ int count;
+ };
+
+ // Verify if the counts on the repetition patterns match expectation after
+ // injecting a signal. No reset on the counters
+ void Verify(const ExpectedCount* expected_counts, size_t num_patterns,
+ const float* tester, size_t num_frames,
+ int sample_rate_hz, size_t channels = 1) {
+ detector_->Detect(tester, num_frames, channels, sample_rate_hz);
+ for (size_t idx = 0; idx < num_patterns; ++idx) {
+ const int look_back_ms = expected_counts[idx].look_back_ms;
+ EXPECT_EQ(expected_counts[idx].count, detector_->GetCount(look_back_ms))
+ << "Repetition with look back "
+ << look_back_ms
+ << " ms counted wrong.";
+ }
+ }
+
+ void VerifyStereo(const ExpectedCount* expected_counts, size_t num_patterns,
+ const float* tester, size_t num_frames,
+ int sample_rate_hz) {
+ static const size_t kNumChannels = 2;
+
+ // Get memory to store interleaved stereo.
+ scoped_ptr<float[]> tester_stereo(
+ new float[num_frames * kNumChannels]);
+
+ for (size_t idx = 0; idx < num_frames; ++idx, ++tester) {
+ for (size_t channel = 0; channel < kNumChannels; ++channel)
+ tester_stereo[idx * kNumChannels + channel] = *tester;
+ }
+
+ Verify(expected_counts, num_patterns, tester_stereo.get(),
+ num_frames, sample_rate_hz, kNumChannels);
+ }
+
+ void SetDetector(int min_length_ms, size_t max_frames,
+ const int* look_back_times, size_t num_look_back) {
+ detector_.reset(new AudioRepetitionDetectorForTest(min_length_ms,
+ max_frames,
+ look_back_times,
+ num_look_back));
+ }
+
+ void ResetCounters() {
+ detector_->ResetCounters();
+ }
+
+ private:
+ scoped_ptr<AudioRepetitionDetectorForTest> detector_;
+};
+
+TEST_F(AudioRepetitionDetectorTest, Basic) {
+ // Check that one look back time will registered only once.
+ const int kLookbackTimes[] = {3, 3, 3, 3};
+
+ const float kTestSignal[] = {1, 2, 3, 1, 2, 3};
+ const ExpectedCount kExpectedCounts_1[] = {
+ {3, 1}
+ };
+ const ExpectedCount kExpectedCounts_2[] = {
+ {3, 1}
+ };
+
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ ResetCounters();
+
+ VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, StereoOutOfSync) {
+ const int kLookbackTimes[] = {3};
+ const float kTestSignal[] = {
+ 1, 1,
+ 2, 2,
+ 3, 3,
+ 1, 1,
+ 2, 2,
+ 3, 1};
+ const ExpectedCount kExpectedCounts[] = {
+ {3, 0}
+ };
+
+ // By default, any repetition longer than 1 ms (1 sample at 1000 Hz) will be
+ // counted as repetition. This test needs to make it longer.
+ SetDetector(3, kDefaultMaxFrames, kLookbackTimes, arraysize(kLookbackTimes));
+ Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal) / 2, kSampleRateHz, 2);
+}
+
+TEST_F(AudioRepetitionDetectorTest, IncompletePattern) {
+ const int kLookbackTimes[] = {3};
+ const float kTestSignal[] = {1, 2, 1, 2, 3, 1, 2, 3};
+ const ExpectedCount kExpectedCounts[] = {
+ {3, 1},
+ };
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, PatternLongerThanFrame) {
+ // To make the test signal most obvious, we choose a special sample rate.
+ const int kSampleRateHz = 1000;
+
+ const int kLookbackTimes[] = {6};
+ const float kTestSignal_1[] = {1, 2, 3, 4, 5};
+ const float kTestSignal_2[] = {6, 1, 2, 3, 4, 5, 6};
+ const ExpectedCount kExpectedCounts_1[] = {
+ {6, 0},
+ };
+ const ExpectedCount kExpectedCounts_2[] = {
+ {6, 1},
+ };
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
+ arraysize(kTestSignal_1), kSampleRateHz);
+ Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
+ arraysize(kTestSignal_2), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
+ arraysize(kTestSignal_1), kSampleRateHz);
+ VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
+ arraysize(kTestSignal_2), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, TwoPatterns) {
+ const int kLookbackTimes[] = {3, 4};
+ const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4};
+ const ExpectedCount kExpectedCounts[] = {
+ // 1,2,3 belongs to both patterns.
+ {3, 1},
+ {4, 1}
+ };
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, MaxFramesShorterThanInput) {
+ // To make the test signal most obvious, we choose a special sample rate.
+ const int kSampleRateHz = 1000;
+
+ const int kLookbackTimes[] = {3, 4};
+ const float kTestSignal[] = {1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4};
+ const ExpectedCount kExpectedCounts[] = {
+ // 1,2,3 belongs to both patterns.
+ {3, 1},
+ {4, 1}
+ };
+
+ // length of kTestSignal is 11 but I set maximum frames to be 2. The detection
+ // should still work.
+ SetDetector(kDefaultMinLengthMs, 2, kLookbackTimes,arraysize(kLookbackTimes));
+ Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, NestedPatterns) {
+ const int kLookbackTimes[] = {6, 3};
+ const float kTestSignal[] = {1, 2, 3, 1, 2, 3};
+ const ExpectedCount kExpectedCounts_1[] = {
+ {3, 1},
+ {6, 0}
+ };
+ const ExpectedCount kExpectedCounts_2[] = {
+ {3, 1},
+ {6, 1}
+ };
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, NotFullLengthPattern) {
+ const int kLookbackTimes[] = {4};
+ const float kTestSignal[] = {1, 2, 3, -1, 1, 2, 3, -2};
+ const ExpectedCount kExpectedCounts[] = {
+ {4, 1},
+ };
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts, arraysize(kExpectedCounts), kTestSignal,
+ arraysize(kTestSignal), kSampleRateHz);
+}
+
+TEST_F(AudioRepetitionDetectorTest, ZerosCountOrNot) {
+ const int kLookbackTimes[] = {3};
+ const float kTestSignal_1[] = {0, 0, 0, 0, 0, 0};
+ const float kTestSignal_2[] = {0, 1, 2, 0, 1, 2};
+ const ExpectedCount kExpectedCounts_1[] = {
+ // Full zeros won't count.
+ {3, 0},
+ };
+ const ExpectedCount kExpectedCounts_2[] = {
+ // Partial zero will count.
+ {3, 1},
+ };
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
+ arraysize(kTestSignal_1), kSampleRateHz);
+ Verify(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
+ arraysize(kTestSignal_2), kSampleRateHz);
+ ResetCounters();
+ VerifyStereo(kExpectedCounts_1, arraysize(kExpectedCounts_1), kTestSignal_1,
+ arraysize(kTestSignal_1), kSampleRateHz);
+ VerifyStereo(kExpectedCounts_2, arraysize(kExpectedCounts_2), kTestSignal_2,
+ arraysize(kTestSignal_2), kSampleRateHz);
+}
+
+// Previous tests use short signal to test the detection algorithm, this one
+// tests a normal frame size
+TEST_F(AudioRepetitionDetectorTest, NormalSignal) {
+ const int kNormalSampleRateHz = 44100;
+ // Let the signal be "*(4ms)-A(13ms)-*(100ms)-A", where * denotes random
+ // samples.
+ const size_t kPreSamples = kNormalSampleRateHz * 4 / 1000;
+ const size_t kRepSamples = kNormalSampleRateHz * 13 / 1000;
+ const size_t kSkipSamples = kNormalSampleRateHz * 100 / 1000;
+ const size_t kSamples = kPreSamples + kRepSamples * 2 + kSkipSamples;
+
+ const int kLookbackTimes[] = {80, 90, 100, 110, 120};
+
+ float test_signal[kSamples];
+ size_t idx = 0;
+ for (; idx < kPreSamples + kRepSamples + kSkipSamples; ++idx)
+ test_signal[idx] = static_cast<float>(base::RandDouble());
+
+ for (; idx < kSamples; ++idx)
+ test_signal[idx] = test_signal[idx - kSkipSamples];
+
+ ExpectedCount expect_counts[arraysize(kLookbackTimes)];
+ for (size_t i = 0; i < arraysize(kLookbackTimes); ++i) {
+ expect_counts[i].look_back_ms = kLookbackTimes[i];
+ expect_counts[i].count = 0;
+ }
+
+ // We only expect a repetition with 100 ms look back time.
+ expect_counts[2].count = 1;
+
+ SetDetector(kDefaultMinLengthMs, kDefaultMaxFrames, kLookbackTimes,
+ arraysize(kLookbackTimes));
+ Verify(expect_counts, arraysize(expect_counts), test_signal, kSamples,
+ kNormalSampleRateHz);
+}
+
+} // namespace content
« 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