niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 1 | /* |
bjornv@webrtc.org | 0c6f931 | 2012-01-30 09:39:08 +0000 | [diff] [blame] | 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 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 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #ifndef MODULES_AUDIO_PROCESSING_ECHO_CANCELLATION_IMPL_H_ |
| 12 | #define MODULES_AUDIO_PROCESSING_ECHO_CANCELLATION_IMPL_H_ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 13 | |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 14 | #include <stddef.h> |
kwiberg | 88788ad | 2016-02-19 07:04:49 -0800 | [diff] [blame] | 15 | #include <memory> |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 16 | #include <string> |
terelius | 85fa7d5 | 2016-03-24 01:51:52 -0700 | [diff] [blame] | 17 | #include <vector> |
kwiberg | 88788ad | 2016-02-19 07:04:49 -0800 | [diff] [blame] | 18 | |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 19 | #include "api/array_view.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 20 | #include "modules/audio_processing/include/audio_processing.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame^] | 21 | #include "rtc_base/constructor_magic.h" |
| 22 | #include "rtc_base/critical_section.h" |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 23 | #include "rtc_base/thread_annotations.h" |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 24 | |
| 25 | namespace webrtc { |
andrew@webrtc.org | 61e596f | 2013-07-25 18:28:29 +0000 | [diff] [blame] | 26 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 27 | class AudioBuffer; |
| 28 | |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 29 | // The acoustic echo cancellation (AEC) component provides better performance |
| 30 | // than AECM but also requires more processing power and is dependent on delay |
| 31 | // stability and reporting accuracy. As such it is well-suited and recommended |
| 32 | // for PC and IP phone applications. |
| 33 | class EchoCancellationImpl { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 34 | public: |
Sam Zackrisson | 7f4dfa4 | 2018-11-01 08:59:29 +0100 | [diff] [blame] | 35 | explicit EchoCancellationImpl(); |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 36 | ~EchoCancellationImpl(); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 37 | |
peah | 764e364 | 2016-10-22 05:04:30 -0700 | [diff] [blame] | 38 | void ProcessRenderAudio(rtc::ArrayView<const float> packed_render_audio); |
peah | b58a158 | 2016-03-15 09:34:24 -0700 | [diff] [blame] | 39 | int ProcessCaptureAudio(AudioBuffer* audio, int stream_delay_ms); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 40 | |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 41 | int Enable(bool enable); |
| 42 | bool is_enabled() const; |
| 43 | |
| 44 | // Differences in clock speed on the primary and reverse streams can impact |
| 45 | // the AEC performance. On the client-side, this could be seen when different |
| 46 | // render and capture devices are used, particularly with webcams. |
| 47 | // |
| 48 | // This enables a compensation mechanism, and requires that |
| 49 | // set_stream_drift_samples() be called. |
| 50 | int enable_drift_compensation(bool enable); |
| 51 | bool is_drift_compensation_enabled() const; |
| 52 | |
| 53 | // Sets the difference between the number of samples rendered and captured by |
| 54 | // the audio devices since the last call to |ProcessStream()|. Must be called |
| 55 | // if drift compensation is enabled, prior to |ProcessStream()|. |
| 56 | void set_stream_drift_samples(int drift); |
| 57 | int stream_drift_samples() const; |
| 58 | |
| 59 | enum SuppressionLevel { |
| 60 | kLowSuppression, |
| 61 | kModerateSuppression, |
| 62 | kHighSuppression |
| 63 | }; |
| 64 | |
| 65 | // Sets the aggressiveness of the suppressor. A higher level trades off |
| 66 | // double-talk performance for increased echo suppression. |
| 67 | int set_suppression_level(SuppressionLevel level); |
| 68 | SuppressionLevel suppression_level() const; |
| 69 | |
| 70 | // Returns false if the current frame almost certainly contains no echo |
| 71 | // and true if it _might_ contain echo. |
| 72 | bool stream_has_echo() const; |
| 73 | |
| 74 | // Enables the computation of various echo metrics. These are obtained |
| 75 | // through |GetMetrics()|. |
| 76 | int enable_metrics(bool enable); |
| 77 | bool are_metrics_enabled() const; |
| 78 | |
| 79 | // Each statistic is reported in dB. |
| 80 | // P_far: Far-end (render) signal power. |
| 81 | // P_echo: Near-end (capture) echo signal power. |
| 82 | // P_out: Signal power at the output of the AEC. |
| 83 | // P_a: Internal signal power at the point before the AEC's non-linear |
| 84 | // processor. |
| 85 | struct Metrics { |
Sam Zackrisson | 2812763 | 2018-11-01 11:37:15 +0100 | [diff] [blame] | 86 | struct Statistic { |
| 87 | int instant = 0; // Instantaneous value. |
| 88 | int average = 0; // Long-term average. |
| 89 | int maximum = 0; // Long-term maximum. |
| 90 | int minimum = 0; // Long-term minimum. |
| 91 | }; |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 92 | // RERL = ERL + ERLE |
Sam Zackrisson | 2812763 | 2018-11-01 11:37:15 +0100 | [diff] [blame] | 93 | Statistic residual_echo_return_loss; |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 94 | |
| 95 | // ERL = 10log_10(P_far / P_echo) |
Sam Zackrisson | 2812763 | 2018-11-01 11:37:15 +0100 | [diff] [blame] | 96 | Statistic echo_return_loss; |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 97 | |
| 98 | // ERLE = 10log_10(P_echo / P_out) |
Sam Zackrisson | 2812763 | 2018-11-01 11:37:15 +0100 | [diff] [blame] | 99 | Statistic echo_return_loss_enhancement; |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 100 | |
| 101 | // (Pre non-linear processing suppression) A_NLP = 10log_10(P_echo / P_a) |
Sam Zackrisson | 2812763 | 2018-11-01 11:37:15 +0100 | [diff] [blame] | 102 | Statistic a_nlp; |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 103 | |
| 104 | // Fraction of time that the AEC linear filter is divergent, in a 1-second |
| 105 | // non-overlapped aggregation window. |
| 106 | float divergent_filter_fraction; |
| 107 | }; |
| 108 | |
Sam Zackrisson | cdf0e6d | 2018-09-17 11:05:17 +0200 | [diff] [blame] | 109 | // Provides various statistics about the AEC. |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 110 | int GetMetrics(Metrics* metrics); |
| 111 | |
| 112 | // Enables computation and logging of delay values. Statistics are obtained |
| 113 | // through |GetDelayMetrics()|. |
| 114 | int enable_delay_logging(bool enable); |
| 115 | bool is_delay_logging_enabled() const; |
| 116 | |
Sam Zackrisson | cdf0e6d | 2018-09-17 11:05:17 +0200 | [diff] [blame] | 117 | // Provides delay metrics. |
saza | be490b2 | 2018-10-03 17:03:13 +0200 | [diff] [blame] | 118 | // The delay metrics consists of the delay |median| and the delay standard |
| 119 | // deviation |std|. It also consists of the fraction of delay estimates |
| 120 | // |fraction_poor_delays| that can make the echo cancellation perform poorly. |
| 121 | // The values are aggregated until the first call to |GetDelayMetrics()| and |
| 122 | // afterwards aggregated and updated every second. |
| 123 | // Note that if there are several clients pulling metrics from |
| 124 | // |GetDelayMetrics()| during a session the first call from any of them will |
| 125 | // change to one second aggregation window for all. |
| 126 | int GetDelayMetrics(int* median, int* std); |
| 127 | int GetDelayMetrics(int* median, int* std, float* fraction_poor_delays); |
| 128 | |
| 129 | // Returns a pointer to the low level AEC component. In case of multiple |
| 130 | // channels, the pointer to the first one is returned. A NULL pointer is |
| 131 | // returned when the AEC component is disabled or has not been initialized |
| 132 | // successfully. |
| 133 | struct AecCore* aec_core() const; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 134 | |
peah | b58a158 | 2016-03-15 09:34:24 -0700 | [diff] [blame] | 135 | void Initialize(int sample_rate_hz, |
| 136 | size_t num_reverse_channels_, |
| 137 | size_t num_output_channels_, |
| 138 | size_t num_proc_channels_); |
peah | 88ac853 | 2016-09-12 16:47:25 -0700 | [diff] [blame] | 139 | void SetExtraOptions(const webrtc::Config& config); |
Minyue | 13b96ba | 2015-10-03 00:39:14 +0200 | [diff] [blame] | 140 | bool is_delay_agnostic_enabled() const; |
| 141 | bool is_extended_filter_enabled() const; |
peah | 7789fe7 | 2016-04-15 01:19:44 -0700 | [diff] [blame] | 142 | std::string GetExperimentsDescription(); |
peah | 0332c2d | 2016-04-15 11:23:33 -0700 | [diff] [blame] | 143 | bool is_refined_adaptive_filter_enabled() const; |
Minyue | 13b96ba | 2015-10-03 00:39:14 +0200 | [diff] [blame] | 144 | |
peah | 20028c4 | 2016-03-04 11:50:54 -0800 | [diff] [blame] | 145 | // Returns the system delay of the first AEC component. |
| 146 | int GetSystemDelayInSamples() const; |
| 147 | |
peah | 764e364 | 2016-10-22 05:04:30 -0700 | [diff] [blame] | 148 | static void PackRenderAudioBuffer(const AudioBuffer* audio, |
| 149 | size_t num_output_channels, |
| 150 | size_t num_channels, |
| 151 | std::vector<float>* packed_buffer); |
| 152 | static size_t NumCancellersRequired(size_t num_output_channels, |
| 153 | size_t num_reverse_channels); |
| 154 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 155 | private: |
peah | b624d8c | 2016-03-05 03:01:14 -0800 | [diff] [blame] | 156 | class Canceller; |
peah | b58a158 | 2016-03-15 09:34:24 -0700 | [diff] [blame] | 157 | struct StreamProperties; |
peah | b624d8c | 2016-03-05 03:01:14 -0800 | [diff] [blame] | 158 | |
peah | fa6228e | 2015-11-16 16:27:42 -0800 | [diff] [blame] | 159 | void AllocateRenderQueue(); |
peah | b624d8c | 2016-03-05 03:01:14 -0800 | [diff] [blame] | 160 | int Configure(); |
peah | fa6228e | 2015-11-16 16:27:42 -0800 | [diff] [blame] | 161 | |
peah | b624d8c | 2016-03-05 03:01:14 -0800 | [diff] [blame] | 162 | bool enabled_ = false; |
Sam Zackrisson | 7f4dfa4 | 2018-11-01 08:59:29 +0100 | [diff] [blame] | 163 | bool drift_compensation_enabled_; |
| 164 | bool metrics_enabled_; |
| 165 | SuppressionLevel suppression_level_; |
| 166 | int stream_drift_samples_; |
| 167 | bool was_stream_drift_set_; |
| 168 | bool stream_has_echo_; |
| 169 | bool delay_logging_enabled_; |
| 170 | bool extended_filter_enabled_; |
| 171 | bool delay_agnostic_enabled_; |
| 172 | bool refined_adaptive_filter_enabled_ = false; |
peah | df3efa8 | 2015-11-28 12:35:15 -0800 | [diff] [blame] | 173 | |
Per Åhgren | 1155646 | 2017-12-22 16:13:57 +0100 | [diff] [blame] | 174 | // Only active on Chrome OS devices. |
Sam Zackrisson | 7f4dfa4 | 2018-11-01 08:59:29 +0100 | [diff] [blame] | 175 | const bool enforce_zero_stream_delay_; |
Per Åhgren | 1155646 | 2017-12-22 16:13:57 +0100 | [diff] [blame] | 176 | |
peah | b624d8c | 2016-03-05 03:01:14 -0800 | [diff] [blame] | 177 | std::vector<std::unique_ptr<Canceller>> cancellers_; |
peah | b58a158 | 2016-03-15 09:34:24 -0700 | [diff] [blame] | 178 | std::unique_ptr<StreamProperties> stream_properties_; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 179 | }; |
andrew@webrtc.org | 61e596f | 2013-07-25 18:28:29 +0000 | [diff] [blame] | 180 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 181 | } // namespace webrtc |
| 182 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 183 | #endif // MODULES_AUDIO_PROCESSING_ECHO_CANCELLATION_IMPL_H_ |