blob: c5341080b4338c23975fbcea62516e093d7e8fbe [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>
Yves Gerey988cc082018-10-23 12:03:01 +020015#include <utility>
16#include <vector>
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020017
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020018#include "api/array_view.h"
Sam Zackrissonf3f61592019-09-05 11:30:49 +020019#include "modules/audio_processing/aec3/block_buffer.h"
20#include "modules/audio_processing/aec3/spectrum_buffer.h"
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020021#include "modules/audio_processing/aec3/stationarity_estimator.h"
22
23namespace webrtc {
24
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +020025EchoAudibility::EchoAudibility(bool use_render_stationarity_at_init)
26 : use_render_stationarity_at_init_(use_render_stationarity_at_init) {
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020027 Reset();
28}
29
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +020030EchoAudibility::~EchoAudibility() = default;
31
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020032void EchoAudibility::Update(
33 const RenderBuffer& render_buffer,
34 rtc::ArrayView<const float> render_reverb_contribution_spectrum,
35 int delay_blocks,
36 bool external_delay_seen) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020037 UpdateRenderNoiseEstimator(render_buffer.GetSpectrumBuffer(),
38 render_buffer.GetBlockBuffer(),
39 external_delay_seen);
Jesús de Vicente Peña95581922018-04-30 08:37:57 +020040
Jesús de Vicente Peña836a7a22018-08-31 15:03:04 +020041 if (external_delay_seen || use_render_stationarity_at_init_) {
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020042 UpdateRenderStationarityFlags(
43 render_buffer, render_reverb_contribution_spectrum, delay_blocks);
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020044 }
45}
46
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020047void EchoAudibility::Reset() {
48 render_stationarity_.Reset();
49 non_zero_render_seen_ = false;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020050 render_spectrum_write_prev_ = absl::nullopt;
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020051}
52
53void EchoAudibility::UpdateRenderStationarityFlags(
54 const RenderBuffer& render_buffer,
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020055 rtc::ArrayView<const float> render_reverb_contribution_spectrum,
56 int delay_blocks) {
Sam Zackrissonf3f61592019-09-05 11:30:49 +020057 const SpectrumBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer();
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020058 int idx_at_delay =
59 spectrum_buffer.OffsetIndex(spectrum_buffer.read, delay_blocks);
60
61 int num_lookahead = render_buffer.Headroom() - delay_blocks + 1;
62 num_lookahead = std::max(0, num_lookahead);
63
Jesús de Vicente Peñac98849c2018-10-22 11:41:05 +020064 render_stationarity_.UpdateStationarityFlags(
65 spectrum_buffer, render_reverb_contribution_spectrum, idx_at_delay,
66 num_lookahead);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020067}
68
69void EchoAudibility::UpdateRenderNoiseEstimator(
Sam Zackrissonf3f61592019-09-05 11:30:49 +020070 const SpectrumBuffer& spectrum_buffer,
71 const BlockBuffer& block_buffer,
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020072 bool external_delay_seen) {
73 if (!render_spectrum_write_prev_) {
74 render_spectrum_write_prev_ = spectrum_buffer.write;
75 render_block_write_prev_ = block_buffer.write;
76 return;
77 }
78 int render_spectrum_write_current = spectrum_buffer.write;
79 if (!non_zero_render_seen_ && !external_delay_seen) {
80 non_zero_render_seen_ = !IsRenderTooLow(block_buffer);
81 }
82 if (non_zero_render_seen_) {
83 for (int idx = render_spectrum_write_prev_.value();
84 idx != render_spectrum_write_current;
85 idx = spectrum_buffer.DecIndex(idx)) {
Sam Zackrissona81c09d2019-09-05 09:35:10 +020086 render_stationarity_.UpdateNoiseEstimator(
87 spectrum_buffer.buffer[idx][/*channel=*/0]);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020088 }
89 }
90 render_spectrum_write_prev_ = render_spectrum_write_current;
91}
92
Sam Zackrissonf3f61592019-09-05 11:30:49 +020093bool EchoAudibility::IsRenderTooLow(const BlockBuffer& block_buffer) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020094 bool too_low = false;
95 const int render_block_write_current = block_buffer.write;
96 if (render_block_write_current == render_block_write_prev_) {
97 too_low = true;
98 } else {
99 for (int idx = render_block_write_prev_; idx != render_block_write_current;
100 idx = block_buffer.IncIndex(idx)) {
Per Åhgrence202a02019-09-02 17:01:19 +0200101 auto block = block_buffer.buffer[idx][0][0];
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +0200102 auto r = std::minmax_element(block.cbegin(), block.cend());
103 float max_abs = std::max(std::fabs(*r.first), std::fabs(*r.second));
104 if (max_abs < 10) {
105 too_low = true; // Discards all blocks if one of them is too low.
106 break;
107 }
108 }
109 }
110 render_block_write_prev_ = render_block_write_current;
111 return too_low;
112}
113
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200114} // namespace webrtc