blob: e173aa14d94ed824a80bb5dea1b8f441e88dad1c [file] [log] [blame]
peah69221db2017-01-27 03:28:19 -08001/*
2 * Copyright (c) 2017 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec3/render_delay_buffer.h"
peah69221db2017-01-27 03:28:19 -080012
13#include <string.h>
14#include <algorithm>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_processing/aec3/aec3_common.h"
17#include "modules/audio_processing/aec3/block_processor.h"
18#include "modules/audio_processing/aec3/decimator_by_4.h"
19#include "modules/audio_processing/aec3/fft_data.h"
20#include "rtc_base/checks.h"
21#include "rtc_base/constructormagic.h"
22#include "rtc_base/logging.h"
peah69221db2017-01-27 03:28:19 -080023
24namespace webrtc {
25namespace {
26
peahcf02cf12017-04-05 14:18:07 -070027class ApiCallJitterBuffer {
peah69221db2017-01-27 03:28:19 -080028 public:
peahcf02cf12017-04-05 14:18:07 -070029 explicit ApiCallJitterBuffer(size_t num_bands) {
30 buffer_.fill(std::vector<std::vector<float>>(
31 num_bands, std::vector<float>(kBlockSize, 0.f)));
peah69221db2017-01-27 03:28:19 -080032 }
peahcf02cf12017-04-05 14:18:07 -070033
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; }
peah69221db2017-01-27 03:28:19 -080067
68 private:
peahcf02cf12017-04-05 14:18:07 -070069 std::array<std::vector<std::vector<float>>, kMaxApiCallsJitterBlocks> buffer_;
70 size_t size_ = 0;
71 int last_insert_index_ = 0;
72};
peah69221db2017-01-27 03:28:19 -080073
peahcf02cf12017-04-05 14:18:07 -070074class RenderDelayBufferImpl final : public RenderDelayBuffer {
75 public:
76 explicit RenderDelayBufferImpl(size_t num_bands);
77 ~RenderDelayBufferImpl() override;
78
79 void Reset() override;
80 bool Insert(const std::vector<std::vector<float>>& block) override;
81 bool UpdateBuffers() override;
82 void SetDelay(size_t delay) override;
83 size_t Delay() const override { return delay_; }
84
85 const RenderBuffer& GetRenderBuffer() const override { return fft_buffer_; }
86
87 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override {
88 return downsampled_render_buffer_;
89 }
90
91 private:
92 const Aec3Optimization optimization_;
93 std::array<std::vector<std::vector<float>>, kRenderDelayBufferSize> buffer_;
94 size_t delay_ = 0;
95 size_t last_insert_index_ = 0;
96 RenderBuffer fft_buffer_;
97 DownsampledRenderBuffer downsampled_render_buffer_;
98 DecimatorBy4 render_decimator_;
99 ApiCallJitterBuffer api_call_jitter_buffer_;
peahdebaa442017-05-03 05:39:09 -0700100 const std::vector<std::vector<float>> zero_block_;
peah69221db2017-01-27 03:28:19 -0800101 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
102};
103
peahcf02cf12017-04-05 14:18:07 -0700104RenderDelayBufferImpl::RenderDelayBufferImpl(size_t num_bands)
105 : optimization_(DetectOptimization()),
peah86afe9d2017-04-06 15:45:32 -0700106 fft_buffer_(
107 optimization_,
108 num_bands,
Per Ã…hgren1b4059e2017-10-15 20:19:21 +0200109 std::max(kUnknownDelayRenderWindowSize, kAdaptiveFilterLength),
peah86afe9d2017-04-06 15:45:32 -0700110 std::vector<size_t>(1, kAdaptiveFilterLength)),
peahdebaa442017-05-03 05:39:09 -0700111 api_call_jitter_buffer_(num_bands),
112 zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)) {
peahcf02cf12017-04-05 14:18:07 -0700113 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}
peah69221db2017-01-27 03:28:19 -0800118
119RenderDelayBufferImpl::~RenderDelayBufferImpl() = default;
120
peahcf02cf12017-04-05 14:18:07 -0700121void 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();
peah4b572d02017-04-06 16:33:06 -0700129 for (auto& c : buffer_) {
130 for (auto& b : c) {
131 std::fill(b.begin(), b.end(), 0.f);
132 }
133 }
peahcf02cf12017-04-05 14:18:07 -0700134}
peah69221db2017-01-27 03:28:19 -0800135
peahcf02cf12017-04-05 14:18:07 -0700136bool RenderDelayBufferImpl::Insert(
137 const std::vector<std::vector<float>>& block) {
138 RTC_DCHECK_EQ(block.size(), buffer_[0].size());
139 RTC_DCHECK_EQ(block[0].size(), buffer_[0][0].size());
140
141 if (api_call_jitter_buffer_.Full()) {
142 // Report buffer overrun and let the caller handle the overrun.
peah69221db2017-01-27 03:28:19 -0800143 return false;
144 }
peahcf02cf12017-04-05 14:18:07 -0700145 api_call_jitter_buffer_.Insert(block);
peah69221db2017-01-27 03:28:19 -0800146
147 return true;
148}
149
peahcf02cf12017-04-05 14:18:07 -0700150bool RenderDelayBufferImpl::UpdateBuffers() {
151 bool underrun = true;
peahdebaa442017-05-03 05:39:09 -0700152 // Update the buffers with a new block if such is available, otherwise insert
153 // a block of silence.
peahcf02cf12017-04-05 14:18:07 -0700154 if (api_call_jitter_buffer_.Size() > 0) {
155 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size();
156 api_call_jitter_buffer_.Remove(&buffer_[last_insert_index_]);
peahcf02cf12017-04-05 14:18:07 -0700157 underrun = false;
158 }
peah69221db2017-01-27 03:28:19 -0800159
peahcf02cf12017-04-05 14:18:07 -0700160 downsampled_render_buffer_.position =
161 (downsampled_render_buffer_.position - kSubBlockSize +
162 downsampled_render_buffer_.buffer.size()) %
163 downsampled_render_buffer_.buffer.size();
164
165 std::array<float, kSubBlockSize> render_downsampled;
peahdebaa442017-05-03 05:39:09 -0700166 if (underrun) {
167 render_decimator_.Decimate(zero_block_[0], render_downsampled);
168 } else {
169 render_decimator_.Decimate(buffer_[last_insert_index_][0],
170 render_downsampled);
171 }
peahcf02cf12017-04-05 14:18:07 -0700172 std::copy(render_downsampled.rbegin(), render_downsampled.rend(),
173 downsampled_render_buffer_.buffer.begin() +
174 downsampled_render_buffer_.position);
175
peahdebaa442017-05-03 05:39:09 -0700176 if (underrun) {
177 fft_buffer_.Insert(zero_block_);
178 } else {
179 fft_buffer_.Insert(buffer_[(last_insert_index_ - delay_ + buffer_.size()) %
180 buffer_.size()]);
181 }
peahcf02cf12017-04-05 14:18:07 -0700182 return !underrun;
peah69221db2017-01-27 03:28:19 -0800183}
184
185void RenderDelayBufferImpl::SetDelay(size_t delay) {
peahcf02cf12017-04-05 14:18:07 -0700186 if (delay_ == delay) {
187 return;
188 }
189
190 // If there is a new delay set, clear the fft buffer.
191 fft_buffer_.Clear();
192
peah86afe9d2017-04-06 15:45:32 -0700193 if ((buffer_.size() - 1) < delay) {
peahcf02cf12017-04-05 14:18:07 -0700194 // If the desired delay is larger than the delay buffer, shorten the delay
195 // buffer size to achieve the desired alignment with the available buffer
196 // size.
peahcf02cf12017-04-05 14:18:07 -0700197 downsampled_render_buffer_.position =
peah86afe9d2017-04-06 15:45:32 -0700198 (downsampled_render_buffer_.position +
199 kSubBlockSize * (delay - (buffer_.size() - 1))) %
peahcf02cf12017-04-05 14:18:07 -0700200 downsampled_render_buffer_.buffer.size();
201
202 last_insert_index_ =
peah86afe9d2017-04-06 15:45:32 -0700203 (last_insert_index_ - (delay - (buffer_.size() - 1)) + buffer_.size()) %
204 buffer_.size();
205 delay_ = buffer_.size() - 1;
peahcf02cf12017-04-05 14:18:07 -0700206 } else {
207 delay_ = delay;
208 }
peah69221db2017-01-27 03:28:19 -0800209}
210
211} // namespace
212
peahcf02cf12017-04-05 14:18:07 -0700213RenderDelayBuffer* RenderDelayBuffer::Create(size_t num_bands) {
214 return new RenderDelayBufferImpl(num_bands);
peah69221db2017-01-27 03:28:19 -0800215}
216
217} // namespace webrtc