AEC3: Update SpectrumBuffer API
- RenderBuffer::Spectrum() loses its channel argument, allowing for
greater flexibility in passing the multi-channel spectrum data into
functions.
- The FFT spectra lengths are made compile-time constant, rendering
some DCHECKs obsolete.
Bug: webrtc:10913
Change-Id: Ied0c50cf72d974cfef7279fd2b9c572d049b8b16
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/157104
Commit-Queue: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29528}
diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc
index c36cf6d..d35bed5 100644
--- a/modules/audio_processing/aec3/aec_state.cc
+++ b/modules/audio_processing/aec3/aec_state.cc
@@ -46,11 +46,11 @@
if (num_render_channels > 1) {
auto average_channels =
[](size_t num_render_channels,
- const std::vector<std::vector<float>>& spectrum_band_0,
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>>
+ spectrum_band_0,
rtc::ArrayView<float, kFftLengthBy2Plus1> render_power) {
std::fill(render_power.begin(), render_power.end(), 0.f);
for (size_t ch = 0; ch < num_render_channels; ++ch) {
- RTC_DCHECK_EQ(spectrum_band_0[ch].size(), kFftLengthBy2Plus1);
for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
render_power[k] += spectrum_band_0[ch][k];
}
@@ -231,9 +231,8 @@
subtractor_output_analyzer_.ConvergedFilters());
// TODO(bugs.webrtc.org/10913): Take all channels into account.
- const auto& X2 =
- render_buffer.Spectrum(delay_state_.MinDirectPathFilterDelay(),
- /*channel=*/0);
+ const auto& X2 = render_buffer.Spectrum(
+ delay_state_.MinDirectPathFilterDelay())[/*channel=*/0];
erl_estimator_.Update(subtractor_output_analyzer_.ConvergedFilters()[0], X2,
Y2[0]);
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index a05a389..b508c95 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -461,8 +461,8 @@
data_dumper_->DumpRaw("aec3_S2_linear", S2_linear[0]);
data_dumper_->DumpRaw("aec3_Y2", Y2[0]);
data_dumper_->DumpRaw(
- "aec3_X2", render_buffer->Spectrum(aec_state_.MinDirectPathFilterDelay(),
- /*channel=*/0));
+ "aec3_X2", render_buffer->Spectrum(
+ aec_state_.MinDirectPathFilterDelay())[/*channel=*/0]);
data_dumper_->DumpRaw("aec3_R2", R2[0]);
data_dumper_->DumpRaw("aec3_filter_delay",
aec_state_.MinDirectPathFilterDelay());
diff --git a/modules/audio_processing/aec3/erl_estimator.cc b/modules/audio_processing/aec3/erl_estimator.cc
index 85b1e02..4a0c441 100644
--- a/modules/audio_processing/aec3/erl_estimator.cc
+++ b/modules/audio_processing/aec3/erl_estimator.cc
@@ -38,11 +38,10 @@
blocks_since_reset_ = 0;
}
-void ErlEstimator::Update(bool converged_filter,
- rtc::ArrayView<const float> render_spectrum,
- rtc::ArrayView<const float> capture_spectrum) {
- RTC_DCHECK_EQ(kFftLengthBy2Plus1, render_spectrum.size());
- RTC_DCHECK_EQ(kFftLengthBy2Plus1, capture_spectrum.size());
+void ErlEstimator::Update(
+ bool converged_filter,
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> render_spectrum,
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> capture_spectrum) {
const auto& X2 = render_spectrum;
const auto& Y2 = capture_spectrum;
diff --git a/modules/audio_processing/aec3/erl_estimator.h b/modules/audio_processing/aec3/erl_estimator.h
index 2ca21df..25dc39c 100644
--- a/modules/audio_processing/aec3/erl_estimator.h
+++ b/modules/audio_processing/aec3/erl_estimator.h
@@ -32,8 +32,8 @@
// Updates the ERL estimate.
void Update(bool converged_filter,
- rtc::ArrayView<const float> render_spectrum,
- rtc::ArrayView<const float> capture_spectrum);
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> render_spectrum,
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> capture_spectrum);
// Returns the most recent ERL estimate.
const std::array<float, kFftLengthBy2Plus1>& Erl() const { return erl_; }
diff --git a/modules/audio_processing/aec3/mock/mock_render_delay_buffer.cc b/modules/audio_processing/aec3/mock/mock_render_delay_buffer.cc
index f721fd8..d7099b0 100644
--- a/modules/audio_processing/aec3/mock/mock_render_delay_buffer.cc
+++ b/modules/audio_processing/aec3/mock/mock_render_delay_buffer.cc
@@ -19,9 +19,7 @@
NumBandsForRate(sample_rate_hz),
num_channels,
kBlockSize),
- spectrum_buffer_(block_buffer_.buffer.size(),
- num_channels,
- kFftLengthBy2Plus1),
+ spectrum_buffer_(block_buffer_.buffer.size(), num_channels),
fft_buffer_(block_buffer_.buffer.size(), num_channels),
render_buffer_(&block_buffer_, &spectrum_buffer_, &fft_buffer_),
downsampled_render_buffer_(GetDownSampledBufferSize(4, 4)) {
diff --git a/modules/audio_processing/aec3/render_buffer.h b/modules/audio_processing/aec3/render_buffer.h
index d44abd9..3422df3 100644
--- a/modules/audio_processing/aec3/render_buffer.h
+++ b/modules/audio_processing/aec3/render_buffer.h
@@ -44,11 +44,11 @@
}
// Get the spectrum from one of the FFTs in the buffer.
- rtc::ArrayView<const float> Spectrum(int buffer_offset_ffts,
- size_t channel) const {
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Spectrum(
+ int buffer_offset_ffts) const {
int position = spectrum_buffer_->OffsetIndex(spectrum_buffer_->read,
buffer_offset_ffts);
- return spectrum_buffer_->buffer[position][channel];
+ return spectrum_buffer_->buffer[position];
}
// Returns the circular fft buffer.
diff --git a/modules/audio_processing/aec3/render_buffer_unittest.cc b/modules/audio_processing/aec3/render_buffer_unittest.cc
index dca1e21..6981f6d 100644
--- a/modules/audio_processing/aec3/render_buffer_unittest.cc
+++ b/modules/audio_processing/aec3/render_buffer_unittest.cc
@@ -23,7 +23,7 @@
// Verifies the check for non-null fft buffer.
TEST(RenderBuffer, NullExternalFftBuffer) {
BlockBuffer block_buffer(10, 3, 1, kBlockSize);
- SpectrumBuffer spectrum_buffer(10, 1, kFftLengthBy2Plus1);
+ SpectrumBuffer spectrum_buffer(10, 1);
EXPECT_DEATH(RenderBuffer(&block_buffer, &spectrum_buffer, nullptr), "");
}
@@ -37,7 +37,7 @@
// Verifies the check for non-null block buffer.
TEST(RenderBuffer, NullExternalBlockBuffer) {
FftBuffer fft_buffer(10, 1);
- SpectrumBuffer spectrum_buffer(10, 1, kFftLengthBy2Plus1);
+ SpectrumBuffer spectrum_buffer(10, 1);
EXPECT_DEATH(RenderBuffer(nullptr, &spectrum_buffer, &fft_buffer), "");
}
diff --git a/modules/audio_processing/aec3/render_delay_buffer.cc b/modules/audio_processing/aec3/render_delay_buffer.cc
index 6eb32e4..14a6bd5 100644
--- a/modules/audio_processing/aec3/render_delay_buffer.cc
+++ b/modules/audio_processing/aec3/render_delay_buffer.cc
@@ -131,7 +131,7 @@
NumBandsForRate(sample_rate_hz),
num_render_channels,
kBlockSize),
- spectra_(blocks_.buffer.size(), num_render_channels, kFftLengthBy2Plus1),
+ spectra_(blocks_.buffer.size(), num_render_channels),
ffts_(blocks_.buffer.size(), num_render_channels),
delay_(config_.delay.default_delay),
echo_remover_buffer_(&blocks_, &spectra_, &ffts_),
diff --git a/modules/audio_processing/aec3/render_signal_analyzer.cc b/modules/audio_processing/aec3/render_signal_analyzer.cc
index 0b155f6..e64610e 100644
--- a/modules/audio_processing/aec3/render_signal_analyzer.cc
+++ b/modules/audio_processing/aec3/render_signal_analyzer.cc
@@ -38,13 +38,11 @@
std::array<size_t, kFftLengthBy2 - 1> channel_counters;
channel_counters.fill(0);
- for (size_t channel = 0; channel < render_buffer.Block(0)[0].size();
- ++channel) {
- rtc::ArrayView<const float> X2 =
- render_buffer.Spectrum(*delay_partitions, channel);
- RTC_DCHECK_EQ(kFftLengthBy2Plus1, X2.size());
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> X2 =
+ render_buffer.Spectrum(*delay_partitions);
+ for (size_t ch = 0; ch < X2.size(); ++ch) {
for (size_t k = 1; k < kFftLengthBy2; ++k) {
- if (X2[k] > 3 * std::max(X2[k - 1], X2[k + 1])) {
+ if (X2[ch][k] > 3 * std::max(X2[ch][k - 1], X2[ch][k + 1])) {
++channel_counters[k - 1];
}
}
@@ -72,7 +70,8 @@
render_buffer.Block(0);
float max_peak_level = 0.f;
for (size_t channel = 0; channel < x_latest[0].size(); ++channel) {
- const auto X2_latest = render_buffer.Spectrum(0, channel);
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> X2_latest =
+ render_buffer.Spectrum(0)[channel];
// Identify the spectral peak.
const int peak_bin =
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc
index 6a8a3f2..3846a79 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator.cc
@@ -244,21 +244,20 @@
void ResidualEchoEstimator::UpdateRenderNoisePower(
const RenderBuffer& render_buffer) {
std::array<float, kFftLengthBy2Plus1> render_power_data;
- rtc::ArrayView<const float> render_power;
- if (num_render_channels_ == 1) {
- render_power = render_buffer.Spectrum(0, /*channel=*/0);
- } else {
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> X2 =
+ render_buffer.Spectrum(0);
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> render_power =
+ X2[/*channel=*/0];
+ if (num_render_channels_ > 1) {
render_power_data.fill(0.f);
for (size_t ch = 0; ch < num_render_channels_; ++ch) {
- const auto& channel_power = render_buffer.Spectrum(0, ch);
- RTC_DCHECK_EQ(channel_power.size(), kFftLengthBy2Plus1);
+ const auto& channel_power = X2[ch];
for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
render_power_data[k] += channel_power[k];
}
}
render_power = render_power_data;
}
- RTC_DCHECK_EQ(render_power.size(), kFftLengthBy2Plus1);
// Estimate the stationary noise power in a minimum statistics manner.
for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
@@ -295,23 +294,20 @@
// Compute render power for the reverb.
std::array<float, kFftLengthBy2Plus1> render_power_data;
- rtc::ArrayView<const float> render_power;
- if (num_render_channels_ == 1) {
- render_power =
- render_buffer.Spectrum(first_reverb_partition, /*channel=*/0);
- } else {
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> X2 =
+ render_buffer.Spectrum(first_reverb_partition);
+ rtc::ArrayView<const float, kFftLengthBy2Plus1> render_power =
+ X2[/*channel=*/0];
+ if (num_render_channels_ > 1) {
render_power_data.fill(0.f);
for (size_t ch = 0; ch < num_render_channels_; ++ch) {
- const auto& channel_power =
- render_buffer.Spectrum(first_reverb_partition, ch);
- RTC_DCHECK_EQ(channel_power.size(), kFftLengthBy2Plus1);
+ const auto& channel_power = X2[ch];
for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
render_power_data[k] += channel_power[k];
}
}
render_power = render_power_data;
}
- RTC_DCHECK_EQ(render_power.size(), kFftLengthBy2Plus1);
// Update the reverb estimate.
if (reverb_type == ReverbType::kLinear) {
diff --git a/modules/audio_processing/aec3/spectrum_buffer.cc b/modules/audio_processing/aec3/spectrum_buffer.cc
index 8e7fed7..fe32ece 100644
--- a/modules/audio_processing/aec3/spectrum_buffer.cc
+++ b/modules/audio_processing/aec3/spectrum_buffer.cc
@@ -14,14 +14,10 @@
namespace webrtc {
-SpectrumBuffer::SpectrumBuffer(size_t size,
- size_t num_channels,
- size_t spectrum_length)
+SpectrumBuffer::SpectrumBuffer(size_t size, size_t num_channels)
: size(static_cast<int>(size)),
buffer(size,
- std::vector<std::vector<float>>(
- num_channels,
- std::vector<float>(spectrum_length, 0.f))) {
+ std::vector<std::array<float, kFftLengthBy2Plus1>>(num_channels)) {
for (auto& channel : buffer) {
for (auto& c : channel) {
std::fill(c.begin(), c.end(), 0.f);
diff --git a/modules/audio_processing/aec3/spectrum_buffer.h b/modules/audio_processing/aec3/spectrum_buffer.h
index d6c0ba0..51e1317 100644
--- a/modules/audio_processing/aec3/spectrum_buffer.h
+++ b/modules/audio_processing/aec3/spectrum_buffer.h
@@ -13,8 +13,10 @@
#include <stddef.h>
+#include <array>
#include <vector>
+#include "modules/audio_processing/aec3/aec3_common.h"
#include "rtc_base/checks.h"
namespace webrtc {
@@ -22,7 +24,7 @@
// Struct for bundling a circular buffer of one dimensional vector objects
// together with the read and write indices.
struct SpectrumBuffer {
- SpectrumBuffer(size_t size, size_t num_channels, size_t spectrum_length);
+ SpectrumBuffer(size_t size, size_t num_channels);
~SpectrumBuffer();
int IncIndex(int index) const {
@@ -50,7 +52,7 @@
void DecReadIndex() { read = DecIndex(read); }
const int size;
- std::vector<std::vector<std::vector<float>>> buffer;
+ std::vector<std::vector<std::array<float, kFftLengthBy2Plus1>>> buffer;
int write = 0;
int read = 0;
};
diff --git a/modules/audio_processing/aec3/stationarity_estimator.cc b/modules/audio_processing/aec3/stationarity_estimator.cc
index d0c3c9c..01628f3 100644
--- a/modules/audio_processing/aec3/stationarity_estimator.cc
+++ b/modules/audio_processing/aec3/stationarity_estimator.cc
@@ -12,7 +12,6 @@
#include <algorithm>
#include <array>
-#include <vector>
#include "api/array_view.h"
#include "modules/audio_processing/aec3/aec3_common.h"
@@ -45,7 +44,7 @@
// Update just the noise estimator. Usefull until the delay is known
void StationarityEstimator::UpdateNoiseEstimator(
- rtc::ArrayView<const std::vector<float>> spectrum) {
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> spectrum) {
noise_.Update(spectrum);
data_dumper_->DumpRaw("aec3_stationarity_noise_spectrum", noise_.Spectrum());
data_dumper_->DumpRaw("aec3_stationarity_is_block_stationary",
@@ -168,13 +167,12 @@
}
void StationarityEstimator::NoiseSpectrum::Update(
- rtc::ArrayView<const std::vector<float>> spectrum) {
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> spectrum) {
RTC_DCHECK_LE(1, spectrum[0].size());
const int num_render_channels = static_cast<int>(spectrum.size());
std::array<float, kFftLengthBy2Plus1> avg_spectrum_data;
rtc::ArrayView<const float> avg_spectrum;
- RTC_DCHECK_EQ(kFftLengthBy2Plus1, spectrum[0].size());
if (num_render_channels == 1) {
avg_spectrum = spectrum[0];
} else {
@@ -184,7 +182,6 @@
std::copy(spectrum[0].begin(), spectrum[0].end(),
avg_spectrum_data.begin());
for (int ch = 1; ch < num_render_channels; ++ch) {
- RTC_DCHECK_EQ(kFftLengthBy2Plus1, spectrum[ch].size());
for (size_t k = 1; k < kFftLengthBy2Plus1; ++k) {
avg_spectrum_data[k] += spectrum[ch][k];
}
diff --git a/modules/audio_processing/aec3/stationarity_estimator.h b/modules/audio_processing/aec3/stationarity_estimator.h
index 5860ef1..6f7ad40 100644
--- a/modules/audio_processing/aec3/stationarity_estimator.h
+++ b/modules/audio_processing/aec3/stationarity_estimator.h
@@ -15,7 +15,6 @@
#include <array>
#include <memory>
-#include <vector>
#include "api/array_view.h"
#include "modules/audio_processing/aec3/aec3_common.h" // kFftLengthBy2Plus1...
@@ -36,7 +35,8 @@
void Reset();
// Update just the noise estimator. Usefull until the delay is known
- void UpdateNoiseEstimator(rtc::ArrayView<const std::vector<float>> spectrum);
+ void UpdateNoiseEstimator(
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> spectrum);
// Update the flag indicating whether this current frame is stationary. For
// getting a more robust estimation, it looks at future and/or past frames.
@@ -86,7 +86,8 @@
void Reset();
// Update the noise power spectrum with a new frame.
- void Update(rtc::ArrayView<const std::vector<float>> spectrum);
+ void Update(
+ rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> spectrum);
// Get the noise estimation power spectrum.
rtc::ArrayView<const float> Spectrum() const { return noise_spectrum_; }