blob: 4b462238e2877a7159083a752b7bcd070cef279c [file] [log] [blame]
peah522d71b2017-02-23 05:16:26 -08001/*
2 * Copyright (c) 2017 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 "webrtc/modules/audio_processing/aec3/subtractor.h"
12
13#include <algorithm>
14
15#include "webrtc/base/array_view.h"
16#include "webrtc/base/checks.h"
17#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
18
19namespace webrtc {
20
21namespace {
22
peah86afe9d2017-04-06 15:45:32 -070023void PredictionError(const Aec3Fft& fft,
24 const FftData& S,
25 rtc::ArrayView<const float> y,
26 std::array<float, kBlockSize>* e,
27 FftData* E) {
peah522d71b2017-02-23 05:16:26 -080028 std::array<float, kFftLength> s;
29 fft.Ifft(S, &s);
30 constexpr float kScale = 1.0f / kFftLengthBy2;
31 std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e->begin(),
32 [&](float a, float b) { return a - b * kScale; });
33 std::for_each(e->begin(), e->end(), [](float& a) {
34 a = std::max(std::min(a, 32767.0f), -32768.0f);
35 });
36 fft.ZeroPaddedFft(*e, E);
37}
38} // namespace
39
peah522d71b2017-02-23 05:16:26 -080040Subtractor::Subtractor(ApmDataDumper* data_dumper,
41 Aec3Optimization optimization)
aleloi88b82b52017-02-23 06:27:03 -080042 : fft_(),
43 data_dumper_(data_dumper),
peah522d71b2017-02-23 05:16:26 -080044 optimization_(optimization),
peah86afe9d2017-04-06 15:45:32 -070045 main_filter_(kAdaptiveFilterLength, optimization, data_dumper_),
46 shadow_filter_(kAdaptiveFilterLength, optimization, data_dumper_) {
peah522d71b2017-02-23 05:16:26 -080047 RTC_DCHECK(data_dumper_);
48}
49
50Subtractor::~Subtractor() {}
51
52void Subtractor::HandleEchoPathChange(
53 const EchoPathVariability& echo_path_variability) {
54 if (echo_path_variability.delay_change) {
55 main_filter_.HandleEchoPathChange();
56 shadow_filter_.HandleEchoPathChange();
57 G_main_.HandleEchoPathChange();
58 }
59}
60
peahcf02cf12017-04-05 14:18:07 -070061void Subtractor::Process(const RenderBuffer& render_buffer,
peah522d71b2017-02-23 05:16:26 -080062 const rtc::ArrayView<const float> capture,
63 const RenderSignalAnalyzer& render_signal_analyzer,
peah86afe9d2017-04-06 15:45:32 -070064 const AecState& aec_state,
peah522d71b2017-02-23 05:16:26 -080065 SubtractorOutput* output) {
66 RTC_DCHECK_EQ(kBlockSize, capture.size());
67 rtc::ArrayView<const float> y = capture;
peah522d71b2017-02-23 05:16:26 -080068 FftData& E_main = output->E_main;
peah86afe9d2017-04-06 15:45:32 -070069 FftData E_shadow;
peah522d71b2017-02-23 05:16:26 -080070 std::array<float, kBlockSize>& e_main = output->e_main;
71 std::array<float, kBlockSize>& e_shadow = output->e_shadow;
72
73 FftData S;
74 FftData& G = S;
75
peah86afe9d2017-04-06 15:45:32 -070076 // Form the output of the main filter.
77 main_filter_.Filter(render_buffer, &S);
78 PredictionError(fft_, S, y, &e_main, &E_main);
peah522d71b2017-02-23 05:16:26 -080079
peah86afe9d2017-04-06 15:45:32 -070080 // Form the output of the shadow filter.
81 shadow_filter_.Filter(render_buffer, &S);
82 PredictionError(fft_, S, y, &e_shadow, &E_shadow);
peah522d71b2017-02-23 05:16:26 -080083
84 // Compute spectra for future use.
85 E_main.Spectrum(optimization_, &output->E2_main);
86 E_shadow.Spectrum(optimization_, &output->E2_shadow);
87
88 // Update the main filter.
peah86afe9d2017-04-06 15:45:32 -070089 G_main_.Compute(render_buffer, render_signal_analyzer, *output, main_filter_,
90 aec_state.SaturatedCapture(), &G);
91 main_filter_.Adapt(render_buffer, G);
peah522d71b2017-02-23 05:16:26 -080092 data_dumper_->DumpRaw("aec3_subtractor_G_main", G.re);
93 data_dumper_->DumpRaw("aec3_subtractor_G_main", G.im);
94
95 // Update the shadow filter.
peah86afe9d2017-04-06 15:45:32 -070096 G_shadow_.Compute(render_buffer, render_signal_analyzer, E_shadow,
97 shadow_filter_.SizePartitions(),
98 aec_state.SaturatedCapture(), &G);
99 shadow_filter_.Adapt(render_buffer, G);
100
peah522d71b2017-02-23 05:16:26 -0800101 data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.re);
102 data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.im);
103
104 main_filter_.DumpFilter("aec3_subtractor_H_main");
105 shadow_filter_.DumpFilter("aec3_subtractor_H_shadow");
106}
107
108} // namespace webrtc