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