OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" | 11 #include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" |
12 | 12 |
13 #include <string.h> | 13 #include <string.h> |
14 #include <algorithm> | 14 #include <algorithm> |
15 | 15 |
16 #include "webrtc/base/checks.h" | 16 #include "webrtc/base/checks.h" |
17 #include "webrtc/base/constructormagic.h" | 17 #include "webrtc/base/constructormagic.h" |
18 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" | 18 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" |
19 #include "webrtc/modules/audio_processing/aec3/block_processor.h" | |
20 #include "webrtc/modules/audio_processing/aec3/decimator_by_4.h" | |
21 #include "webrtc/modules/audio_processing/aec3/fft_data.h" | |
19 #include "webrtc/system_wrappers/include/logging.h" | 22 #include "webrtc/system_wrappers/include/logging.h" |
20 | 23 |
21 namespace webrtc { | 24 namespace webrtc { |
22 namespace { | 25 namespace { |
23 | 26 |
27 class ApiCallJitterBuffer { | |
28 public: | |
29 explicit ApiCallJitterBuffer(size_t num_bands) { | |
30 buffer_.fill(std::vector<std::vector<float>>( | |
31 num_bands, std::vector<float>(kBlockSize, 0.f))); | |
32 } | |
33 | |
34 ~ApiCallJitterBuffer() = default; | |
35 | |
36 void Reset() { | |
37 size_ = 0; | |
38 last_insert_index_ = 0; | |
39 } | |
40 | |
41 void Insert(std::vector<std::vector<float>>* block) { | |
ivoc
2017/03/31 13:58:31
const ref
peah-webrtc
2017/04/03 08:02:33
Nice!
Done.
| |
42 RTC_DCHECK_LT(size_, buffer_.size()); | |
43 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size(); | |
44 RTC_DCHECK_EQ(buffer_[last_insert_index_].size(), block->size()); | |
45 RTC_DCHECK_EQ(buffer_[last_insert_index_][0].size(), (*block)[0].size()); | |
46 for (size_t k = 0; k < block->size(); ++k) { | |
47 std::copy((*block)[k].begin(), (*block)[k].end(), | |
48 buffer_[last_insert_index_][k].begin()); | |
49 } | |
50 | |
51 ++size_; | |
52 } | |
53 | |
54 void Remove(std::vector<std::vector<float>>* block) { | |
55 RTC_DCHECK_LT(0, size_); | |
56 --size_; | |
57 const size_t extract_index = | |
58 (last_insert_index_ - size_ + buffer_.size()) % buffer_.size(); | |
59 for (size_t k = 0; k < block->size(); ++k) { | |
60 std::copy(buffer_[extract_index][k].begin(), | |
61 buffer_[extract_index][k].end(), (*block)[k].begin()); | |
62 } | |
63 } | |
64 | |
65 size_t Size() const { return size_; } | |
66 bool Full() const { return size_ >= (buffer_.size()); } | |
67 bool Empty() const { return size_ == 0; } | |
68 | |
69 private: | |
70 // TODO(peah): Reduce the size to kMaxApiCallsJitterBlocks. | |
ivoc
2017/03/31 13:58:31
Can be removed.
peah-webrtc
2017/04/03 08:02:33
Done.
| |
71 std::array<std::vector<std::vector<float>>, kMaxApiCallsJitterBlocks> | |
72 buffer_; | |
73 size_t size_ = 0; | |
74 int last_insert_index_ = 0; | |
75 }; | |
76 | |
24 class RenderDelayBufferImpl final : public RenderDelayBuffer { | 77 class RenderDelayBufferImpl final : public RenderDelayBuffer { |
25 public: | 78 public: |
26 RenderDelayBufferImpl(size_t size_blocks, | 79 RenderDelayBufferImpl(size_t num_bands); |
27 size_t num_bands, | |
28 size_t max_api_jitter_blocks); | |
29 ~RenderDelayBufferImpl() override; | 80 ~RenderDelayBufferImpl() override; |
30 | 81 |
82 void Reset() override; | |
31 bool Insert(std::vector<std::vector<float>>* block) override; | 83 bool Insert(std::vector<std::vector<float>>* block) override; |
32 const std::vector<std::vector<float>>& GetNext() override; | 84 bool UpdateBuffers() override; |
33 void SetDelay(size_t delay) override; | 85 void SetDelay(size_t delay) override; |
34 size_t Delay() const override { return delay_; } | 86 size_t Delay() const override { return delay_; } |
35 size_t MaxDelay() const override { | 87 |
36 return buffer_.size() - max_api_jitter_blocks_; | 88 const RenderBuffer& GetRenderBuffer() const override { return fft_buffer_; } |
89 | |
90 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override { | |
91 return downsampled_render_buffer_; | |
37 } | 92 } |
38 bool IsBlockAvailable() const override { return insert_surplus_ > 0; } | |
39 size_t MaxApiJitter() const override { return max_api_jitter_blocks_; } | |
40 | 93 |
41 private: | 94 private: |
42 const size_t max_api_jitter_blocks_; | 95 const Aec3Optimization optimization_; |
43 std::vector<std::vector<std::vector<float>>> buffer_; | 96 std::array<std::vector<std::vector<float>>, kRenderDelayBufferSize> buffer_; |
97 size_t delay_ = 0; | |
44 size_t last_insert_index_ = 0; | 98 size_t last_insert_index_ = 0; |
45 size_t delay_ = 0; | 99 RenderBuffer fft_buffer_; |
46 size_t insert_surplus_ = 0; | 100 DownsampledRenderBuffer downsampled_render_buffer_; |
47 | 101 DecimatorBy4 render_decimator_; |
102 ApiCallJitterBuffer api_call_jitter_buffer_; | |
48 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl); | 103 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl); |
49 }; | 104 }; |
50 | 105 |
51 RenderDelayBufferImpl::RenderDelayBufferImpl(size_t size_blocks, | 106 RenderDelayBufferImpl::RenderDelayBufferImpl(size_t num_bands) |
52 size_t num_bands, | 107 : optimization_(DetectOptimization()), |
53 size_t max_api_jitter_blocks) | 108 fft_buffer_(optimization_, |
54 : max_api_jitter_blocks_(max_api_jitter_blocks), | |
55 buffer_(size_blocks + max_api_jitter_blocks_, | |
56 std::vector<std::vector<float>>( | |
57 num_bands, | 109 num_bands, |
58 std::vector<float>(kBlockSize, 0.f))) {} | 110 std::max(30, kAdaptiveFilterLength), |
111 std::vector<size_t>(1, kAdaptiveFilterLength)), | |
112 api_call_jitter_buffer_(num_bands) { | |
113 buffer_.fill(std::vector<std::vector<float>>( | |
114 num_bands, std::vector<float>(kBlockSize, 0.f))); | |
115 | |
116 RTC_DCHECK_LT(buffer_.size(), downsampled_render_buffer_.buffer.size()); | |
117 } | |
59 | 118 |
60 RenderDelayBufferImpl::~RenderDelayBufferImpl() = default; | 119 RenderDelayBufferImpl::~RenderDelayBufferImpl() = default; |
61 | 120 |
121 void RenderDelayBufferImpl::Reset() { | |
122 // Empty all data in the buffers. | |
123 delay_ = 0; | |
124 last_insert_index_ = 0; | |
125 downsampled_render_buffer_.position = 0; | |
126 downsampled_render_buffer_.buffer.fill(0.f); | |
127 fft_buffer_.Clear(); | |
128 api_call_jitter_buffer_.Reset(); | |
129 } | |
130 | |
62 bool RenderDelayBufferImpl::Insert(std::vector<std::vector<float>>* block) { | 131 bool RenderDelayBufferImpl::Insert(std::vector<std::vector<float>>* block) { |
63 RTC_DCHECK_EQ(block->size(), buffer_[0].size()); | 132 RTC_DCHECK_EQ(block->size(), buffer_[0].size()); |
64 RTC_DCHECK_EQ((*block)[0].size(), buffer_[0][0].size()); | 133 RTC_DCHECK_EQ((*block)[0].size(), buffer_[0][0].size()); |
65 | 134 |
66 if (insert_surplus_ == max_api_jitter_blocks_) { | 135 if (api_call_jitter_buffer_.Full()) { |
136 // Report buffer overrun and let the caller handle the overrun. | |
67 return false; | 137 return false; |
68 } | 138 } |
69 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size(); | 139 api_call_jitter_buffer_.Insert(block); |
70 block->swap(buffer_[last_insert_index_]); | |
71 | |
72 ++insert_surplus_; | |
73 | 140 |
74 return true; | 141 return true; |
75 } | 142 } |
76 | 143 |
77 const std::vector<std::vector<float>>& RenderDelayBufferImpl::GetNext() { | 144 bool RenderDelayBufferImpl::UpdateBuffers() { |
78 RTC_DCHECK(IsBlockAvailable()); | 145 bool underrun = true; |
79 const size_t extract_index_ = | 146 // Update the buffers with a new block if such is available, otherwise repeat |
80 (last_insert_index_ - delay_ - insert_surplus_ + 1 + buffer_.size()) % | 147 // the previous block. |
81 buffer_.size(); | 148 if (api_call_jitter_buffer_.Size() > 0) { |
82 RTC_DCHECK_LE(0, extract_index_); | 149 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size(); |
83 RTC_DCHECK_GT(buffer_.size(), extract_index_); | 150 api_call_jitter_buffer_.Remove(&buffer_[last_insert_index_]); |
84 | 151 |
85 RTC_DCHECK_LT(0, insert_surplus_); | 152 underrun = false; |
86 --insert_surplus_; | 153 } |
87 | 154 |
88 return buffer_[extract_index_]; | 155 downsampled_render_buffer_.position = |
156 (downsampled_render_buffer_.position - kSubBlockSize + | |
157 downsampled_render_buffer_.buffer.size()) % | |
158 downsampled_render_buffer_.buffer.size(); | |
159 | |
160 std::array<float, kSubBlockSize> render_downsampled; | |
161 render_decimator_.Decimate(buffer_[last_insert_index_][0], | |
162 render_downsampled); | |
163 std::copy(render_downsampled.rbegin(), render_downsampled.rend(), | |
164 downsampled_render_buffer_.buffer.begin() + | |
165 downsampled_render_buffer_.position); | |
166 | |
167 fft_buffer_.Insert( | |
168 buffer_[(last_insert_index_ - delay_ + buffer_.size()) % buffer_.size()]); | |
169 return !underrun; | |
89 } | 170 } |
90 | 171 |
91 void RenderDelayBufferImpl::SetDelay(size_t delay) { | 172 void RenderDelayBufferImpl::SetDelay(size_t delay) { |
92 RTC_DCHECK_GE(MaxDelay(), delay); | 173 if (delay_ == delay) { |
93 delay_ = delay; | 174 return; |
175 } | |
176 | |
177 // If there is a new delay set, clear the fft buffer. | |
178 fft_buffer_.Clear(); | |
179 | |
180 if ((buffer_.size() - 1) < delay) { | |
181 // If the desired delay is larger than the delay buffer, shorten the delay | |
182 // buffer size to achieve the desired alignment with the available buffer | |
183 // size. | |
184 downsampled_render_buffer_.position = | |
185 (downsampled_render_buffer_.position + | |
186 kSubBlockSize * (delay - (buffer_.size() - 1))) % | |
187 downsampled_render_buffer_.buffer.size(); | |
188 | |
189 last_insert_index_ = | |
190 (last_insert_index_ - (delay - (buffer_.size() - 1)) + buffer_.size()) % | |
ivoc
2017/03/31 13:58:32
If delay is sufficiently large (larger that 2 * bu
peah-webrtc
2017/04/03 08:02:33
Hmm, that is true. In practice that cannot happen
ivoc
2017/04/03 16:09:07
Great, it looks much better now.
| |
191 buffer_.size(); | |
192 delay_ = buffer_.size() - 1; | |
193 } else { | |
194 delay_ = delay; | |
195 } | |
94 } | 196 } |
95 | 197 |
96 } // namespace | 198 } // namespace |
97 | 199 |
98 RenderDelayBuffer* RenderDelayBuffer::Create(size_t size_blocks, | 200 RenderDelayBuffer* RenderDelayBuffer::Create(size_t num_bands) { |
99 size_t num_bands, | 201 return new RenderDelayBufferImpl(num_bands); |
100 size_t max_api_jitter_blocks) { | |
101 return new RenderDelayBufferImpl(size_blocks, num_bands, | |
102 max_api_jitter_blocks); | |
103 } | 202 } |
104 | 203 |
105 } // namespace webrtc | 204 } // namespace webrtc |
OLD | NEW |