blob: ee0deecbdf72c39ae72882402189f5068c9da20e [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
solenberg5e465c32015-12-08 13:22:33 -080055void NoiseSuppressionImpl::Initialize(int channels, int sample_rate_hz) {
56 RTC_DCHECK_LE(0, channels);
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;
60 std::vector<rtc::scoped_ptr<Suppressor>> new_suppressors;
61 if (enabled_) {
62 new_suppressors.resize(channels);
63 for (int i = 0; i < channels; i++) {
64 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
solenberg5e465c32015-12-08 13:22:33 -080079 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
80 RTC_DCHECK_EQ(suppressors_.size(),
81 static_cast<size_t>(audio->num_channels()));
82 for (size_t i = 0; i < suppressors_.size(); i++) {
83 WebRtcNs_Analyze(suppressors_[i]->state(),
84 audio->split_bands_const_f(i)[kBand0To8kHz]);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000085 }
86#endif
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000087}
88
solenberg29e2f932015-12-16 01:18:15 -080089void NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080090 RTC_DCHECK(audio);
peahdf3efa82015-11-28 12:35:15 -080091 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -080092 if (!enabled_) {
solenberg29e2f932015-12-16 01:18:15 -080093 return;
niklase@google.com470e71d2011-07-07 08:21:25 +000094 }
niklase@google.com470e71d2011-07-07 08:21:25 +000095
solenberg5e465c32015-12-08 13:22:33 -080096 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
97 RTC_DCHECK_EQ(suppressors_.size(),
98 static_cast<size_t>(audio->num_channels()));
99 for (size_t i = 0; i < suppressors_.size(); i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000100#if defined(WEBRTC_NS_FLOAT)
solenberg5e465c32015-12-08 13:22:33 -0800101 WebRtcNs_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000102 audio->split_bands_const_f(i),
103 audio->num_bands(),
104 audio->split_bands_f(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000105#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800106 WebRtcNsx_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000107 audio->split_bands_const(i),
108 audio->num_bands(),
109 audio->split_bands(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000110#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000112}
113
114int NoiseSuppressionImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800115 rtc::CritScope cs(crit_);
solenberg29e2f932015-12-16 01:18:15 -0800116 if (enabled_ != enable) {
117 enabled_ = enable;
118 Initialize(channels_, sample_rate_hz_);
119 }
solenberg5e465c32015-12-08 13:22:33 -0800120 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000121}
122
123bool NoiseSuppressionImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800124 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -0800125 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000126}
127
128int NoiseSuppressionImpl::set_level(Level level) {
solenberg5e465c32015-12-08 13:22:33 -0800129 int policy = 1;
130 switch (level) {
131 case NoiseSuppression::kLow:
132 policy = 0;
133 break;
134 case NoiseSuppression::kModerate:
135 policy = 1;
136 break;
137 case NoiseSuppression::kHigh:
138 policy = 2;
139 break;
140 case NoiseSuppression::kVeryHigh:
141 policy = 3;
142 break;
143 default:
144 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +0000145 }
solenberg29e2f932015-12-16 01:18:15 -0800146 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000147 level_ = level;
solenberg5e465c32015-12-08 13:22:33 -0800148 for (auto& suppressor : suppressors_) {
149 int error = NS_SET_POLICY(suppressor->state(), policy);
150 RTC_DCHECK_EQ(0, error);
151 }
152 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
155NoiseSuppression::Level NoiseSuppressionImpl::level() const {
peahdf3efa82015-11-28 12:35:15 -0800156 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 return level_;
158}
159
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000160float NoiseSuppressionImpl::speech_probability() const {
peahdf3efa82015-11-28 12:35:15 -0800161 rtc::CritScope cs(crit_);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000162#if defined(WEBRTC_NS_FLOAT)
163 float probability_average = 0.0f;
solenberg5e465c32015-12-08 13:22:33 -0800164 for (auto& suppressor : suppressors_) {
165 probability_average +=
166 WebRtcNs_prior_speech_probability(suppressor->state());
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000167 }
solenberg5e465c32015-12-08 13:22:33 -0800168 if (suppressors_.size() > 0) {
169 probability_average /= suppressors_.size();
170 }
171 return probability_average;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000172#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800173 // TODO(peah): Returning error code as a float! Remove this.
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000174 // Currently not available for the fixed point implementation.
peahdf3efa82015-11-28 12:35:15 -0800175 return AudioProcessing::kUnsupportedFunctionError;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000176#endif
177}
niklase@google.com470e71d2011-07-07 08:21:25 +0000178} // namespace webrtc