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}
This commit is contained in:
parent
c336dd1cb6
commit
98872dc556
@ -46,11 +46,11 @@ void ComputeAvgRenderReverb(
|
||||
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 @@ void AecState::Update(
|
||||
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]);
|
||||
|
||||
|
||||
@ -461,8 +461,8 @@ void EchoRemoverImpl::ProcessCapture(
|
||||
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());
|
||||
|
||||
@ -38,11 +38,10 @@ void ErlEstimator::Reset() {
|
||||
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;
|
||||
|
||||
|
||||
@ -32,8 +32,8 @@ class ErlEstimator {
|
||||
|
||||
// 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_; }
|
||||
|
||||
@ -19,9 +19,7 @@ MockRenderDelayBuffer::MockRenderDelayBuffer(int sample_rate_hz,
|
||||
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)) {
|
||||
|
||||
@ -44,11 +44,11 @@ class RenderBuffer {
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
@ -23,7 +23,7 @@ namespace webrtc {
|
||||
// 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 @@ TEST(RenderBuffer, NullExternalSpectrumBuffer) {
|
||||
// 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), "");
|
||||
}
|
||||
|
||||
|
||||
@ -131,7 +131,7 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
|
||||
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_),
|
||||
|
||||
@ -38,13 +38,11 @@ void IdentifySmallNarrowBandRegions(
|
||||
|
||||
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 @@ void IdentifyStrongNarrowBandComponent(const RenderBuffer& render_buffer,
|
||||
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 =
|
||||
|
||||
@ -244,21 +244,20 @@ void ResidualEchoEstimator::Reset() {
|
||||
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 @@ void ResidualEchoEstimator::AddReverb(
|
||||
|
||||
// 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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 @@ namespace webrtc {
|
||||
// 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 @@ struct SpectrumBuffer {
|
||||
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;
|
||||
};
|
||||
|
||||
@ -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 @@ void StationarityEstimator::Reset() {
|
||||
|
||||
// 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::Reset() {
|
||||
}
|
||||
|
||||
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 @@ void StationarityEstimator::NoiseSpectrum::Update(
|
||||
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];
|
||||
}
|
||||
|
||||
@ -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 @@ class StationarityEstimator {
|
||||
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 @@ class StationarityEstimator {
|
||||
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_; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user