blob: 8dd713f4e50161822ab995655d664f7488dac27a [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
bjornv@webrtc.org0c6f9312012-01-30 09:39:08 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/noise_suppression_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/audio_processing/audio_buffer.h"
14#include "rtc_base/constructormagic.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000015#if defined(WEBRTC_NS_FLOAT)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_processing/ns/noise_suppression.h"
solenberg5e465c32015-12-08 13:22:33 -080017#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
21typedef NsHandle NsState;
niklase@google.com470e71d2011-07-07 08:21:25 +000022#elif defined(WEBRTC_NS_FIXED)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/audio_processing/ns/noise_suppression_x.h"
solenberg5e465c32015-12-08 13:22:33 -080024#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
28typedef NsxHandle NsState;
niklase@google.com470e71d2011-07-07 08:21:25 +000029#endif
30
niklase@google.com470e71d2011-07-07 08:21:25 +000031namespace webrtc {
solenberg5e465c32015-12-08 13:22:33 -080032class NoiseSuppressionImpl::Suppressor {
33 public:
34 explicit Suppressor(int sample_rate_hz) {
35 state_ = NS_CREATE();
36 RTC_CHECK(state_);
37 int error = NS_INIT(state_, sample_rate_hz);
38 RTC_DCHECK_EQ(0, error);
niklase@google.com470e71d2011-07-07 08:21:25 +000039 }
solenberg5e465c32015-12-08 13:22:33 -080040 ~Suppressor() {
41 NS_FREE(state_);
42 }
43 NsState* state() { return state_; }
44 private:
45 NsState* state_ = nullptr;
46 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Suppressor);
47};
niklase@google.com470e71d2011-07-07 08:21:25 +000048
solenberg5e465c32015-12-08 13:22:33 -080049NoiseSuppressionImpl::NoiseSuppressionImpl(rtc::CriticalSection* crit)
50 : crit_(crit) {
peahdf3efa82015-11-28 12:35:15 -080051 RTC_DCHECK(crit);
52}
niklase@google.com470e71d2011-07-07 08:21:25 +000053
54NoiseSuppressionImpl::~NoiseSuppressionImpl() {}
55
Peter Kasting69558702016-01-12 16:26:35 -080056void NoiseSuppressionImpl::Initialize(size_t channels, int sample_rate_hz) {
solenberg5e465c32015-12-08 13:22:33 -080057 rtc::CritScope cs(crit_);
solenberg29e2f932015-12-16 01:18:15 -080058 channels_ = channels;
59 sample_rate_hz_ = sample_rate_hz;
kwiberg88788ad2016-02-19 07:04:49 -080060 std::vector<std::unique_ptr<Suppressor>> new_suppressors;
solenberg29e2f932015-12-16 01:18:15 -080061 if (enabled_) {
62 new_suppressors.resize(channels);
Peter Kasting69558702016-01-12 16:26:35 -080063 for (size_t i = 0; i < channels; i++) {
solenberg29e2f932015-12-16 01:18:15 -080064 new_suppressors[i].reset(new Suppressor(sample_rate_hz));
65 }
66 }
solenberg5e465c32015-12-08 13:22:33 -080067 suppressors_.swap(new_suppressors);
68 set_level(level_);
69}
70
solenberg29e2f932015-12-16 01:18:15 -080071void NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080072 RTC_DCHECK(audio);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000073#if defined(WEBRTC_NS_FLOAT)
solenberg5e465c32015-12-08 13:22:33 -080074 rtc::CritScope cs(crit_);
75 if (!enabled_) {
solenberg29e2f932015-12-16 01:18:15 -080076 return;
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000077 }
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000078
kwibergaf476c72016-11-28 15:21:39 -080079 RTC_DCHECK_GE(160, audio->num_frames_per_band());
Peter Kasting69558702016-01-12 16:26:35 -080080 RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
solenberg5e465c32015-12-08 13:22:33 -080081 for (size_t i = 0; i < suppressors_.size(); i++) {
82 WebRtcNs_Analyze(suppressors_[i]->state(),
83 audio->split_bands_const_f(i)[kBand0To8kHz]);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000084 }
85#endif
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000086}
87
solenberg29e2f932015-12-16 01:18:15 -080088void NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080089 RTC_DCHECK(audio);
peahdf3efa82015-11-28 12:35:15 -080090 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -080091 if (!enabled_) {
solenberg29e2f932015-12-16 01:18:15 -080092 return;
niklase@google.com470e71d2011-07-07 08:21:25 +000093 }
niklase@google.com470e71d2011-07-07 08:21:25 +000094
kwibergaf476c72016-11-28 15:21:39 -080095 RTC_DCHECK_GE(160, audio->num_frames_per_band());
Peter Kasting69558702016-01-12 16:26:35 -080096 RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
solenberg5e465c32015-12-08 13:22:33 -080097 for (size_t i = 0; i < suppressors_.size(); i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +000098#if defined(WEBRTC_NS_FLOAT)
solenberg5e465c32015-12-08 13:22:33 -080099 WebRtcNs_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000100 audio->split_bands_const_f(i),
101 audio->num_bands(),
102 audio->split_bands_f(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000103#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800104 WebRtcNsx_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000105 audio->split_bands_const(i),
106 audio->num_bands(),
107 audio->split_bands(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000108#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000110}
111
112int NoiseSuppressionImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800113 rtc::CritScope cs(crit_);
solenberg29e2f932015-12-16 01:18:15 -0800114 if (enabled_ != enable) {
115 enabled_ = enable;
116 Initialize(channels_, sample_rate_hz_);
117 }
solenberg5e465c32015-12-08 13:22:33 -0800118 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000119}
120
121bool NoiseSuppressionImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800122 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -0800123 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000124}
125
126int NoiseSuppressionImpl::set_level(Level level) {
solenberg5e465c32015-12-08 13:22:33 -0800127 int policy = 1;
128 switch (level) {
129 case NoiseSuppression::kLow:
130 policy = 0;
131 break;
132 case NoiseSuppression::kModerate:
133 policy = 1;
134 break;
135 case NoiseSuppression::kHigh:
136 policy = 2;
137 break;
138 case NoiseSuppression::kVeryHigh:
139 policy = 3;
140 break;
141 default:
142 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 }
solenberg29e2f932015-12-16 01:18:15 -0800144 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000145 level_ = level;
solenberg5e465c32015-12-08 13:22:33 -0800146 for (auto& suppressor : suppressors_) {
147 int error = NS_SET_POLICY(suppressor->state(), policy);
148 RTC_DCHECK_EQ(0, error);
149 }
150 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000151}
152
153NoiseSuppression::Level NoiseSuppressionImpl::level() const {
peahdf3efa82015-11-28 12:35:15 -0800154 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000155 return level_;
156}
157
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000158float NoiseSuppressionImpl::speech_probability() const {
peahdf3efa82015-11-28 12:35:15 -0800159 rtc::CritScope cs(crit_);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000160#if defined(WEBRTC_NS_FLOAT)
161 float probability_average = 0.0f;
solenberg5e465c32015-12-08 13:22:33 -0800162 for (auto& suppressor : suppressors_) {
163 probability_average +=
164 WebRtcNs_prior_speech_probability(suppressor->state());
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000165 }
pkasting25702cb2016-01-08 13:50:27 -0800166 if (!suppressors_.empty()) {
solenberg5e465c32015-12-08 13:22:33 -0800167 probability_average /= suppressors_.size();
168 }
169 return probability_average;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000170#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800171 // TODO(peah): Returning error code as a float! Remove this.
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000172 // Currently not available for the fixed point implementation.
peahdf3efa82015-11-28 12:35:15 -0800173 return AudioProcessing::kUnsupportedFunctionError;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000174#endif
175}
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800176
177std::vector<float> NoiseSuppressionImpl::NoiseEstimate() {
178 rtc::CritScope cs(crit_);
179 std::vector<float> noise_estimate;
180#if defined(WEBRTC_NS_FLOAT)
Alejandro Luebs3b149962016-04-01 13:54:36 -0700181 const float kNumChannelsFraction = 1.f / suppressors_.size();
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800182 noise_estimate.assign(WebRtcNs_num_freq(), 0.f);
183 for (auto& suppressor : suppressors_) {
184 const float* noise = WebRtcNs_noise_estimate(suppressor->state());
185 for (size_t i = 0; i < noise_estimate.size(); ++i) {
Alejandro Luebs3b149962016-04-01 13:54:36 -0700186 noise_estimate[i] += kNumChannelsFraction * noise[i];
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800187 }
188 }
189#elif defined(WEBRTC_NS_FIXED)
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800190 noise_estimate.assign(WebRtcNsx_num_freq(), 0.f);
191 for (auto& suppressor : suppressors_) {
Alejandro Luebs3b149962016-04-01 13:54:36 -0700192 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());
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800197 for (size_t i = 0; i < noise_estimate.size(); ++i) {
Alejandro Luebs3b149962016-04-01 13:54:36 -0700198 noise_estimate[i] += kNormalizationFactor * noise[i];
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800199 }
200 }
201#endif
202 return noise_estimate;
203}
204
Alex Luebs57ae8292016-03-09 16:24:34 +0100205size_t NoiseSuppressionImpl::num_noise_bins() {
206#if defined(WEBRTC_NS_FLOAT)
207 return WebRtcNs_num_freq();
208#elif defined(WEBRTC_NS_FIXED)
209 return WebRtcNsx_num_freq();
210#endif
211}
212
niklase@google.com470e71d2011-07-07 08:21:25 +0000213} // namespace webrtc