blob: fa123de351e5449daaaba66f899a8e79a2108eea [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
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +020023EchoAudibility::EchoAudibility(bool use_render_stationarity_at_init)
24 : use_render_stationarity_at_init_(use_render_stationarity_at_init) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020025 Reset();
26}
27
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020028EchoAudibility::~EchoAudibility() = default;
29
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020030void EchoAudibility::Update(const RenderBuffer& render_buffer,
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020031 int delay_blocks,
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020032 bool external_delay_seen,
33 float reverb_decay) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020034 UpdateRenderNoiseEstimator(render_buffer.GetSpectrumBuffer(),
35 render_buffer.GetBlockBuffer(),
36 external_delay_seen);
Jesús de Vicente Peña95581922018-04-30 08:37:57 +020037
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +020038 if (external_delay_seen || use_render_stationarity_at_init_) {
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020039 UpdateRenderStationarityFlags(render_buffer, delay_blocks, reverb_decay);
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020040 }
41}
42
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020043void EchoAudibility::Reset() {
44 render_stationarity_.Reset();
45 non_zero_render_seen_ = false;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020046 render_spectrum_write_prev_ = absl::nullopt;
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020047}
48
49void EchoAudibility::UpdateRenderStationarityFlags(
50 const RenderBuffer& render_buffer,
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020051 int delay_blocks,
52 float reverb_decay) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020053 const VectorBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer();
54 int idx_at_delay =
55 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
56
57 int num_lookahead = render_buffer.Headroom() - delay_blocks + 1;
58 num_lookahead = std::max(0, num_lookahead);
59
60 render_stationarity_.UpdateStationarityFlags(spectrum_buffer, idx_at_delay,
Jesús de Vicente Peña075cb2b2018-06-13 15:13:55 +020061 num_lookahead, reverb_decay);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020062}
63
64void EchoAudibility::UpdateRenderNoiseEstimator(
65 const VectorBuffer& spectrum_buffer,
66 const MatrixBuffer& block_buffer,
67 bool external_delay_seen) {
68 if (!render_spectrum_write_prev_) {
69 render_spectrum_write_prev_ = spectrum_buffer.write;
70 render_block_write_prev_ = block_buffer.write;
71 return;
72 }
73 int render_spectrum_write_current = spectrum_buffer.write;
74 if (!non_zero_render_seen_ && !external_delay_seen) {
75 non_zero_render_seen_ = !IsRenderTooLow(block_buffer);
76 }
77 if (non_zero_render_seen_) {
78 for (int idx = render_spectrum_write_prev_.value();
79 idx != render_spectrum_write_current;
80 idx = spectrum_buffer.DecIndex(idx)) {
81 render_stationarity_.UpdateNoiseEstimator(spectrum_buffer.buffer[idx]);
82 }
83 }
84 render_spectrum_write_prev_ = render_spectrum_write_current;
85}
86
87bool EchoAudibility::IsRenderTooLow(const MatrixBuffer& block_buffer) {
88 bool too_low = false;
89 const int render_block_write_current = block_buffer.write;
90 if (render_block_write_current == render_block_write_prev_) {
91 too_low = true;
92 } else {
93 for (int idx = render_block_write_prev_; idx != render_block_write_current;
94 idx = block_buffer.IncIndex(idx)) {
95 auto block = block_buffer.buffer[idx][0];
96 auto r = std::minmax_element(block.cbegin(), block.cend());
97 float max_abs = std::max(std::fabs(*r.first), std::fabs(*r.second));
98 if (max_abs < 10) {
99 too_low = true; // Discards all blocks if one of them is too low.
100 break;
101 }
102 }
103 }
104 render_block_write_prev_ = render_block_write_current;
105 return too_low;
106}
107
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200108} // namespace webrtc