blob: 3897d947e1a39a00f02cbb6661296065c331d609 [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();
peahdebaa442017-05-03 05:39:09 -070058 G_shadow_.HandleEchoPathChange();
peah522d71b2017-02-23 05:16:26 -080059 }
60}
61
peahcf02cf12017-04-05 14:18:07 -070062void Subtractor::Process(const RenderBuffer& render_buffer,
peah522d71b2017-02-23 05:16:26 -080063 const rtc::ArrayView<const float> capture,
64 const RenderSignalAnalyzer& render_signal_analyzer,
peah86afe9d2017-04-06 15:45:32 -070065 const AecState& aec_state,
peah522d71b2017-02-23 05:16:26 -080066 SubtractorOutput* output) {
67 RTC_DCHECK_EQ(kBlockSize, capture.size());
68 rtc::ArrayView<const float> y = capture;
peah522d71b2017-02-23 05:16:26 -080069 FftData& E_main = output->E_main;
peah86afe9d2017-04-06 15:45:32 -070070 FftData E_shadow;
peah522d71b2017-02-23 05:16:26 -080071 std::array<float, kBlockSize>& e_main = output->e_main;
72 std::array<float, kBlockSize>& e_shadow = output->e_shadow;
73
74 FftData S;
75 FftData& G = S;
76
peah86afe9d2017-04-06 15:45:32 -070077 // Form the output of the main filter.
78 main_filter_.Filter(render_buffer, &S);
79 PredictionError(fft_, S, y, &e_main, &E_main);
peah522d71b2017-02-23 05:16:26 -080080
peah86afe9d2017-04-06 15:45:32 -070081 // Form the output of the shadow filter.
82 shadow_filter_.Filter(render_buffer, &S);
83 PredictionError(fft_, S, y, &e_shadow, &E_shadow);
peah522d71b2017-02-23 05:16:26 -080084
85 // Compute spectra for future use.
86 E_main.Spectrum(optimization_, &output->E2_main);
87 E_shadow.Spectrum(optimization_, &output->E2_shadow);
88
89 // Update the main filter.
peah86afe9d2017-04-06 15:45:32 -070090 G_main_.Compute(render_buffer, render_signal_analyzer, *output, main_filter_,
91 aec_state.SaturatedCapture(), &G);
92 main_filter_.Adapt(render_buffer, G);
peah522d71b2017-02-23 05:16:26 -080093 data_dumper_->DumpRaw("aec3_subtractor_G_main", G.re);
94 data_dumper_->DumpRaw("aec3_subtractor_G_main", G.im);
95
96 // Update the shadow filter.
peah86afe9d2017-04-06 15:45:32 -070097 G_shadow_.Compute(render_buffer, render_signal_analyzer, E_shadow,
98 shadow_filter_.SizePartitions(),
99 aec_state.SaturatedCapture(), &G);
100 shadow_filter_.Adapt(render_buffer, G);
101
peah522d71b2017-02-23 05:16:26 -0800102 data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.re);
103 data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.im);
104
105 main_filter_.DumpFilter("aec3_subtractor_H_main");
106 shadow_filter_.DumpFilter("aec3_subtractor_H_shadow");
107}
108
109} // namespace webrtc