Line data Source code
1 : /*
2 : * Copyright (c) 2012 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/noise_suppression_impl.h"
12 :
13 : #include "webrtc/base/constructormagic.h"
14 : #include "webrtc/modules/audio_processing/audio_buffer.h"
15 : #if defined(WEBRTC_NS_FLOAT)
16 : #include "webrtc/modules/audio_processing/ns/noise_suppression.h"
17 : #define NS_CREATE WebRtcNs_Create
18 : #define NS_FREE WebRtcNs_Free
19 : #define NS_INIT WebRtcNs_Init
20 : #define NS_SET_POLICY WebRtcNs_set_policy
21 : typedef NsHandle NsState;
22 : #elif defined(WEBRTC_NS_FIXED)
23 : #include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
24 : #define NS_CREATE WebRtcNsx_Create
25 : #define NS_FREE WebRtcNsx_Free
26 : #define NS_INIT WebRtcNsx_Init
27 : #define NS_SET_POLICY WebRtcNsx_set_policy
28 : typedef NsxHandle NsState;
29 : #endif
30 :
31 : namespace webrtc {
32 : class NoiseSuppressionImpl::Suppressor {
33 : public:
34 0 : explicit Suppressor(int sample_rate_hz) {
35 0 : state_ = NS_CREATE();
36 0 : RTC_CHECK(state_);
37 0 : int error = NS_INIT(state_, sample_rate_hz);
38 0 : RTC_DCHECK_EQ(0, error);
39 0 : }
40 0 : ~Suppressor() {
41 0 : NS_FREE(state_);
42 0 : }
43 0 : NsState* state() { return state_; }
44 : private:
45 : NsState* state_ = nullptr;
46 : RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Suppressor);
47 : };
48 :
49 0 : NoiseSuppressionImpl::NoiseSuppressionImpl(rtc::CriticalSection* crit)
50 0 : : crit_(crit) {
51 0 : RTC_DCHECK(crit);
52 0 : }
53 :
54 0 : NoiseSuppressionImpl::~NoiseSuppressionImpl() {}
55 :
56 0 : void NoiseSuppressionImpl::Initialize(size_t channels, int sample_rate_hz) {
57 0 : rtc::CritScope cs(crit_);
58 0 : channels_ = channels;
59 0 : sample_rate_hz_ = sample_rate_hz;
60 0 : std::vector<std::unique_ptr<Suppressor>> new_suppressors;
61 0 : if (enabled_) {
62 0 : new_suppressors.resize(channels);
63 0 : for (size_t i = 0; i < channels; i++) {
64 0 : new_suppressors[i].reset(new Suppressor(sample_rate_hz));
65 : }
66 : }
67 0 : suppressors_.swap(new_suppressors);
68 0 : set_level(level_);
69 0 : }
70 :
71 0 : void NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
72 0 : RTC_DCHECK(audio);
73 : #if defined(WEBRTC_NS_FLOAT)
74 0 : rtc::CritScope cs(crit_);
75 0 : if (!enabled_) {
76 0 : return;
77 : }
78 :
79 0 : RTC_DCHECK_GE(160, audio->num_frames_per_band());
80 0 : RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
81 0 : for (size_t i = 0; i < suppressors_.size(); i++) {
82 0 : WebRtcNs_Analyze(suppressors_[i]->state(),
83 0 : audio->split_bands_const_f(i)[kBand0To8kHz]);
84 : }
85 : #endif
86 : }
87 :
88 0 : void NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
89 0 : RTC_DCHECK(audio);
90 0 : rtc::CritScope cs(crit_);
91 0 : if (!enabled_) {
92 0 : return;
93 : }
94 :
95 0 : RTC_DCHECK_GE(160, audio->num_frames_per_band());
96 0 : RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
97 0 : for (size_t i = 0; i < suppressors_.size(); i++) {
98 : #if defined(WEBRTC_NS_FLOAT)
99 0 : WebRtcNs_Process(suppressors_[i]->state(),
100 : audio->split_bands_const_f(i),
101 : audio->num_bands(),
102 0 : audio->split_bands_f(i));
103 : #elif defined(WEBRTC_NS_FIXED)
104 : WebRtcNsx_Process(suppressors_[i]->state(),
105 : audio->split_bands_const(i),
106 : audio->num_bands(),
107 : audio->split_bands(i));
108 : #endif
109 : }
110 : }
111 :
112 0 : int NoiseSuppressionImpl::Enable(bool enable) {
113 0 : rtc::CritScope cs(crit_);
114 0 : if (enabled_ != enable) {
115 0 : enabled_ = enable;
116 0 : Initialize(channels_, sample_rate_hz_);
117 : }
118 0 : return AudioProcessing::kNoError;
119 : }
120 :
121 0 : bool NoiseSuppressionImpl::is_enabled() const {
122 0 : rtc::CritScope cs(crit_);
123 0 : return enabled_;
124 : }
125 :
126 0 : int NoiseSuppressionImpl::set_level(Level level) {
127 0 : int policy = 1;
128 0 : switch (level) {
129 : case NoiseSuppression::kLow:
130 0 : policy = 0;
131 0 : break;
132 : case NoiseSuppression::kModerate:
133 0 : policy = 1;
134 0 : break;
135 : case NoiseSuppression::kHigh:
136 0 : policy = 2;
137 0 : break;
138 : case NoiseSuppression::kVeryHigh:
139 0 : policy = 3;
140 0 : break;
141 : default:
142 0 : RTC_NOTREACHED();
143 : }
144 0 : rtc::CritScope cs(crit_);
145 0 : level_ = level;
146 0 : for (auto& suppressor : suppressors_) {
147 0 : int error = NS_SET_POLICY(suppressor->state(), policy);
148 0 : RTC_DCHECK_EQ(0, error);
149 : }
150 0 : return AudioProcessing::kNoError;
151 : }
152 :
153 0 : NoiseSuppression::Level NoiseSuppressionImpl::level() const {
154 0 : rtc::CritScope cs(crit_);
155 0 : return level_;
156 : }
157 :
158 0 : float NoiseSuppressionImpl::speech_probability() const {
159 0 : rtc::CritScope cs(crit_);
160 : #if defined(WEBRTC_NS_FLOAT)
161 0 : float probability_average = 0.0f;
162 0 : for (auto& suppressor : suppressors_) {
163 0 : probability_average +=
164 0 : WebRtcNs_prior_speech_probability(suppressor->state());
165 : }
166 0 : if (!suppressors_.empty()) {
167 0 : probability_average /= suppressors_.size();
168 : }
169 0 : return probability_average;
170 : #elif defined(WEBRTC_NS_FIXED)
171 : // TODO(peah): Returning error code as a float! Remove this.
172 : // Currently not available for the fixed point implementation.
173 : return AudioProcessing::kUnsupportedFunctionError;
174 : #endif
175 : }
176 :
177 0 : std::vector<float> NoiseSuppressionImpl::NoiseEstimate() {
178 0 : rtc::CritScope cs(crit_);
179 0 : std::vector<float> noise_estimate;
180 : #if defined(WEBRTC_NS_FLOAT)
181 0 : const float kNumChannelsFraction = 1.f / suppressors_.size();
182 0 : noise_estimate.assign(WebRtcNs_num_freq(), 0.f);
183 0 : for (auto& suppressor : suppressors_) {
184 0 : const float* noise = WebRtcNs_noise_estimate(suppressor->state());
185 0 : for (size_t i = 0; i < noise_estimate.size(); ++i) {
186 0 : noise_estimate[i] += kNumChannelsFraction * noise[i];
187 : }
188 : }
189 : #elif defined(WEBRTC_NS_FIXED)
190 : noise_estimate.assign(WebRtcNsx_num_freq(), 0.f);
191 : for (auto& suppressor : suppressors_) {
192 : int q_noise;
193 : const uint32_t* noise = WebRtcNsx_noise_estimate(suppressor->state(),
194 : &q_noise);
195 : const float kNormalizationFactor =
196 : 1.f / ((1 << q_noise) * suppressors_.size());
197 : for (size_t i = 0; i < noise_estimate.size(); ++i) {
198 : noise_estimate[i] += kNormalizationFactor * noise[i];
199 : }
200 : }
201 : #endif
202 0 : return noise_estimate;
203 : }
204 :
205 0 : size_t NoiseSuppressionImpl::num_noise_bins() {
206 : #if defined(WEBRTC_NS_FLOAT)
207 0 : return WebRtcNs_num_freq();
208 : #elif defined(WEBRTC_NS_FIXED)
209 : return WebRtcNsx_num_freq();
210 : #endif
211 : }
212 :
213 : } // namespace webrtc
|