OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/modules/audio_processing/repetition_detector.h" | |
12 | |
13 #include <algorithm> | |
14 | |
15 #include "webrtc/base/checks.h" | |
16 #include "webrtc/base/safe_conversions.h" | |
17 | |
18 namespace webrtc { | |
19 | |
20 namespace { | |
21 static const RepetitionDetector::Pattern kRepetitionPatterns[] = { | |
22 // {id_, look_back_, length_} | |
23 {0, 10, 10}, | |
24 {1, 100, 10} | |
25 }; | |
26 static const size_t kMaxFrames = 480; // 10ms * 48kHz | |
27 } | |
28 | |
29 RepetitionDetector::State::State(int id, int look_back_ms, int min_length_ms) | |
30 : id_(id), | |
31 look_back_ms_(look_back_ms), | |
32 min_length_ms_(min_length_ms) { | |
33 Reset(); | |
34 } | |
35 | |
36 void RepetitionDetector::State::Increment(bool zero) { | |
37 if (0 == count_frames_ && zero) { | |
38 all_zero_ = true; | |
39 } | |
40 ++count_frames_; | |
41 if (!zero) { | |
42 all_zero_ = false; | |
43 } | |
44 } | |
45 | |
46 bool RepetitionDetector::State::HasValidReport(int sample_rate_hz) const { | |
47 return (!all_zero_ && count_frames_ >= | |
48 rtc::checked_cast<size_t>(min_length_ms_ * sample_rate_hz / 1000)); | |
49 } | |
50 | |
51 void RepetitionDetector::State::Reset() { | |
52 count_frames_ = 0; | |
53 all_zero_ = true; | |
54 reported_ = false; | |
55 } | |
56 | |
57 RepetitionDetector::RepetitionDetector() | |
58 : max_look_back_ms_(0), | |
59 sample_rate_hz_(0), | |
60 buffer_size_frames_(0), | |
61 buffer_end_index_(0), | |
62 max_frames_(kMaxFrames) { | |
63 RegisterRepetitionPatterns(kRepetitionPatterns, | |
64 sizeof(kRepetitionPatterns) / sizeof (Pattern)); | |
65 } | |
66 | |
67 void RepetitionDetector::RegisterRepetitionPatterns(const Pattern* patterns, | |
68 size_t num_patterns) { | |
69 Pattern pattern; | |
70 for (size_t idx = 0; idx < num_patterns; idx++) { | |
71 pattern = patterns[idx]; | |
72 states_.push_back(new State(pattern.id_, pattern.look_back_ms_, | |
73 pattern.min_length_ms_)); | |
74 if (pattern.look_back_ms_ > max_look_back_ms_) { | |
75 max_look_back_ms_ = pattern.look_back_ms_; | |
76 } | |
77 } | |
78 } | |
79 | |
80 void RepetitionDetector::Reset(size_t num_channels, int sample_rate_hz) { | |
81 num_channels_ = num_channels; | |
82 sample_rate_hz_ = sample_rate_hz; | |
83 int sample_1k = max_look_back_ms_ * sample_rate_hz_; | |
84 buffer_size_frames_ = (sample_1k + 999) / 1000 + max_frames_; | |
hlundin-webrtc
2015/09/15 09:26:38
Now just comment that what you implemented is in f
minyue-webrtc
2015/09/17 13:45:22
Done.
| |
85 audio_buffer_.resize(buffer_size_frames_ * num_channels_); | |
86 for (auto state : states_) { | |
87 state->Reset(); | |
88 } | |
89 } | |
90 | |
91 void RepetitionDetector::AddFramesToBuffer(const float* data, | |
92 size_t num_frames) { | |
93 DCHECK_LE(num_frames, buffer_size_frames_); | |
94 size_t margin = buffer_size_frames_ - buffer_end_index_; | |
hlundin-webrtc
2015/09/15 09:26:38
const
minyue-webrtc
2015/09/17 13:45:22
Done.
| |
95 const auto it = audio_buffer_.begin() + buffer_end_index_ * num_channels_; | |
96 if (num_frames <= margin) { | |
97 std::copy(data, data + num_frames * num_channels_, it); | |
98 buffer_end_index_ += num_frames; | |
99 } else { | |
100 std::copy(data, data + margin * num_channels_, it); | |
101 std::copy(data + margin * num_channels_, data + num_frames * num_channels_, | |
102 audio_buffer_.begin()); | |
103 buffer_end_index_ = num_frames - margin; | |
104 } | |
105 } | |
106 | |
107 bool RepetitionDetector::Equal(const float* frame, | |
108 int look_back_frames) const { | |
109 const size_t look_back_index = | |
110 (buffer_end_index_ + buffer_size_frames_ - look_back_frames) % | |
111 buffer_size_frames_; | |
112 auto it = audio_buffer_.begin() + look_back_index * num_channels_; | |
113 for (size_t cdx = 0; cdx < num_channels_; ++cdx, ++frame, ++it) { | |
114 if (*frame != *it) { | |
115 return false; | |
116 } | |
117 } | |
118 return true; | |
119 } | |
120 | |
121 bool RepetitionDetector::IsZero(const float* frame) const { | |
122 for (size_t cdx = 0; cdx < num_channels_; ++cdx, ++frame) { | |
123 if (*frame != 0) { | |
124 return false; | |
125 } | |
126 } | |
127 return true; | |
128 } | |
129 | |
130 void RepetitionDetector::Detect(const float* data, size_t num_frames, | |
131 size_t num_channels, int sample_rate_hz) { | |
132 DCHECK_GT(states_.size(), 0ul); | |
133 if (num_channels != num_channels_ || sample_rate_hz != sample_rate_hz_) { | |
134 Reset(num_channels, sample_rate_hz); | |
135 } | |
136 | |
137 while (num_frames > max_frames_) { | |
138 Detect(data, max_frames_, num_channels, sample_rate_hz); | |
139 data += max_frames_ * num_channels; | |
140 num_frames -= max_frames_; | |
141 } | |
142 | |
143 if (num_frames == 0) | |
144 return; | |
145 | |
146 AddFramesToBuffer(data, num_frames); | |
147 | |
148 for (size_t idx = num_frames; idx > 0; --idx, data += num_channels) { | |
149 for (auto state : states_) { | |
150 const size_t look_back_frames = | |
151 rtc::CheckedDivExact(state->look_back_ms() * sample_rate_hz_, 1000); | |
152 // Equal(data, offset) checks if |data| equals the audio frame located | |
153 // |offset| frames from the end of buffer. Now a full frame has been | |
154 // inserted to the buffer, and thus |offset| should compensate for it. | |
155 if (Equal(data, look_back_frames + idx)) { | |
156 if (!state->reported()) { | |
157 state->Increment(IsZero(data)); | |
158 if (state->HasValidReport(sample_rate_hz)) { | |
159 ReportRepetition(state->id()); | |
160 state->set_reported(true); | |
161 } | |
162 } | |
163 } else { | |
164 state->Reset(); | |
165 } | |
166 } | |
167 } | |
168 } | |
169 | |
170 } // namespace webrtc | |
OLD | NEW |