noise_suppression_impl.cc revision 5e465c33cac54ed5265f18413f7afc44aae2dfca
1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
11#include "webrtc/modules/audio_processing/noise_suppression_impl.h"
12
13#include "webrtc/modules/audio_processing/audio_buffer.h"
14#if defined(WEBRTC_NS_FLOAT)
15#include "webrtc/modules/audio_processing/ns/noise_suppression.h"
16#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;
21#elif defined(WEBRTC_NS_FIXED)
22#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
23#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;
28#endif
29
30namespace webrtc {
31class 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);
38  }
39  ~Suppressor() {
40    NS_FREE(state_);
41  }
42  NsState* state() { return state_; }
43 private:
44  NsState* state_ = nullptr;
45  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Suppressor);
46};
47
48NoiseSuppressionImpl::NoiseSuppressionImpl(rtc::CriticalSection* crit)
49    : crit_(crit) {
50  RTC_DCHECK(crit);
51}
52
53NoiseSuppressionImpl::~NoiseSuppressionImpl() {}
54
55void 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
66int NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
67  RTC_DCHECK(audio);
68#if defined(WEBRTC_NS_FLOAT)
69  rtc::CritScope cs(crit_);
70  if (!enabled_) {
71    return AudioProcessing::kNoError;
72  }
73
74  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]);
80  }
81#endif
82  return AudioProcessing::kNoError;
83}
84
85int NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
86  RTC_DCHECK(audio);
87  rtc::CritScope cs(crit_);
88  if (!enabled_) {
89    return AudioProcessing::kNoError;
90  }
91
92  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++) {
96#if defined(WEBRTC_NS_FLOAT)
97    WebRtcNs_Process(suppressors_[i]->state(),
98                     audio->split_bands_const_f(i),
99                     audio->num_bands(),
100                     audio->split_bands_f(i));
101#elif defined(WEBRTC_NS_FIXED)
102    WebRtcNsx_Process(suppressors_[i]->state(),
103                      audio->split_bands_const(i),
104                      audio->num_bands(),
105                      audio->split_bands(i));
106#endif
107  }
108  return AudioProcessing::kNoError;
109}
110
111int NoiseSuppressionImpl::Enable(bool enable) {
112  rtc::CritScope cs(crit_);
113  enabled_ = enable;
114  return AudioProcessing::kNoError;
115}
116
117bool NoiseSuppressionImpl::is_enabled() const {
118  rtc::CritScope cs(crit_);
119  return enabled_;
120}
121
122int NoiseSuppressionImpl::set_level(Level level) {
123  rtc::CritScope cs(crit_);
124  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();
140  }
141  level_ = level;
142  for (auto& suppressor : suppressors_) {
143    int error = NS_SET_POLICY(suppressor->state(), policy);
144    RTC_DCHECK_EQ(0, error);
145  }
146  return AudioProcessing::kNoError;
147}
148
149NoiseSuppression::Level NoiseSuppressionImpl::level() const {
150  rtc::CritScope cs(crit_);
151  return level_;
152}
153
154float NoiseSuppressionImpl::speech_probability() const {
155  rtc::CritScope cs(crit_);
156#if defined(WEBRTC_NS_FLOAT)
157  float probability_average = 0.0f;
158  for (auto& suppressor : suppressors_) {
159    probability_average +=
160        WebRtcNs_prior_speech_probability(suppressor->state());
161  }
162  if (suppressors_.size() > 0) {
163    probability_average /= suppressors_.size();
164  }
165  return probability_average;
166#elif defined(WEBRTC_NS_FIXED)
167  // TODO(peah): Returning error code as a float! Remove this.
168  // Currently not available for the fixed point implementation.
169  return AudioProcessing::kUnsupportedFunctionError;
170#endif
171}
172}  // namespace webrtc
173