Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: webrtc/modules/audio_processing/level_controller/signal_classifier.cc

Issue 2090583002: New module for the adaptive level controlling functionality in the audio processing module (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Corrected the initial behavior for the peak level estimate, and ensured a nonzero minimum peak leveā€¦ Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 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/level_controller/signal_classifier.h"
12
13 #include <algorithm>
14 #include <numeric>
15 #include <vector>
16
17 #include "webrtc/base/array_view.h"
18 #include "webrtc/base/constructormagic.h"
19 #include "webrtc/modules/audio_processing/aec/aec_rdft.h"
20 #include "webrtc/modules/audio_processing/audio_buffer.h"
21 #include "webrtc/modules/audio_processing/level_controller/down_sampler.h"
22 #include "webrtc/modules/audio_processing/level_controller/noise_spectrum_estima tor.h"
23 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
24
25 namespace webrtc {
26 namespace {
27
28 void RemoveDcLevel(rtc::ArrayView<float> x) {
29 RTC_DCHECK_LT(0u, x.size());
30 float mean = std::accumulate(x.data(), x.data() + x.size(), 0.f);
31 mean /= x.size();
32
33 for (float& v : x) {
34 v -= mean;
35 }
36 }
37
38 void PowerSpectrum(rtc::ArrayView<const float> x,
39 rtc::ArrayView<float> spectrum) {
40 RTC_DCHECK_EQ(65u, spectrum.size());
41 RTC_DCHECK_EQ(128u, x.size());
42 float X[128];
43 std::copy(x.data(), x.data() + x.size(), X);
44 aec_rdft_forward_128(X);
45
46 float* X_p = X;
47 RTC_CHECK_EQ(X_p, &X[0]);
hlundin-webrtc 2016/06/27 11:21:17 Use DCHECK here and in the places below.
peah-webrtc 2016/06/27 22:51:50 Done.
48 spectrum[0] = (*X_p) * (*X_p);
49 ++X_p;
50 RTC_CHECK_EQ(X_p, &X[1]);
51 spectrum[64] = (*X_p) * (*X_p);
52 for (int k = 1; k < 64; ++k) {
53 ++X_p;
54 RTC_CHECK_EQ(X_p, &X[2 * k]);
55 spectrum[k] += (*X_p) * (*X_p);
hlundin-webrtc 2016/06/27 11:21:17 You are adding to an undefined value here. Use = i
peah-webrtc 2016/06/27 22:51:50 Great find!!!!! Done.
56 ++X_p;
57 RTC_CHECK_EQ(X_p, &X[2 * k + 1]);
58 spectrum[k] += (*X_p) * (*X_p);
59 }
60 }
61
62 void ClassifySignal(rtc::ArrayView<const float> signal_spectrum,
63 rtc::ArrayView<const float> noise_spectrum,
64 ApmDataDumper* data_dumper,
65 SignalClassifier::SignalType* signal_type) {
hlundin-webrtc 2016/06/27 11:21:17 Return the signal type instead of having it as an
peah-webrtc 2016/06/27 22:51:50 Done.
66 int num_stationary_bands = 0;
67 int num_highly_nonstationary_bands = 0;
68
69 // Detect stationary and highly nonstationary bands.
70 for (int k = 1; k < 40; k++) {
hlundin-webrtc 2016/06/27 11:21:17 size_t
peah-webrtc 2016/06/27 22:51:50 Done.
71 if (signal_spectrum[k] < 3 * noise_spectrum[k]) {
72 ++num_stationary_bands;
73 } else if (signal_spectrum[k] > 9 * noise_spectrum[k]) {
74 ++num_highly_nonstationary_bands;
75 }
76 }
77
78 // Use the detected number of bands to classify the overall signal
79 // stationarity.
80 if (num_stationary_bands > 20) {
81 *signal_type = SignalClassifier::SignalType::kStationary;
82 } else if (num_highly_nonstationary_bands > 15) {
83 *signal_type = SignalClassifier::SignalType::kHighlyNonStationary;
84 } else {
85 *signal_type = SignalClassifier::SignalType::kNonStationary;
86 }
87
88 data_dumper->DumpRaw("lc_num_stationary_bands", 1, &num_stationary_bands);
89 data_dumper->DumpRaw("lc_num_highly_nonstationary_bands", 1,
90 &num_highly_nonstationary_bands);
91 }
92
93 } // namespace
94
95 class FrameExtender {
hlundin-webrtc 2016/06/27 11:21:17 Why is this outside of the unnamed namespace?
peah-webrtc 2016/06/27 22:51:50 I think it needs to be outside of that for the rea
hlundin-webrtc 2016/06/28 11:29:01 Oh, I see. Then I think I would prefer to have it
peah-webrtc 2016/06/28 22:19:37 Done.
96 public:
97 FrameExtender(size_t frame_size, size_t extended_frame_size)
98 : x_old_(extended_frame_size - frame_size, 0.f) {}
99
100 void ExtendFrame(rtc::ArrayView<const float> x,
101 rtc::ArrayView<float> x_extended) {
102 RTC_DCHECK_EQ(x_old_.size() + x.size(), x_extended.size());
103 std::copy(x_old_.data(), x_old_.data() + x_old_.size(), x_extended.data());
104 std::copy(x.data(), x.data() + x.size(), x_extended.data() + x_old_.size());
105 std::copy(x_extended.data() + x_extended.size() - x_old_.size(),
106 x_extended.data() + x_extended.size(), x_old_.data());
107 }
108
109 private:
110 std::vector<float> x_old_;
111
112 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FrameExtender);
113 };
114
115 SignalClassifier::SignalClassifier(ApmDataDumper* data_dumper)
116 : data_dumper_(data_dumper) {
117 Initialize(AudioProcessing::kSampleRate48kHz);
118 }
119 SignalClassifier::~SignalClassifier() {}
120
121 void SignalClassifier::Initialize(int sample_rate_hz) {
122 aec_rdft_init();
123 down_sampler_.reset(new DownSampler(data_dumper_, sample_rate_hz));
124 frame_extender_.reset(new FrameExtender(80, 128));
125 noise_spectrum_estimator_.reset(new NoiseSpectrumEstimator(data_dumper_));
126 sample_rate_hz_ = sample_rate_hz;
127 initialization_frames_left_ = 2;
128 }
129
130 void SignalClassifier::Analyze(const AudioBuffer& audio,
131 SignalType* signal_type) {
132 // Compute the signal power spectrum.
hlundin-webrtc 2016/06/27 11:21:17 You may want to DCHECK some properties of the Audi
peah-webrtc 2016/06/27 22:51:50 That would make sense, but I think AudioBuffer doe
hlundin-webrtc 2016/06/28 11:29:01 Can't you just check that the number of samples in
peah-webrtc 2016/06/28 22:19:37 True! Good point! Done.
133 float downsampled_frame[80];
134 down_sampler_->DownSample(
135 rtc::ArrayView<const float>(audio.channels_const_f()[0],
136 audio.num_frames()),
137 downsampled_frame);
138 float extended_frame[128];
139 frame_extender_->ExtendFrame(downsampled_frame, extended_frame);
140 RemoveDcLevel(extended_frame);
141 float signal_spectrum[65];
142 PowerSpectrum(extended_frame, signal_spectrum);
143
144 // Classify the signal based on the estimate of the noise spectrum and the
145 // signal spectrum estimate.
146 ClassifySignal(signal_spectrum, noise_spectrum_estimator_->GetNoiseSpectrum(),
147 data_dumper_, signal_type);
148
149 // Update the noise spectrum based on the signal spectrum.
150 noise_spectrum_estimator_->Update(signal_spectrum,
151 initialization_frames_left_ > 0);
152
153 // Update the number of frames until a reliable signal spectrum is achieved.
154 initialization_frames_left_ = std::max(0, initialization_frames_left_ - 1);
155 }
156
157 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698