Index: webrtc/modules/audio_processing/repetition_detector_unittest.cc |
diff --git a/webrtc/modules/audio_processing/repetition_detector_unittest.cc b/webrtc/modules/audio_processing/repetition_detector_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..70d53614d40c646160e815b58d18cb2b1fa00196 |
--- /dev/null |
+++ b/webrtc/modules/audio_processing/repetition_detector_unittest.cc |
@@ -0,0 +1,294 @@ |
+/* |
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include <map> |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webrtc/modules/audio_processing/repetition_detector.h" |
+ |
+namespace webrtc { |
+ |
+class RepetitionDetectorTest : public RepetitionDetector, |
+ public ::testing::Test { |
+ public: |
+ struct ExpectedCount { |
+ int id_; |
+ int count_; |
+ }; |
+ |
+ protected: |
+ void ResetRepetitionPattern(const Pattern* patterns, int num_patterns) { |
+ ClearRepititionPatterns(); |
+ RegisterRepititionPatterns(patterns, num_patterns); |
+ } |
+ |
+ // 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, int num_patterns, |
+ const int16_t* tester, int samples_per_channel, |
+ int channels = 1) { |
+ Detect(tester, samples_per_channel, channels); |
+ int id; |
+ for (int idx = 0; idx < num_patterns; idx++) { |
+ id = expected_counts[idx].id_; |
+ EXPECT_EQ(expected_counts[idx].count_, GetCount(id)) << |
+ "Repetition #" << id << " counted wrong."; |
+ } |
+ } |
+ |
+ void VerifyStereo(const ExpectedCount* expected_counts, int num_patterns, |
+ const int16_t* tester, int samples_per_channel) { |
+ int16_t* tester_stereo = new int16_t[samples_per_channel * 2]; |
+ for (int idx = 0; idx < samples_per_channel; idx++) { |
+ tester_stereo[idx * 2] = tester_stereo[idx * 2 + 1] = tester[idx]; |
+ } |
+ Verify(expected_counts, num_patterns, tester_stereo, |
+ samples_per_channel, 2); |
+ delete[] tester_stereo; |
+ } |
+ |
+ void ReportRepetition(int id) override { |
+ auto it = counters_.find(id); |
+ if (it == counters_.end()) { |
+ counters_[id] = 0; |
+ } |
+ counters_[id]++; |
+ } |
+ |
+ int GetCount(int id) { |
+ auto it = counters_.find(id); |
+ if (it == counters_.end()) { |
+ return 0; |
+ } |
+ return counters_[id]; |
+ } |
+ |
+ void ResetCounters() { |
+ for (auto& item : counters_) { |
+ item.second = 0; |
+ } |
+ } |
+ |
+ private: |
+ std::map<int, int> counters_; |
+}; |
+ |
+TEST_F(RepetitionDetectorTest, Basic) { |
+ // 123456123456 look_back=6, loop_back_range=0, length=6, length_range=0 |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 3, 0, 3, 0} |
+ }; |
+ const int16_t kTestSignal[] = {1, 2, 3, 1, 2, 3}; |
+ const ExpectedCount kExpectedCounts_1[] = { |
+ {0, 1} |
+ }; |
+ const ExpectedCount kExpectedCounts_2[] = { |
+ {0, 3} |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts_1, sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+ Verify(kExpectedCounts_2, sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts_1, |
+ sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), kTestSignal, |
+ sizeof(kTestSignal) / sizeof(int16_t)); |
+ VerifyStereo(kExpectedCounts_2, |
+ sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), kTestSignal, |
+ sizeof(kTestSignal) / sizeof(int16_t)); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, StereoOutOfSync) { |
+ // 123456123456 look_back=6, loop_back_range=0, length=6, length_range=0 |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 3, 0, 3, 0} |
+ }; |
+ const int16_t kTestSignal[] = { |
+ 1, 1, |
+ 2, 2, |
+ 3, 3, |
+ 1, 1, |
+ 2, 2, |
+ 3, 1}; |
+ const ExpectedCount kExpectedCounts[] = { |
+ {0, 0} |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts, sizeof(kExpectedCounts) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t) / 2, 2); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, IncompletePattern) { |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 3, 0, 3, 0}, |
+ }; |
+ const int16_t kTestSignal[] = {1, 2, 1, 2, 3, 1, 2, 3}; |
+ const ExpectedCount kExpectedCounts[] = { |
+ {0, 1}, |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts, sizeof(kExpectedCounts) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts, sizeof(kExpectedCounts) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, PatternLongerThanFrame) { |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 6, 0, 6, 0}, |
+ }; |
+ const int16_t kTestSignal_1[] = {1, 2, 3, 4, 5}; |
+ const int16_t kTestSignal_2[] = {6, 1, 2, 3, 4, 5, 6}; |
+ const ExpectedCount kExpectedCounts_1[] = { |
+ {0, 0}, |
+ }; |
+ const ExpectedCount kExpectedCounts_2[] = { |
+ {0, 1}, |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts_1, sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), |
+ kTestSignal_1, sizeof(kTestSignal_1) / sizeof(int16_t)); |
+ Verify(kExpectedCounts_2, sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), |
+ kTestSignal_2, sizeof(kTestSignal_2) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts_1, |
+ sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), kTestSignal_1, |
+ sizeof(kTestSignal_1) / sizeof(int16_t)); |
+ VerifyStereo(kExpectedCounts_2, |
+ sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), kTestSignal_2, |
+ sizeof(kTestSignal_2) / sizeof(int16_t)); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, TwoPatterns) { |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 3, 0, 3, 0}, |
+ {1, 4, 0, 4, 0}, |
+ }; |
+ const int16_t kTestSignal_1[] = {1, 2, 3, 1, 2, 3}; |
+ const int16_t kTestSignal_2[] = {1, 2, 3, 4, 1, 2, 3, 4}; |
+ const ExpectedCount kExpectedCounts_1[] = { |
+ {0, 1}, |
+ {1, 0} |
+ }; |
+ const ExpectedCount kExpectedCounts_2[] = { |
+ {0, 2}, // Add 1 because the third 1,2,3 belongs to both patterns. |
+ {1, 1} |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts_1, sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), |
+ kTestSignal_1, sizeof(kTestSignal_1) / sizeof(int16_t)); |
+ Verify(kExpectedCounts_2, sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), |
+ kTestSignal_2, sizeof(kTestSignal_2) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts_1, |
+ sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), kTestSignal_1, |
+ sizeof(kTestSignal_1) / sizeof(int16_t)); |
+ VerifyStereo(kExpectedCounts_2, |
+ sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), kTestSignal_2, |
+ sizeof(kTestSignal_2) / sizeof(int16_t)); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, NestedPatterns) { |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 3, 0, 3, 0}, |
+ {1, 6, 0, 6, 0}, // When a triplet repeated 3 times, this is triggered. |
+ }; |
+ const int16_t kTestSignal[] = {1, 2, 3, 1, 2, 3}; |
+ const ExpectedCount kExpectedCounts_1[] = { |
+ {0, 1}, |
+ {1, 0} |
+ }; |
+ const ExpectedCount kExpectedCounts_2[] = { |
+ {0, 3}, // Add 1 because the third 1,2,3 belongs to both patterns. |
+ {1, 1} |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts_1, sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+ Verify(kExpectedCounts_2, sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts_1, |
+ sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), kTestSignal, |
+ sizeof(kTestSignal) / sizeof(int16_t)); |
+ VerifyStereo(kExpectedCounts_2, |
+ sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), kTestSignal, |
+ sizeof(kTestSignal) / sizeof(int16_t)); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, RangedLookBack) { |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 3, 1, 3, 1}, |
+ }; |
+ const int16_t kTestSignal_1[] = {1, 2, 3, 1, 2, 3}; |
+ const int16_t kTestSignal_2[] = {1, 2, 3, 4, 1, 2, 3, 4}; |
+ const ExpectedCount kExpectedCounts_1[] = { |
+ {0, 1}, |
+ }; |
+ const ExpectedCount kExpectedCounts_2[] = { |
+ {0, 3}, |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts_1, sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), |
+ kTestSignal_1, sizeof(kTestSignal_1) / sizeof(int16_t)); |
+ Verify(kExpectedCounts_2, sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), |
+ kTestSignal_2, sizeof(kTestSignal_2) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts_1, |
+ sizeof(kExpectedCounts_1) / sizeof(ExpectedCount), kTestSignal_1, |
+ sizeof(kTestSignal_1) / sizeof(int16_t)); |
+ VerifyStereo(kExpectedCounts_2, |
+ sizeof(kExpectedCounts_2) / sizeof(ExpectedCount), kTestSignal_2, |
+ sizeof(kTestSignal_2) / sizeof(int16_t)); |
+} |
+ |
+TEST_F(RepetitionDetectorTest, NotFullLengthPattern) { |
+ const Pattern kRepetitionPatterns[] = { |
+ // id, look_back, loop_back_range, length, length_range |
+ {0, 4, 0, 3, 0}, |
+ }; |
+ const int16_t kTestSignal[] = {1, 2, 3, -1, 1, 2, 3, -2}; |
+ const ExpectedCount kExpectedCounts[] = { |
+ {0, 1}, |
+ }; |
+ |
+ ResetRepetitionPattern(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof(Pattern)); |
+ Verify(kExpectedCounts, sizeof(kExpectedCounts) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+ ResetCounters(); |
+ VerifyStereo(kExpectedCounts, sizeof(kExpectedCounts) / sizeof(ExpectedCount), |
+ kTestSignal, sizeof(kTestSignal) / sizeof(int16_t)); |
+} |
+ |
+} // namespace webrtc |