blob: 75d261a15ea3de25cfab981f756a09d31b1c07a3 [file] [log] [blame]
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +02001/*
2 * Copyright (c) 2018 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/echo_audibility.h"
12
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020013#include <algorithm>
14#include <cmath>
15
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020016#include "api/array_view.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020017#include "modules/audio_processing/aec3/aec3_common.h"
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020018#include "modules/audio_processing/aec3/matrix_buffer.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020019#include "modules/audio_processing/aec3/stationarity_estimator.h"
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020020#include "modules/audio_processing/aec3/vector_buffer.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020021
22namespace webrtc {
23
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +020024EchoAudibility::EchoAudibility(bool use_render_stationarity_at_init)
25 : use_render_stationarity_at_init_(use_render_stationarity_at_init) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020026 Reset();
27}
28
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020029EchoAudibility::~EchoAudibility() = default;
30
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020031void EchoAudibility::Update(
32 const RenderBuffer& render_buffer,
33 rtc::ArrayView<const float> render_reverb_contribution_spectrum,
34 int delay_blocks,
35 bool external_delay_seen) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020036 UpdateRenderNoiseEstimator(render_buffer.GetSpectrumBuffer(),
37 render_buffer.GetBlockBuffer(),
38 external_delay_seen);
Jesús de Vicente Peña95581922018-04-30 08:37:57 +020039
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +020040 if (external_delay_seen || use_render_stationarity_at_init_) {
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020041 UpdateRenderStationarityFlags(
42 render_buffer, render_reverb_contribution_spectrum, delay_blocks);
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020043 }
44}
45
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020046void EchoAudibility::Reset() {
47 render_stationarity_.Reset();
48 non_zero_render_seen_ = false;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020049 render_spectrum_write_prev_ = absl::nullopt;
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020050}
51
52void EchoAudibility::UpdateRenderStationarityFlags(
53 const RenderBuffer& render_buffer,
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020054 rtc::ArrayView<const float> render_reverb_contribution_spectrum,
55 int delay_blocks) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020056 const VectorBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer();
57 int idx_at_delay =
58 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
59
60 int num_lookahead = render_buffer.Headroom() - delay_blocks + 1;
61 num_lookahead = std::max(0, num_lookahead);
62
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020063 render_stationarity_.UpdateStationarityFlags(
64 spectrum_buffer, render_reverb_contribution_spectrum, idx_at_delay,
65 num_lookahead);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020066}
67
68void EchoAudibility::UpdateRenderNoiseEstimator(
69 const VectorBuffer& spectrum_buffer,
70 const MatrixBuffer& block_buffer,
71 bool external_delay_seen) {
72 if (!render_spectrum_write_prev_) {
73 render_spectrum_write_prev_ = spectrum_buffer.write;
74 render_block_write_prev_ = block_buffer.write;
75 return;
76 }
77 int render_spectrum_write_current = spectrum_buffer.write;
78 if (!non_zero_render_seen_ && !external_delay_seen) {
79 non_zero_render_seen_ = !IsRenderTooLow(block_buffer);
80 }
81 if (non_zero_render_seen_) {
82 for (int idx = render_spectrum_write_prev_.value();
83 idx != render_spectrum_write_current;
84 idx = spectrum_buffer.DecIndex(idx)) {
85 render_stationarity_.UpdateNoiseEstimator(spectrum_buffer.buffer[idx]);
86 }
87 }
88 render_spectrum_write_prev_ = render_spectrum_write_current;
89}
90
91bool EchoAudibility::IsRenderTooLow(const MatrixBuffer& block_buffer) {
92 bool too_low = false;
93 const int render_block_write_current = block_buffer.write;
94 if (render_block_write_current == render_block_write_prev_) {
95 too_low = true;
96 } else {
97 for (int idx = render_block_write_prev_; idx != render_block_write_current;
98 idx = block_buffer.IncIndex(idx)) {
99 auto block = block_buffer.buffer[idx][0];
100 auto r = std::minmax_element(block.cbegin(), block.cend());
101 float max_abs = std::max(std::fabs(*r.first), std::fabs(*r.second));
102 if (max_abs < 10) {
103 too_low = true; // Discards all blocks if one of them is too low.
104 break;
105 }
106 }
107 }
108 render_block_write_prev_ = render_block_write_current;
109 return too_low;
110}
111
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200112} // namespace webrtc