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" |
| 22 #include "webrtc/system_wrappers/include/logging.h" |
19 | 23 |
20 namespace webrtc { | 24 namespace webrtc { |
21 namespace { | 25 namespace { |
22 | 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(const std::vector<std::vector<float>>& block) { |
| 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 ++size_; |
| 51 } |
| 52 |
| 53 void Remove(std::vector<std::vector<float>>* block) { |
| 54 RTC_DCHECK_LT(0, size_); |
| 55 --size_; |
| 56 const size_t extract_index = |
| 57 (last_insert_index_ - size_ + buffer_.size()) % buffer_.size(); |
| 58 for (size_t k = 0; k < block->size(); ++k) { |
| 59 std::copy(buffer_[extract_index][k].begin(), |
| 60 buffer_[extract_index][k].end(), (*block)[k].begin()); |
| 61 } |
| 62 } |
| 63 |
| 64 size_t Size() const { return size_; } |
| 65 bool Full() const { return size_ >= (buffer_.size()); } |
| 66 bool Empty() const { return size_ == 0; } |
| 67 |
| 68 private: |
| 69 std::array<std::vector<std::vector<float>>, kMaxApiCallsJitterBlocks> buffer_; |
| 70 size_t size_ = 0; |
| 71 int last_insert_index_ = 0; |
| 72 }; |
| 73 |
23 class RenderDelayBufferImpl final : public RenderDelayBuffer { | 74 class RenderDelayBufferImpl final : public RenderDelayBuffer { |
24 public: | 75 public: |
25 RenderDelayBufferImpl(size_t size_blocks, | 76 explicit RenderDelayBufferImpl(size_t num_bands); |
26 size_t num_bands, | |
27 size_t max_api_jitter_blocks); | |
28 ~RenderDelayBufferImpl() override; | 77 ~RenderDelayBufferImpl() override; |
29 | 78 |
30 bool Insert(std::vector<std::vector<float>>* block) override; | 79 void Reset() override; |
31 const std::vector<std::vector<float>>& GetNext() override; | 80 bool Insert(const std::vector<std::vector<float>>& block) override; |
| 81 bool UpdateBuffers() override; |
32 void SetDelay(size_t delay) override; | 82 void SetDelay(size_t delay) override; |
33 size_t Delay() const override { return delay_; } | 83 size_t Delay() const override { return delay_; } |
34 size_t MaxDelay() const override { | 84 |
35 return buffer_.size() - max_api_jitter_blocks_; | 85 const RenderBuffer& GetRenderBuffer() const override { return fft_buffer_; } |
| 86 |
| 87 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override { |
| 88 return downsampled_render_buffer_; |
36 } | 89 } |
37 bool IsBlockAvailable() const override { return insert_surplus_ > 0; } | |
38 size_t MaxApiJitter() const override { return max_api_jitter_blocks_; } | |
39 | 90 |
40 private: | 91 private: |
41 const size_t max_api_jitter_blocks_; | 92 const Aec3Optimization optimization_; |
42 std::vector<std::vector<std::vector<float>>> buffer_; | 93 std::array<std::vector<std::vector<float>>, kRenderDelayBufferSize> buffer_; |
| 94 size_t delay_ = 0; |
43 size_t last_insert_index_ = 0; | 95 size_t last_insert_index_ = 0; |
44 size_t delay_ = 0; | 96 RenderBuffer fft_buffer_; |
45 size_t insert_surplus_ = 0; | 97 DownsampledRenderBuffer downsampled_render_buffer_; |
46 | 98 DecimatorBy4 render_decimator_; |
| 99 ApiCallJitterBuffer api_call_jitter_buffer_; |
47 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl); | 100 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl); |
48 }; | 101 }; |
49 | 102 |
50 RenderDelayBufferImpl::RenderDelayBufferImpl(size_t size_blocks, | 103 RenderDelayBufferImpl::RenderDelayBufferImpl(size_t num_bands) |
51 size_t num_bands, | 104 : optimization_(DetectOptimization()), |
52 size_t max_api_jitter_blocks) | 105 fft_buffer_(optimization_, |
53 : max_api_jitter_blocks_(max_api_jitter_blocks), | |
54 buffer_(size_blocks + max_api_jitter_blocks_, | |
55 std::vector<std::vector<float>>( | |
56 num_bands, | 106 num_bands, |
57 std::vector<float>(kBlockSize, 0.f))) {} | 107 std::max(30, kAdaptiveFilterLength), |
| 108 std::vector<size_t>(1, kAdaptiveFilterLength)), |
| 109 api_call_jitter_buffer_(num_bands) { |
| 110 buffer_.fill(std::vector<std::vector<float>>( |
| 111 num_bands, std::vector<float>(kBlockSize, 0.f))); |
| 112 |
| 113 RTC_DCHECK_LT(buffer_.size(), downsampled_render_buffer_.buffer.size()); |
| 114 } |
58 | 115 |
59 RenderDelayBufferImpl::~RenderDelayBufferImpl() = default; | 116 RenderDelayBufferImpl::~RenderDelayBufferImpl() = default; |
60 | 117 |
61 bool RenderDelayBufferImpl::Insert(std::vector<std::vector<float>>* block) { | 118 void RenderDelayBufferImpl::Reset() { |
62 RTC_DCHECK_EQ(block->size(), buffer_[0].size()); | 119 // Empty all data in the buffers. |
63 RTC_DCHECK_EQ((*block)[0].size(), buffer_[0][0].size()); | 120 delay_ = 0; |
| 121 last_insert_index_ = 0; |
| 122 downsampled_render_buffer_.position = 0; |
| 123 downsampled_render_buffer_.buffer.fill(0.f); |
| 124 fft_buffer_.Clear(); |
| 125 api_call_jitter_buffer_.Reset(); |
| 126 } |
64 | 127 |
65 if (insert_surplus_ == max_api_jitter_blocks_) { | 128 bool RenderDelayBufferImpl::Insert( |
| 129 const std::vector<std::vector<float>>& block) { |
| 130 RTC_DCHECK_EQ(block.size(), buffer_[0].size()); |
| 131 RTC_DCHECK_EQ(block[0].size(), buffer_[0][0].size()); |
| 132 |
| 133 if (api_call_jitter_buffer_.Full()) { |
| 134 // Report buffer overrun and let the caller handle the overrun. |
66 return false; | 135 return false; |
67 } | 136 } |
68 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size(); | 137 api_call_jitter_buffer_.Insert(block); |
69 block->swap(buffer_[last_insert_index_]); | |
70 | |
71 ++insert_surplus_; | |
72 | 138 |
73 return true; | 139 return true; |
74 } | 140 } |
75 | 141 |
76 const std::vector<std::vector<float>>& RenderDelayBufferImpl::GetNext() { | 142 bool RenderDelayBufferImpl::UpdateBuffers() { |
77 RTC_DCHECK(IsBlockAvailable()); | 143 bool underrun = true; |
78 const size_t extract_index_ = | 144 // Update the buffers with a new block if such is available, otherwise repeat |
79 (last_insert_index_ - delay_ - insert_surplus_ + 1 + buffer_.size()) % | 145 // the previous block. |
80 buffer_.size(); | 146 if (api_call_jitter_buffer_.Size() > 0) { |
81 RTC_DCHECK_LE(0, extract_index_); | 147 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size(); |
82 RTC_DCHECK_GT(buffer_.size(), extract_index_); | 148 api_call_jitter_buffer_.Remove(&buffer_[last_insert_index_]); |
83 | 149 |
84 RTC_DCHECK_LT(0, insert_surplus_); | 150 underrun = false; |
85 --insert_surplus_; | 151 } |
86 | 152 |
87 return buffer_[extract_index_]; | 153 downsampled_render_buffer_.position = |
| 154 (downsampled_render_buffer_.position - kSubBlockSize + |
| 155 downsampled_render_buffer_.buffer.size()) % |
| 156 downsampled_render_buffer_.buffer.size(); |
| 157 |
| 158 std::array<float, kSubBlockSize> render_downsampled; |
| 159 render_decimator_.Decimate(buffer_[last_insert_index_][0], |
| 160 render_downsampled); |
| 161 std::copy(render_downsampled.rbegin(), render_downsampled.rend(), |
| 162 downsampled_render_buffer_.buffer.begin() + |
| 163 downsampled_render_buffer_.position); |
| 164 |
| 165 fft_buffer_.Insert( |
| 166 buffer_[(last_insert_index_ - delay_ + buffer_.size()) % buffer_.size()]); |
| 167 return !underrun; |
88 } | 168 } |
89 | 169 |
90 void RenderDelayBufferImpl::SetDelay(size_t delay) { | 170 void RenderDelayBufferImpl::SetDelay(size_t delay) { |
91 RTC_DCHECK_GE(MaxDelay(), delay); | 171 if (delay_ == delay) { |
92 delay_ = delay; | 172 return; |
| 173 } |
| 174 |
| 175 // If there is a new delay set, clear the fft buffer. |
| 176 fft_buffer_.Clear(); |
| 177 |
| 178 const size_t max_delay = buffer_.size() - 1; |
| 179 if (max_delay < delay) { |
| 180 // If the desired delay is larger than the delay buffer, shorten the delay |
| 181 // buffer size to achieve the desired alignment with the available buffer |
| 182 // size. |
| 183 const size_t delay_decrease = delay - max_delay; |
| 184 RTC_DCHECK_LT(delay_decrease, buffer_.size()); |
| 185 |
| 186 downsampled_render_buffer_.position = |
| 187 (downsampled_render_buffer_.position + kSubBlockSize * delay_decrease) % |
| 188 downsampled_render_buffer_.buffer.size(); |
| 189 |
| 190 last_insert_index_ = |
| 191 (last_insert_index_ + buffer_.size() - delay_decrease) % buffer_.size(); |
| 192 |
| 193 RTC_DCHECK_EQ(max_delay, delay_ - delay_decrease); |
| 194 delay_ = max_delay; |
| 195 } else { |
| 196 delay_ = delay; |
| 197 } |
93 } | 198 } |
94 | 199 |
95 } // namespace | 200 } // namespace |
96 | 201 |
97 RenderDelayBuffer* RenderDelayBuffer::Create(size_t size_blocks, | 202 RenderDelayBuffer* RenderDelayBuffer::Create(size_t num_bands) { |
98 size_t num_bands, | 203 return new RenderDelayBufferImpl(num_bands); |
99 size_t max_api_jitter_blocks) { | |
100 return new RenderDelayBufferImpl(size_blocks, num_bands, | |
101 max_api_jitter_blocks); | |
102 } | 204 } |
103 | 205 |
104 } // namespace webrtc | 206 } // namespace webrtc |
OLD | NEW |