blob: 7f19005924de76373ebe8547337e341ad0656767 [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
pbos@webrtc.org7fad4b82013-05-28 08:11:59 +000011#include "webrtc/modules/audio_processing/noise_suppression_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
andrew@webrtc.org56e4a052014-02-27 22:23:17 +000013#include "webrtc/modules/audio_processing/audio_buffer.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000014#if defined(WEBRTC_NS_FLOAT)
Henrik Kjellander9b72af92015-11-11 20:16:11 +010015#include "webrtc/modules/audio_processing/ns/noise_suppression.h"
solenberg5e465c32015-12-08 13:22:33 -080016#define NS_CREATE WebRtcNs_Create
17#define NS_FREE WebRtcNs_Free
18#define NS_INIT WebRtcNs_Init
19#define NS_SET_POLICY WebRtcNs_set_policy
20typedef NsHandle NsState;
niklase@google.com470e71d2011-07-07 08:21:25 +000021#elif defined(WEBRTC_NS_FIXED)
Henrik Kjellander9b72af92015-11-11 20:16:11 +010022#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
solenberg5e465c32015-12-08 13:22:33 -080023#define NS_CREATE WebRtcNsx_Create
24#define NS_FREE WebRtcNsx_Free
25#define NS_INIT WebRtcNsx_Init
26#define NS_SET_POLICY WebRtcNsx_set_policy
27typedef NsxHandle NsState;
niklase@google.com470e71d2011-07-07 08:21:25 +000028#endif
29
niklase@google.com470e71d2011-07-07 08:21:25 +000030namespace webrtc {
solenberg5e465c32015-12-08 13:22:33 -080031class NoiseSuppressionImpl::Suppressor {
32 public:
33 explicit Suppressor(int sample_rate_hz) {
34 state_ = NS_CREATE();
35 RTC_CHECK(state_);
36 int error = NS_INIT(state_, sample_rate_hz);
37 RTC_DCHECK_EQ(0, error);
niklase@google.com470e71d2011-07-07 08:21:25 +000038 }
solenberg5e465c32015-12-08 13:22:33 -080039 ~Suppressor() {
40 NS_FREE(state_);
41 }
42 NsState* state() { return state_; }
43 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
solenberg5e465c32015-12-08 13:22:33 -080078 RTC_DCHECK_GE(160u, 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
solenberg5e465c32015-12-08 13:22:33 -080094 RTC_DCHECK_GE(160u, 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)
solenberg5e465c32015-12-08 13:22:33 -080098 WebRtcNs_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +000099 audio->split_bands_const_f(i),
100 audio->num_bands(),
101 audio->split_bands_f(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000102#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800103 WebRtcNsx_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000104 audio->split_bands_const(i),
105 audio->num_bands(),
106 audio->split_bands(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000107#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000109}
110
111int NoiseSuppressionImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800112 rtc::CritScope cs(crit_);
solenberg29e2f932015-12-16 01:18:15 -0800113 if (enabled_ != enable) {
114 enabled_ = enable;
115 Initialize(channels_, sample_rate_hz_);
116 }
solenberg5e465c32015-12-08 13:22:33 -0800117 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000118}
119
120bool NoiseSuppressionImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800121 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -0800122 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000123}
124
125int NoiseSuppressionImpl::set_level(Level level) {
solenberg5e465c32015-12-08 13:22:33 -0800126 int policy = 1;
127 switch (level) {
128 case NoiseSuppression::kLow:
129 policy = 0;
130 break;
131 case NoiseSuppression::kModerate:
132 policy = 1;
133 break;
134 case NoiseSuppression::kHigh:
135 policy = 2;
136 break;
137 case NoiseSuppression::kVeryHigh:
138 policy = 3;
139 break;
140 default:
141 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +0000142 }
solenberg29e2f932015-12-16 01:18:15 -0800143 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 level_ = level;
solenberg5e465c32015-12-08 13:22:33 -0800145 for (auto& suppressor : suppressors_) {
146 int error = NS_SET_POLICY(suppressor->state(), policy);
147 RTC_DCHECK_EQ(0, error);
148 }
149 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000150}
151
152NoiseSuppression::Level NoiseSuppressionImpl::level() const {
peahdf3efa82015-11-28 12:35:15 -0800153 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000154 return level_;
155}
156
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000157float NoiseSuppressionImpl::speech_probability() const {
peahdf3efa82015-11-28 12:35:15 -0800158 rtc::CritScope cs(crit_);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000159#if defined(WEBRTC_NS_FLOAT)
160 float probability_average = 0.0f;
solenberg5e465c32015-12-08 13:22:33 -0800161 for (auto& suppressor : suppressors_) {
162 probability_average +=
163 WebRtcNs_prior_speech_probability(suppressor->state());
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000164 }
pkasting25702cb2016-01-08 13:50:27 -0800165 if (!suppressors_.empty()) {
solenberg5e465c32015-12-08 13:22:33 -0800166 probability_average /= suppressors_.size();
167 }
168 return probability_average;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000169#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800170 // TODO(peah): Returning error code as a float! Remove this.
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000171 // Currently not available for the fixed point implementation.
peahdf3efa82015-11-28 12:35:15 -0800172 return AudioProcessing::kUnsupportedFunctionError;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000173#endif
174}
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800175
176std::vector<float> NoiseSuppressionImpl::NoiseEstimate() {
177 rtc::CritScope cs(crit_);
178 std::vector<float> noise_estimate;
179#if defined(WEBRTC_NS_FLOAT)
Alejandro Luebs32348192016-02-17 20:04:19 -0800180 const float kNormalizationFactor = 1.f / (1 << 15);
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800181 noise_estimate.assign(WebRtcNs_num_freq(), 0.f);
182 for (auto& suppressor : suppressors_) {
183 const float* noise = WebRtcNs_noise_estimate(suppressor->state());
184 for (size_t i = 0; i < noise_estimate.size(); ++i) {
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -0800185 noise_estimate[i] +=
186 kNormalizationFactor * noise[i] / suppressors_.size();
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800187 }
188 }
189#elif defined(WEBRTC_NS_FIXED)
Alejandro Luebs32348192016-02-17 20:04:19 -0800190 const float kNormalizationFactor = 1.f / (1 << 23);
Alejandro Luebsfa639f02016-02-09 11:24:32 -0800191 noise_estimate.assign(WebRtcNsx_num_freq(), 0.f);
192 for (auto& suppressor : suppressors_) {
193 const uint32_t* noise = WebRtcNsx_noise_estimate(suppressor->state());
194 for (size_t i = 0; i < noise_estimate.size(); ++i) {
195 noise_estimate[i] += kNormalizationFactor *
196 static_cast<float>(noise[i]) / suppressors_.size();
197 }
198 }
199#endif
200 return noise_estimate;
201}
202
niklase@google.com470e71d2011-07-07 08:21:25 +0000203} // namespace webrtc