blob: 6ae414e3cf5d4b4d7c039abe5cc6db4ddd6051f5 [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
Per Åhgren8718afb2019-10-15 10:31:35 +020032void EchoAudibility::Update(const RenderBuffer& render_buffer,
33 rtc::ArrayView<const float> average_reverb,
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_) {
Per Åhgren8718afb2019-10-15 10:31:35 +020041 UpdateRenderStationarityFlags(render_buffer, average_reverb, delay_blocks);
Jesús de Vicente Peñadc872b62018-04-25 16:11:42 +020042 }
43}
44
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020045void EchoAudibility::Reset() {
46 render_stationarity_.Reset();
47 non_zero_render_seen_ = false;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020048 render_spectrum_write_prev_ = absl::nullopt;
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020049}
50
51void EchoAudibility::UpdateRenderStationarityFlags(
52 const RenderBuffer& render_buffer,
Per Åhgren8718afb2019-10-15 10:31:35 +020053 rtc::ArrayView<const float> average_reverb,
54 int min_channel_delay_blocks) {
Sam Zackrissonf3f61592019-09-05 11:30:49 +020055 const SpectrumBuffer& spectrum_buffer = render_buffer.GetSpectrumBuffer();
Per Åhgren8718afb2019-10-15 10:31:35 +020056 int idx_at_delay = spectrum_buffer.OffsetIndex(spectrum_buffer.read,
57 min_channel_delay_blocks);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020058
Per Åhgren8718afb2019-10-15 10:31:35 +020059 int num_lookahead = render_buffer.Headroom() - min_channel_delay_blocks + 1;
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020060 num_lookahead = std::max(0, num_lookahead);
61
Per Åhgren8718afb2019-10-15 10:31:35 +020062 render_stationarity_.UpdateStationarityFlags(spectrum_buffer, average_reverb,
63 idx_at_delay, num_lookahead);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020064}
65
66void EchoAudibility::UpdateRenderNoiseEstimator(
Sam Zackrissonf3f61592019-09-05 11:30:49 +020067 const SpectrumBuffer& spectrum_buffer,
68 const BlockBuffer& block_buffer,
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020069 bool external_delay_seen) {
70 if (!render_spectrum_write_prev_) {
71 render_spectrum_write_prev_ = spectrum_buffer.write;
72 render_block_write_prev_ = block_buffer.write;
73 return;
74 }
75 int render_spectrum_write_current = spectrum_buffer.write;
76 if (!non_zero_render_seen_ && !external_delay_seen) {
77 non_zero_render_seen_ = !IsRenderTooLow(block_buffer);
78 }
79 if (non_zero_render_seen_) {
80 for (int idx = render_spectrum_write_prev_.value();
81 idx != render_spectrum_write_current;
82 idx = spectrum_buffer.DecIndex(idx)) {
Per Åhgren8718afb2019-10-15 10:31:35 +020083 render_stationarity_.UpdateNoiseEstimator(spectrum_buffer.buffer[idx]);
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020084 }
85 }
86 render_spectrum_write_prev_ = render_spectrum_write_current;
87}
88
Sam Zackrissonf3f61592019-09-05 11:30:49 +020089bool EchoAudibility::IsRenderTooLow(const BlockBuffer& block_buffer) {
Per Åhgren8718afb2019-10-15 10:31:35 +020090 const int num_render_channels =
Per Åhgrencf205192019-12-02 11:55:10 +010091 static_cast<int>(block_buffer.buffer[0][0].size());
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +020092 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)) {
Per Åhgren8718afb2019-10-15 10:31:35 +020099 float max_abs_over_channels = 0.f;
100 for (int ch = 0; ch < num_render_channels; ++ch) {
101 auto block = block_buffer.buffer[idx][0][ch];
102 auto r = std::minmax_element(block.cbegin(), block.cend());
103 float max_abs_channel =
104 std::max(std::fabs(*r.first), std::fabs(*r.second));
105 max_abs_over_channels =
106 std::max(max_abs_over_channels, max_abs_channel);
107 }
108 if (max_abs_over_channels < 10.f) {
Jesús de Vicente Peña2f2633d2018-05-02 09:47:22 +0200109 too_low = true; // Discards all blocks if one of them is too low.
110 break;
111 }
112 }
113 }
114 render_block_write_prev_ = render_block_write_current;
115 return too_low;
116}
117
Jesús de Vicente Peñad5cb4772018-04-25 13:58:45 +0200118} // namespace webrtc