blob: 68d2dd11e6cf06dc7c9a3f97273ad3419ae245a3 [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ñad5cb4772018-04-25 13:58:45 +020016#include "modules/audio_processing/aec3/aec3_common.h"
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020017#include "modules/audio_processing/aec3/matrix_buffer.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020018#include "modules/audio_processing/aec3/stationarity_estimator.h"
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020019#include "modules/audio_processing/aec3/vector_buffer.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020020
21namespace webrtc {
22
23EchoAudibility::EchoAudibility() {
24 Reset();
25}
26
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020027EchoAudibility::~EchoAudibility() = default;
28
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020029void EchoAudibility::Update(const RenderBuffer& render_buffer,
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020030 int delay_blocks,
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020031 bool external_delay_seen) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020032 UpdateRenderNoiseEstimator(render_buffer.GetSpectrumBuffer(),
33 render_buffer.GetBlockBuffer(),
34 external_delay_seen);
Jesús de Vicente Peña95581922018-04-30 08:37:57 +020035
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020036 if (external_delay_seen) {
Jesús de Vicente Peña95581922018-04-30 08:37:57 +020037 UpdateRenderStationarityFlags(render_buffer, delay_blocks);
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020038 }
39}
40
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020041void EchoAudibility::Reset() {
42 render_stationarity_.Reset();
43 non_zero_render_seen_ = false;
44 render_spectrum_write_prev_ = rtc::nullopt;
45}
46
47void EchoAudibility::UpdateRenderStationarityFlags(
48 const RenderBuffer& render_buffer,
49 int delay_blocks) {
50 const VectorBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer();
51 int idx_at_delay =
52 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
53
54 int num_lookahead = render_buffer.Headroom() - delay_blocks + 1;
55 num_lookahead = std::max(0, num_lookahead);
56
57 render_stationarity_.UpdateStationarityFlags(spectrum_buffer, idx_at_delay,
58 num_lookahead);
59}
60
61void EchoAudibility::UpdateRenderNoiseEstimator(
62 const VectorBuffer& spectrum_buffer,
63 const MatrixBuffer& block_buffer,
64 bool external_delay_seen) {
65 if (!render_spectrum_write_prev_) {
66 render_spectrum_write_prev_ = spectrum_buffer.write;
67 render_block_write_prev_ = block_buffer.write;
68 return;
69 }
70 int render_spectrum_write_current = spectrum_buffer.write;
71 if (!non_zero_render_seen_ && !external_delay_seen) {
72 non_zero_render_seen_ = !IsRenderTooLow(block_buffer);
73 }
74 if (non_zero_render_seen_) {
75 for (int idx = render_spectrum_write_prev_.value();
76 idx != render_spectrum_write_current;
77 idx = spectrum_buffer.DecIndex(idx)) {
78 render_stationarity_.UpdateNoiseEstimator(spectrum_buffer.buffer[idx]);
79 }
80 }
81 render_spectrum_write_prev_ = render_spectrum_write_current;
82}
83
84bool EchoAudibility::IsRenderTooLow(const MatrixBuffer& block_buffer) {
85 bool too_low = false;
86 const int render_block_write_current = block_buffer.write;
87 if (render_block_write_current == render_block_write_prev_) {
88 too_low = true;
89 } else {
90 for (int idx = render_block_write_prev_; idx != render_block_write_current;
91 idx = block_buffer.IncIndex(idx)) {
92 auto block = block_buffer.buffer[idx][0];
93 auto r = std::minmax_element(block.cbegin(), block.cend());
94 float max_abs = std::max(std::fabs(*r.first), std::fabs(*r.second));
95 if (max_abs < 10) {
96 too_low = true; // Discards all blocks if one of them is too low.
97 break;
98 }
99 }
100 }
101 render_block_write_prev_ = render_block_write_current;
102 return too_low;
103}
104
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200105} // namespace webrtc