Index: webrtc/modules/audio_processing/repetition_detector.cc |
diff --git a/webrtc/modules/audio_processing/repetition_detector.cc b/webrtc/modules/audio_processing/repetition_detector.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..185e6cbd94f1a489a55f0863e2e9b8df93cb854d |
--- /dev/null |
+++ b/webrtc/modules/audio_processing/repetition_detector.cc |
@@ -0,0 +1,145 @@ |
+/* |
+ * 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 "webrtc/modules/audio_processing/repetition_detector.h" |
+ |
+#include <string.h> // memset |
+ |
+#include "webrtc/base/checks.h" |
+ |
+namespace webrtc { |
+ |
+namespace { |
+static const RepetitionDetector::Pattern kRepetitionPatterns[] = { |
peah-webrtc
2015/08/12 11:02:54
Both look_back_range_ and length_range_ are zero
minyue-webrtc
2015/08/12 11:32:14
Maybe not enough but there is a unittest around th
peah-webrtc
2015/08/12 21:05:16
Sorry, I missed the unit test. Great!
|
+ // {id_, look_back_, look_back_range_, length_, length_range_} |
+ {0, 10, 0, 10, 0}, |
+ {1, 100, 0, 100, 0} |
+}; |
+} |
+ |
+RepetitionDetector::RepetitionDetector() |
+ : audio_buffer_(nullptr), |
+ num_channels_(0), |
+ buffer_length_samples_(0), |
+ buffer_end_(0) { |
+ RegisterRepititionPatterns(kRepetitionPatterns, |
+ sizeof(kRepetitionPatterns) / sizeof (Pattern)); |
+ CreateBuffer(); |
+} |
+ |
+RepetitionDetector::~RepetitionDetector() { |
+ DeleteBuffer(); |
+} |
+ |
+ |
+void RepetitionDetector::RegisterRepititionPatterns(const Pattern* patterns, |
peah-webrtc
2015/08/12 11:02:54
Typo, should be RegisterRepetitionPatterns
minyue-webrtc
2015/08/12 11:32:14
Acknowledged.
|
+ int num_patterns) { |
+ int max_look_back = 0; |
+ Pattern pattern; |
+ for (int idx = 0; idx < num_patterns; idx++) { |
+ pattern = patterns[idx]; |
+ for (int offset = -pattern.look_back_range_; |
peah-webrtc
2015/08/12 11:02:54
In the specified patterns, look_back_range_ is set
minyue-webrtc
2015/08/12 11:32:14
I think the look_back and length may not be necess
|
+ offset <= pattern.look_back_range_; offset++) { |
+ states_.push_back(State(pattern.id_, pattern.look_back_ + offset, |
+ pattern.length_, pattern.length_range_)); |
+ } |
+ if (pattern.look_back_ + pattern.look_back_range_ > max_look_back) { |
+ max_look_back = pattern.look_back_ + pattern.look_back_range_; |
+ } |
+ } |
+ buffer_length_samples_ = max_look_back; |
+} |
+ |
+void RepetitionDetector::ClearRepititionPatterns() { |
peah-webrtc
2015/08/12 11:02:54
A typo, should be ClearRepetitionPatterns
minyue-webrtc
2015/08/12 11:32:14
Acknowledged.
|
+ states_.clear(); |
+ buffer_length_samples_ = 0; |
+} |
+ |
+void RepetitionDetector::CreateBuffer() { |
+ if (audio_buffer_) { |
+ return; |
+ } |
+ audio_buffer_ = new int16_t*[num_channels_]; |
+ for (int ch = 0; ch < num_channels_; ch++) { |
+ audio_buffer_[ch] = new int16_t[buffer_length_samples_]; |
+ memset(audio_buffer_[ch], 0, buffer_length_samples_ * sizeof(int16_t)); |
+ } |
+ buffer_end_ = 0; |
+} |
+ |
+void RepetitionDetector::DeleteBuffer() { |
+ if (!audio_buffer_) { |
+ return; |
+ } |
+ for (int ch = 0; ch < num_channels_; ch++) { |
+ delete[] audio_buffer_[ch]; |
+ } |
+ delete[] audio_buffer_; |
+ audio_buffer_ = nullptr; |
+} |
+ |
+void RepetitionDetector::Reset(int new_num_channels) { |
+ DeleteBuffer(); |
+ num_channels_ = new_num_channels; |
+ CreateBuffer(); |
+ for (auto& state : states_) { |
+ state.count_ = 0; |
+ } |
+ // We do not reset |occurances_| to be able to count issues that have |
hlundin-webrtc
2015/08/12 14:12:04
What is occurances_?
minyue-webrtc
2015/08/12 14:20:20
Sorry. it was a counter, but now removed, since I
|
+ // happened. |
+} |
+ |
+void RepetitionDetector::Detect(const int16_t* data, int samples_per_channel, |
+ int num_channels) { |
+ DCHECK_GT(states_.size(), 0ul); |
+ if (num_channels != num_channels_) { |
+ Reset(num_channels); |
+ } |
+ |
+ int look_back_pointer; |
hlundin-webrtc
2015/08/12 14:12:04
This is not a pointer. Suggest look_back_index or
|
+ int new_buffer_end = buffer_end_; |
+ const int16_t* sample = data; |
+ |
+ for (int idx = 0; idx < samples_per_channel; idx++) { |
hlundin-webrtc
2015/08/12 14:12:04
This nested for loop and its associated code is ve
minyue-webrtc
2015/08/12 14:20:20
It can happen that repetition starts in the middle
hlundin-webrtc
2015/08/12 14:38:00
Hm, ok. But I still have a feeling you could simpl
peah-webrtc
2015/08/12 21:05:16
I agree that this feels more complex than needed.
|
+ for (auto& state : states_) { |
+ new_buffer_end = (buffer_end_ + 1) % buffer_length_samples_; |
+ look_back_pointer = (new_buffer_end - state.look_back_ + |
+ buffer_length_samples_) % buffer_length_samples_; |
peah-webrtc
2015/08/12 11:02:54
The addition of buffer_length_samples_ seems to be
minyue-webrtc
2015/08/12 11:32:13
This is to avoid negative, e,g, -2%3=-2
peah-webrtc
2015/08/12 21:05:16
Good point! Thanks!
|
+ |
+ // For multichannel audio, all channels have to repeat the same way. |
peah-webrtc
2015/08/12 11:02:54
Is this a neccessary requirement, would it not jus
minyue-webrtc
2015/08/12 11:32:14
I consulted Chromium people. It is supposed that s
hlundin-webrtc
2015/08/12 14:12:04
I agree with Per. Look at only one channel for now
minyue-webrtc
2015/08/28 14:27:00
In our recordings, we found that repetition should
|
+ bool sample_repeated = true; |
+ for (int ch = 0; ch < num_channels_; ch++) { |
+ if (sample[ch] != audio_buffer_[ch][look_back_pointer]) { |
+ sample_repeated = false; |
peah-webrtc
2015/08/12 21:05:16
Inequality is not a sufficient condition for repea
minyue-webrtc
2015/08/28 14:27:00
Zeros are treated specially now.
|
+ } |
+ } |
+ |
+ if (sample_repeated) { |
+ state.count_++; |
+ } |
+ if (state.count_>= state.look_back_ || // To break multiple repetitions. |
+ !sample_repeated) { |
+ if (state.count_ >= state.length_ - state.length_range_ && |
peah-webrtc
2015/08/12 11:02:54
I'm not fully sure about the role of the length_ra
minyue-webrtc
2015/08/12 11:32:14
see discussion on look_back_range
|
+ state.count_ <= state.length_ + state.length_range_) { |
+ ReportRepetition(state.id_); |
+ } |
+ state.count_ = 0; |
+ } |
+ } |
+ |
+ // Update buffer. |
+ for (int ch = 0; ch < num_channels_; ch++, sample++) { |
+ audio_buffer_[ch][new_buffer_end] = *sample; |
+ } |
+ buffer_end_ = new_buffer_end; |
+ } |
+} |
+ |
+} // namespace webrtc |