blob: a504cca4befbdbffe3a3677d62ecb142c395e728 [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ña075cb2b2018-06-13 15:13:55 +020031 bool external_delay_seen,
32 float reverb_decay) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020033 UpdateRenderNoiseEstimator(render_buffer.GetSpectrumBuffer(),
34 render_buffer.GetBlockBuffer(),
35 external_delay_seen);
Jesús de Vicente Peña95581922018-04-30 08:37:57 +020036
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020037 if (external_delay_seen) {
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020038 UpdateRenderStationarityFlags(render_buffer, delay_blocks, reverb_decay);
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020039 }
40}
41
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020042void EchoAudibility::Reset() {
43 render_stationarity_.Reset();
44 non_zero_render_seen_ = false;
45 render_spectrum_write_prev_ = rtc::nullopt;
46}
47
48void EchoAudibility::UpdateRenderStationarityFlags(
49 const RenderBuffer& render_buffer,
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020050 int delay_blocks,
51 float reverb_decay) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020052 const VectorBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer();
53 int idx_at_delay =
54 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
55
56 int num_lookahead = render_buffer.Headroom() - delay_blocks + 1;
57 num_lookahead = std::max(0, num_lookahead);
58
59 render_stationarity_.UpdateStationarityFlags(spectrum_buffer, idx_at_delay,
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020060 num_lookahead, reverb_decay);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020061}
62
63void EchoAudibility::UpdateRenderNoiseEstimator(
64 const VectorBuffer& spectrum_buffer,
65 const MatrixBuffer& block_buffer,
66 bool external_delay_seen) {
67 if (!render_spectrum_write_prev_) {
68 render_spectrum_write_prev_ = spectrum_buffer.write;
69 render_block_write_prev_ = block_buffer.write;
70 return;
71 }
72 int render_spectrum_write_current = spectrum_buffer.write;
73 if (!non_zero_render_seen_ && !external_delay_seen) {
74 non_zero_render_seen_ = !IsRenderTooLow(block_buffer);
75 }
76 if (non_zero_render_seen_) {
77 for (int idx = render_spectrum_write_prev_.value();
78 idx != render_spectrum_write_current;
79 idx = spectrum_buffer.DecIndex(idx)) {
80 render_stationarity_.UpdateNoiseEstimator(spectrum_buffer.buffer[idx]);
81 }
82 }
83 render_spectrum_write_prev_ = render_spectrum_write_current;
84}
85
86bool EchoAudibility::IsRenderTooLow(const MatrixBuffer& block_buffer) {
87 bool too_low = false;
88 const int render_block_write_current = block_buffer.write;
89 if (render_block_write_current == render_block_write_prev_) {
90 too_low = true;
91 } else {
92 for (int idx = render_block_write_prev_; idx != render_block_write_current;
93 idx = block_buffer.IncIndex(idx)) {
94 auto block = block_buffer.buffer[idx][0];
95 auto r = std::minmax_element(block.cbegin(), block.cend());
96 float max_abs = std::max(std::fabs(*r.first), std::fabs(*r.second));
97 if (max_abs < 10) {
98 too_low = true; // Discards all blocks if one of them is too low.
99 break;
100 }
101 }
102 }
103 render_block_write_prev_ = render_block_write_current;
104 return too_low;
105}
106
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200107} // namespace webrtc