1/*
2 *  Copyright (c) 2011 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 "noise_suppression_impl.h"
12
13#include <cassert>
14
15#include "critical_section_wrapper.h"
16#if defined(WEBRTC_NS_FLOAT)
17#include "noise_suppression.h"
18#elif defined(WEBRTC_NS_FIXED)
19#include "noise_suppression_x.h"
20#endif
21
22#include "audio_processing_impl.h"
23#include "audio_buffer.h"
24
25namespace webrtc {
26
27#if defined(WEBRTC_NS_FLOAT)
28typedef NsHandle Handle;
29#elif defined(WEBRTC_NS_FIXED)
30typedef NsxHandle Handle;
31#endif
32
33namespace {
34int MapSetting(NoiseSuppression::Level level) {
35  switch (level) {
36    case NoiseSuppression::kLow:
37      return 0;
38    case NoiseSuppression::kModerate:
39      return 1;
40    case NoiseSuppression::kHigh:
41      return 2;
42    case NoiseSuppression::kVeryHigh:
43      return 3;
44    default:
45      return -1;
46  }
47}
48}  // namespace
49
50NoiseSuppressionImpl::NoiseSuppressionImpl(const AudioProcessingImpl* apm)
51  : ProcessingComponent(apm),
52    apm_(apm),
53    level_(kModerate) {}
54
55NoiseSuppressionImpl::~NoiseSuppressionImpl() {}
56
57int NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
58  int err = apm_->kNoError;
59
60  if (!is_component_enabled()) {
61    return apm_->kNoError;
62  }
63  assert(audio->samples_per_split_channel() <= 160);
64  assert(audio->num_channels() == num_handles());
65
66  for (int i = 0; i < num_handles(); i++) {
67    Handle* my_handle = static_cast<Handle*>(handle(i));
68#if defined(WEBRTC_NS_FLOAT)
69    err = WebRtcNs_Process(static_cast<Handle*>(handle(i)),
70                           audio->low_pass_split_data(i),
71                           audio->high_pass_split_data(i),
72                           audio->low_pass_split_data(i),
73                           audio->high_pass_split_data(i));
74#elif defined(WEBRTC_NS_FIXED)
75    err = WebRtcNsx_Process(static_cast<Handle*>(handle(i)),
76                            audio->low_pass_split_data(i),
77                            audio->high_pass_split_data(i),
78                            audio->low_pass_split_data(i),
79                            audio->high_pass_split_data(i));
80#endif
81
82    if (err != apm_->kNoError) {
83      return GetHandleError(my_handle);
84    }
85  }
86
87  return apm_->kNoError;
88}
89
90int NoiseSuppressionImpl::Enable(bool enable) {
91  CriticalSectionScoped crit_scoped(*apm_->crit());
92  return EnableComponent(enable);
93}
94
95bool NoiseSuppressionImpl::is_enabled() const {
96  return is_component_enabled();
97}
98
99int NoiseSuppressionImpl::set_level(Level level) {
100  CriticalSectionScoped crit_scoped(*apm_->crit());
101  if (MapSetting(level) == -1) {
102    return apm_->kBadParameterError;
103  }
104
105  level_ = level;
106  return Configure();
107}
108
109NoiseSuppression::Level NoiseSuppressionImpl::level() const {
110  return level_;
111}
112
113int NoiseSuppressionImpl::get_version(char* version,
114                                      int version_len_bytes) const {
115#if defined(WEBRTC_NS_FLOAT)
116  if (WebRtcNs_get_version(version, version_len_bytes) != 0)
117#elif defined(WEBRTC_NS_FIXED)
118  if (WebRtcNsx_get_version(version, version_len_bytes) != 0)
119#endif
120  {
121      return apm_->kBadParameterError;
122  }
123
124  return apm_->kNoError;
125}
126
127void* NoiseSuppressionImpl::CreateHandle() const {
128  Handle* handle = NULL;
129#if defined(WEBRTC_NS_FLOAT)
130  if (WebRtcNs_Create(&handle) != apm_->kNoError)
131#elif defined(WEBRTC_NS_FIXED)
132  if (WebRtcNsx_Create(&handle) != apm_->kNoError)
133#endif
134  {
135    handle = NULL;
136  } else {
137    assert(handle != NULL);
138  }
139
140  return handle;
141}
142
143int NoiseSuppressionImpl::DestroyHandle(void* handle) const {
144#if defined(WEBRTC_NS_FLOAT)
145  return WebRtcNs_Free(static_cast<Handle*>(handle));
146#elif defined(WEBRTC_NS_FIXED)
147  return WebRtcNsx_Free(static_cast<Handle*>(handle));
148#endif
149}
150
151int NoiseSuppressionImpl::InitializeHandle(void* handle) const {
152#if defined(WEBRTC_NS_FLOAT)
153  return WebRtcNs_Init(static_cast<Handle*>(handle), apm_->sample_rate_hz());
154#elif defined(WEBRTC_NS_FIXED)
155  return WebRtcNsx_Init(static_cast<Handle*>(handle), apm_->sample_rate_hz());
156#endif
157}
158
159int NoiseSuppressionImpl::ConfigureHandle(void* handle) const {
160#if defined(WEBRTC_NS_FLOAT)
161  return WebRtcNs_set_policy(static_cast<Handle*>(handle),
162                             MapSetting(level_));
163#elif defined(WEBRTC_NS_FIXED)
164  return WebRtcNsx_set_policy(static_cast<Handle*>(handle),
165                              MapSetting(level_));
166#endif
167}
168
169int NoiseSuppressionImpl::num_handles_required() const {
170  return apm_->num_output_channels();
171}
172
173int NoiseSuppressionImpl::GetHandleError(void* handle) const {
174  // The NS has no get_error() function.
175  assert(handle != NULL);
176  return apm_->kUnspecifiedError;
177}
178}  // namespace webrtc
179
180