blob: 15d404323c36f88eff1f1618e0421a0f65aac1cf [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 }
Yves Gerey665174f2018-06-19 15:03:05 +020040 ~Suppressor() { NS_FREE(state_); }
solenberg5e465c32015-12-08 13:22:33 -080041 NsState* state() { return state_; }
Yves Gerey665174f2018-06-19 15:03:05 +020042
solenberg5e465c32015-12-08 13:22:33 -080043 private:
44 NsState* state_ = nullptr;
45 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Suppressor);
46};
niklase@google.com470e71d2011-07-07 08:21:25 +000047
solenberg5e465c32015-12-08 13:22:33 -080048NoiseSuppressionImpl::NoiseSuppressionImpl(rtc::CriticalSection* crit)
49 : crit_(crit) {
peahdf3efa82015-11-28 12:35:15 -080050 RTC_DCHECK(crit);
51}
niklase@google.com470e71d2011-07-07 08:21:25 +000052
53NoiseSuppressionImpl::~NoiseSuppressionImpl() {}
54
Peter Kasting69558702016-01-12 16:26:35 -080055void NoiseSuppressionImpl::Initialize(size_t channels, int sample_rate_hz) {
solenberg5e465c32015-12-08 13:22:33 -080056 rtc::CritScope cs(crit_);
solenberg29e2f932015-12-16 01:18:15 -080057 channels_ = channels;
58 sample_rate_hz_ = sample_rate_hz;
kwiberg88788ad2016-02-19 07:04:49 -080059 std::vector<std::unique_ptr<Suppressor>> new_suppressors;
solenberg29e2f932015-12-16 01:18:15 -080060 if (enabled_) {
61 new_suppressors.resize(channels);
Peter Kasting69558702016-01-12 16:26:35 -080062 for (size_t i = 0; i < channels; i++) {
solenberg29e2f932015-12-16 01:18:15 -080063 new_suppressors[i].reset(new Suppressor(sample_rate_hz));
64 }
65 }
solenberg5e465c32015-12-08 13:22:33 -080066 suppressors_.swap(new_suppressors);
67 set_level(level_);
68}
69
solenberg29e2f932015-12-16 01:18:15 -080070void NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080071 RTC_DCHECK(audio);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000072#if defined(WEBRTC_NS_FLOAT)
solenberg5e465c32015-12-08 13:22:33 -080073 rtc::CritScope cs(crit_);
74 if (!enabled_) {
solenberg29e2f932015-12-16 01:18:15 -080075 return;
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000076 }
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000077
kwibergaf476c72016-11-28 15:21:39 -080078 RTC_DCHECK_GE(160, audio->num_frames_per_band());
Peter Kasting69558702016-01-12 16:26:35 -080079 RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
solenberg5e465c32015-12-08 13:22:33 -080080 for (size_t i = 0; i < suppressors_.size(); i++) {
81 WebRtcNs_Analyze(suppressors_[i]->state(),
82 audio->split_bands_const_f(i)[kBand0To8kHz]);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000083 }
84#endif
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000085}
86
solenberg29e2f932015-12-16 01:18:15 -080087void NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080088 RTC_DCHECK(audio);
peahdf3efa82015-11-28 12:35:15 -080089 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -080090 if (!enabled_) {
solenberg29e2f932015-12-16 01:18:15 -080091 return;
niklase@google.com470e71d2011-07-07 08:21:25 +000092 }
niklase@google.com470e71d2011-07-07 08:21:25 +000093
kwibergaf476c72016-11-28 15:21:39 -080094 RTC_DCHECK_GE(160, audio->num_frames_per_band());
Peter Kasting69558702016-01-12 16:26:35 -080095 RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
solenberg5e465c32015-12-08 13:22:33 -080096 for (size_t i = 0; i < suppressors_.size(); i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +000097#if defined(WEBRTC_NS_FLOAT)
Yves Gerey665174f2018-06-19 15:03:05 +020098 WebRtcNs_Process(suppressors_[i]->state(), audio->split_bands_const_f(i),
99 audio->num_bands(), audio->split_bands_f(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000100#elif defined(WEBRTC_NS_FIXED)
Yves Gerey665174f2018-06-19 15:03:05 +0200101 WebRtcNsx_Process(suppressors_[i]->state(), audio->split_bands_const(i),
102 audio->num_bands(), audio->split_bands(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000103#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000105}
106
107int NoiseSuppressionImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800108 rtc::CritScope cs(crit_);
solenberg29e2f932015-12-16 01:18:15 -0800109 if (enabled_ != enable) {
110 enabled_ = enable;
111 Initialize(channels_, sample_rate_hz_);
112 }
solenberg5e465c32015-12-08 13:22:33 -0800113 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000114}
115
116bool NoiseSuppressionImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800117 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -0800118 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000119}
120
121int NoiseSuppressionImpl::set_level(Level level) {
solenberg5e465c32015-12-08 13:22:33 -0800122 int policy = 1;
123 switch (level) {
124 case NoiseSuppression::kLow:
125 policy = 0;
126 break;
127 case NoiseSuppression::kModerate:
128 policy = 1;
129 break;
130 case NoiseSuppression::kHigh:
131 policy = 2;
132 break;
133 case NoiseSuppression::kVeryHigh:
134 policy = 3;
135 break;
136 default:
137 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +0000138 }
solenberg29e2f932015-12-16 01:18:15 -0800139 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 level_ = level;
solenberg5e465c32015-12-08 13:22:33 -0800141 for (auto& suppressor : suppressors_) {
142 int error = NS_SET_POLICY(suppressor->state(), policy);
143 RTC_DCHECK_EQ(0, error);
144 }
145 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146}
147
148NoiseSuppression::Level NoiseSuppressionImpl::level() const {
peahdf3efa82015-11-28 12:35:15 -0800149 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 return level_;
151}
152
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000153float NoiseSuppressionImpl::speech_probability() const {
peahdf3efa82015-11-28 12:35:15 -0800154 rtc::CritScope cs(crit_);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000155#if defined(WEBRTC_NS_FLOAT)
156 float probability_average = 0.0f;
solenberg5e465c32015-12-08 13:22:33 -0800157 for (auto& suppressor : suppressors_) {
158 probability_average +=
159 WebRtcNs_prior_speech_probability(suppressor->state());
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000160 }
pkasting25702cb2016-01-08 13:50:27 -0800161 if (!suppressors_.empty()) {
solenberg5e465c32015-12-08 13:22:33 -0800162 probability_average /= suppressors_.size();
163 }
164 return probability_average;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000165#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800166 // TODO(peah): Returning error code as a float! Remove this.
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000167 // Currently not available for the fixed point implementation.
peahdf3efa82015-11-28 12:35:15 -0800168 return AudioProcessing::kUnsupportedFunctionError;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000169#endif
170}
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800171
172std::vector<float> NoiseSuppressionImpl::NoiseEstimate() {
173 rtc::CritScope cs(crit_);
174 std::vector<float> noise_estimate;
175#if defined(WEBRTC_NS_FLOAT)
Alejandro Luebs3b149962016-04-01 13:54:36 -0700176 const float kNumChannelsFraction = 1.f / suppressors_.size();
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800177 noise_estimate.assign(WebRtcNs_num_freq(), 0.f);
178 for (auto& suppressor : suppressors_) {
179 const float* noise = WebRtcNs_noise_estimate(suppressor->state());
180 for (size_t i = 0; i < noise_estimate.size(); ++i) {
Alejandro Luebs3b149962016-04-01 13:54:36 -0700181 noise_estimate[i] += kNumChannelsFraction * noise[i];
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800182 }
183 }
184#elif defined(WEBRTC_NS_FIXED)
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800185 noise_estimate.assign(WebRtcNsx_num_freq(), 0.f);
186 for (auto& suppressor : suppressors_) {
Alejandro Luebs3b149962016-04-01 13:54:36 -0700187 int q_noise;
Yves Gerey665174f2018-06-19 15:03:05 +0200188 const uint32_t* noise =
189 WebRtcNsx_noise_estimate(suppressor->state(), &q_noise);
Alejandro Luebs3b149962016-04-01 13:54:36 -0700190 const float kNormalizationFactor =
191 1.f / ((1 << q_noise) * suppressors_.size());
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800192 for (size_t i = 0; i < noise_estimate.size(); ++i) {
Alejandro Luebs3b149962016-04-01 13:54:36 -0700193 noise_estimate[i] += kNormalizationFactor * noise[i];
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800194 }
195 }
196#endif
197 return noise_estimate;
198}
199
Alex Luebs57ae8292016-03-09 16:24:34 +0100200size_t NoiseSuppressionImpl::num_noise_bins() {
201#if defined(WEBRTC_NS_FLOAT)
202 return WebRtcNs_num_freq();
203#elif defined(WEBRTC_NS_FIXED)
204 return WebRtcNsx_num_freq();
205#endif
206}
207
niklase@google.com470e71d2011-07-07 08:21:25 +0000208} // namespace webrtc