blob: d4f8bbb60c234360df42c54dc188a058c2227fb9 [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);
57 std::vector<rtc::scoped_ptr<Suppressor>> new_suppressors(channels);
58 for (int i = 0; i < channels; i++) {
59 new_suppressors[i].reset(new Suppressor(sample_rate_hz));
60 }
61 rtc::CritScope cs(crit_);
62 suppressors_.swap(new_suppressors);
63 set_level(level_);
64}
65
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000066int NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080067 RTC_DCHECK(audio);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000068#if defined(WEBRTC_NS_FLOAT)
solenberg5e465c32015-12-08 13:22:33 -080069 rtc::CritScope cs(crit_);
70 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -080071 return AudioProcessing::kNoError;
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000072 }
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000073
solenberg5e465c32015-12-08 13:22:33 -080074 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
75 RTC_DCHECK_EQ(suppressors_.size(),
76 static_cast<size_t>(audio->num_channels()));
77 for (size_t i = 0; i < suppressors_.size(); i++) {
78 WebRtcNs_Analyze(suppressors_[i]->state(),
79 audio->split_bands_const_f(i)[kBand0To8kHz]);
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000080 }
81#endif
peahdf3efa82015-11-28 12:35:15 -080082 return AudioProcessing::kNoError;
aluebs@webrtc.orgfda2c2e2014-09-18 09:54:06 +000083}
84
niklase@google.com470e71d2011-07-07 08:21:25 +000085int NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
solenberg5e465c32015-12-08 13:22:33 -080086 RTC_DCHECK(audio);
peahdf3efa82015-11-28 12:35:15 -080087 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -080088 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -080089 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +000090 }
niklase@google.com470e71d2011-07-07 08:21:25 +000091
solenberg5e465c32015-12-08 13:22:33 -080092 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
93 RTC_DCHECK_EQ(suppressors_.size(),
94 static_cast<size_t>(audio->num_channels()));
95 for (size_t i = 0; i < suppressors_.size(); i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +000096#if defined(WEBRTC_NS_FLOAT)
solenberg5e465c32015-12-08 13:22:33 -080097 WebRtcNs_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +000098 audio->split_bands_const_f(i),
99 audio->num_bands(),
100 audio->split_bands_f(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000101#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800102 WebRtcNsx_Process(suppressors_[i]->state(),
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000103 audio->split_bands_const(i),
104 audio->num_bands(),
105 audio->split_bands(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000106#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 }
peahdf3efa82015-11-28 12:35:15 -0800108 return AudioProcessing::kNoError;
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_);
solenberg5e465c32015-12-08 13:22:33 -0800113 enabled_ = enable;
114 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000115}
116
117bool NoiseSuppressionImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800118 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -0800119 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000120}
121
122int NoiseSuppressionImpl::set_level(Level level) {
peahdf3efa82015-11-28 12:35:15 -0800123 rtc::CritScope cs(crit_);
solenberg5e465c32015-12-08 13:22:33 -0800124 int policy = 1;
125 switch (level) {
126 case NoiseSuppression::kLow:
127 policy = 0;
128 break;
129 case NoiseSuppression::kModerate:
130 policy = 1;
131 break;
132 case NoiseSuppression::kHigh:
133 policy = 2;
134 break;
135 case NoiseSuppression::kVeryHigh:
136 policy = 3;
137 break;
138 default:
139 RTC_NOTREACHED();
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000141 level_ = level;
solenberg5e465c32015-12-08 13:22:33 -0800142 for (auto& suppressor : suppressors_) {
143 int error = NS_SET_POLICY(suppressor->state(), policy);
144 RTC_DCHECK_EQ(0, error);
145 }
146 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000147}
148
149NoiseSuppression::Level NoiseSuppressionImpl::level() const {
peahdf3efa82015-11-28 12:35:15 -0800150 rtc::CritScope cs(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000151 return level_;
152}
153
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000154float NoiseSuppressionImpl::speech_probability() const {
peahdf3efa82015-11-28 12:35:15 -0800155 rtc::CritScope cs(crit_);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000156#if defined(WEBRTC_NS_FLOAT)
157 float probability_average = 0.0f;
solenberg5e465c32015-12-08 13:22:33 -0800158 for (auto& suppressor : suppressors_) {
159 probability_average +=
160 WebRtcNs_prior_speech_probability(suppressor->state());
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000161 }
solenberg5e465c32015-12-08 13:22:33 -0800162 if (suppressors_.size() > 0) {
163 probability_average /= suppressors_.size();
164 }
165 return probability_average;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000166#elif defined(WEBRTC_NS_FIXED)
solenberg5e465c32015-12-08 13:22:33 -0800167 // TODO(peah): Returning error code as a float! Remove this.
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000168 // Currently not available for the fixed point implementation.
peahdf3efa82015-11-28 12:35:15 -0800169 return AudioProcessing::kUnsupportedFunctionError;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000170#endif
171}
niklase@google.com470e71d2011-07-07 08:21:25 +0000172} // namespace webrtc