1 /*
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 
11 #include "modules/audio_processing/aec3/render_buffer.h"
12 
13 #include <algorithm>
14 
15 #include "modules/audio_processing/aec3/aec3_common.h"
16 #include "rtc_base/checks.h"
17 
18 namespace webrtc {
19 
RenderBuffer(Aec3Optimization optimization,size_t num_bands,size_t num_partitions,const std::vector<size_t> num_ffts_for_spectral_sums)20 RenderBuffer::RenderBuffer(Aec3Optimization optimization,
21                            size_t num_bands,
22                            size_t num_partitions,
23                            const std::vector<size_t> num_ffts_for_spectral_sums)
24     : optimization_(optimization),
25       fft_buffer_(num_partitions),
26       spectrum_buffer_(num_partitions, std::array<float, kFftLengthBy2Plus1>()),
27       spectral_sums_(num_ffts_for_spectral_sums.size(),
28                      std::array<float, kFftLengthBy2Plus1>()),
29       last_block_(num_bands, std::vector<float>(kBlockSize, 0.f)),
30       fft_() {
31   // Current implementation only allows a maximum of one spectral sum lengths.
32   RTC_DCHECK_EQ(1, num_ffts_for_spectral_sums.size());
33   spectral_sums_length_ = num_ffts_for_spectral_sums[0];
34   RTC_DCHECK_GE(fft_buffer_.size(), spectral_sums_length_);
35 
36   Clear();
37 }
38 
39 RenderBuffer::~RenderBuffer() = default;
40 
Clear()41 void RenderBuffer::Clear() {
42   position_ = 0;
43   for (auto& sum : spectral_sums_) {
44     sum.fill(0.f);
45   }
46 
47   for (auto& spectrum : spectrum_buffer_) {
48     spectrum.fill(0.f);
49   }
50 
51   for (auto& fft : fft_buffer_) {
52     fft.Clear();
53   }
54 
55   for (auto& b : last_block_) {
56     std::fill(b.begin(), b.end(), 0.f);
57   }
58 }
59 
Insert(const std::vector<std::vector<float>> & block)60 void RenderBuffer::Insert(const std::vector<std::vector<float>>& block) {
61   // Compute the FFT of the data in the lowest band.
62   FftData X;
63   fft_.PaddedFft(block[0], last_block_[0], &X);
64 
65   // Copy the last render frame.
66   RTC_DCHECK_EQ(last_block_.size(), block.size());
67   for (size_t k = 0; k < block.size(); ++k) {
68     RTC_DCHECK_EQ(last_block_[k].size(), block[k].size());
69     std::copy(block[k].begin(), block[k].end(), last_block_[k].begin());
70   }
71 
72   // Insert X into the buffer.
73   position_ = position_ > 0 ? position_ - 1 : fft_buffer_.size() - 1;
74   fft_buffer_[position_].Assign(X);
75 
76   // Compute and insert the spectrum for the FFT into the spectrum buffer.
77   X.Spectrum(optimization_, &spectrum_buffer_[position_]);
78 
79   // Pre-compute and cache the spectral sums.
80   std::copy(spectrum_buffer_[position_].begin(),
81             spectrum_buffer_[position_].end(), spectral_sums_[0].begin());
82   size_t position = (position_ + 1) % fft_buffer_.size();
83   for (size_t j = 1; j < spectral_sums_length_; ++j) {
84     const std::array<float, kFftLengthBy2Plus1>& spectrum =
85         spectrum_buffer_[position];
86 
87     for (size_t k = 0; k < spectral_sums_[0].size(); ++k) {
88       spectral_sums_[0][k] += spectrum[k];
89     }
90 
91     position = position < (fft_buffer_.size() - 1) ? position + 1 : 0;
92   }
93 }
94 
95 }  // namespace webrtc
96