blob: 7e9cdb701840295fb512678c40343a8db7e90e63 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +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.org956aa7e2013-05-21 13:52:32 +000011#include "webrtc/voice_engine/voe_audio_processing_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbosad856222015-11-27 09:48:36 -080013#include "webrtc/base/logging.h"
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000014#include "webrtc/modules/audio_processing/include/audio_processing.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010015#include "webrtc/system_wrappers/include/trace.h"
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000016#include "webrtc/voice_engine/channel.h"
17#include "webrtc/voice_engine/include/voe_errors.h"
18#include "webrtc/voice_engine/transmit_mixer.h"
19#include "webrtc/voice_engine/voice_engine_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
andrew@webrtc.org02d71742012-04-24 19:47:00 +000021// TODO(andrew): move to a common place.
andrew@webrtc.org55c0d4a2012-08-29 02:13:12 +000022#define WEBRTC_VOICE_INIT_CHECK() \
23 do { \
24 if (!_shared->statistics().Initialized()) { \
25 _shared->SetLastError(VE_NOT_INITED, kTraceError); \
26 return -1; \
27 } \
28 } while (0)
29
30#define WEBRTC_VOICE_INIT_CHECK_BOOL() \
31 do { \
32 if (!_shared->statistics().Initialized()) { \
33 _shared->SetLastError(VE_NOT_INITED, kTraceError); \
34 return false; \
35 } \
36 } while (0)
37
niklase@google.com470e71d2011-07-07 08:21:25 +000038namespace webrtc {
39
sjlee@webrtc.org414fa7f2012-09-11 17:25:46 +000040#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
andrew@webrtc.org80124742012-03-08 17:54:24 +000041static const EcModes kDefaultEcMode = kEcAecm;
42#else
43static const EcModes kDefaultEcMode = kEcAec;
44#endif
45
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000046VoEAudioProcessing* VoEAudioProcessing::GetInterface(VoiceEngine* voiceEngine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000047#ifndef WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000048 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000049#else
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000050 if (NULL == voiceEngine) {
51 return NULL;
52 }
tommi@webrtc.org0989fb72013-02-15 15:07:32 +000053 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
tommi@webrtc.orga990e122012-04-26 15:28:22 +000054 s->AddRef();
55 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000056#endif
57}
58
59#ifdef WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API
tommi@webrtc.org851becd2012-04-04 14:57:19 +000060VoEAudioProcessingImpl::VoEAudioProcessingImpl(voe::SharedData* shared)
Jelena Marusic0d266052015-05-04 14:15:32 +020061 : _isAecMode(kDefaultEcMode == kEcAec), _shared(shared) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +000062 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000063 "VoEAudioProcessingImpl::VoEAudioProcessingImpl() - ctor");
niklase@google.com470e71d2011-07-07 08:21:25 +000064}
65
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000066VoEAudioProcessingImpl::~VoEAudioProcessingImpl() {
tommi@webrtc.org851becd2012-04-04 14:57:19 +000067 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000068 "VoEAudioProcessingImpl::~VoEAudioProcessingImpl() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +000069}
70
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000071int VoEAudioProcessingImpl::SetNsStatus(bool enable, NsModes mode) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +000072 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000073 "SetNsStatus(enable=%d, mode=%d)", enable, mode);
niklase@google.com470e71d2011-07-07 08:21:25 +000074#ifdef WEBRTC_VOICE_ENGINE_NR
tommi@webrtc.org851becd2012-04-04 14:57:19 +000075 if (!_shared->statistics().Initialized()) {
76 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000077 return -1;
78 }
niklase@google.com470e71d2011-07-07 08:21:25 +000079
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +000080 NoiseSuppression::Level nsLevel = kDefaultNsMode;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000081 switch (mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +000082 case kNsDefault:
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +000083 nsLevel = kDefaultNsMode;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000084 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000085 case kNsUnchanged:
tommi@webrtc.org851becd2012-04-04 14:57:19 +000086 nsLevel = _shared->audio_processing()->noise_suppression()->level();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000087 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000088 case kNsConference:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000089 nsLevel = NoiseSuppression::kHigh;
90 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000091 case kNsLowSuppression:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000092 nsLevel = NoiseSuppression::kLow;
93 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000094 case kNsModerateSuppression:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000095 nsLevel = NoiseSuppression::kModerate;
96 break;
niklase@google.com470e71d2011-07-07 08:21:25 +000097 case kNsHighSuppression:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +000098 nsLevel = NoiseSuppression::kHigh;
99 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000100 case kNsVeryHighSuppression:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000101 nsLevel = NoiseSuppression::kVeryHigh;
102 break;
103 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
Jelena Marusic0d266052015-05-04 14:15:32 +0200105 if (_shared->audio_processing()->noise_suppression()->set_level(nsLevel) !=
106 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000107 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200108 "SetNsStatus() failed to set Ns mode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000110 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000111 if (_shared->audio_processing()->noise_suppression()->Enable(enable) != 0) {
112 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200113 "SetNsStatus() failed to set Ns state");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000114 return -1;
115 }
116
117 return 0;
118#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000119 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200120 "SetNsStatus() Ns is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000121 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000122#endif
123}
124
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000125int VoEAudioProcessingImpl::GetNsStatus(bool& enabled, NsModes& mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000126#ifdef WEBRTC_VOICE_ENGINE_NR
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000127 if (!_shared->statistics().Initialized()) {
128 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000130 }
131
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +0000132 enabled = _shared->audio_processing()->noise_suppression()->is_enabled();
133 NoiseSuppression::Level nsLevel =
134 _shared->audio_processing()->noise_suppression()->level();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000135
136 switch (nsLevel) {
137 case NoiseSuppression::kLow:
138 mode = kNsLowSuppression;
139 break;
140 case NoiseSuppression::kModerate:
141 mode = kNsModerateSuppression;
142 break;
143 case NoiseSuppression::kHigh:
144 mode = kNsHighSuppression;
145 break;
146 case NoiseSuppression::kVeryHigh:
147 mode = kNsVeryHighSuppression;
148 break;
149 }
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000150 return 0;
151#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000152 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200153 "GetNsStatus() Ns is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000154 return -1;
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000155#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000156}
157
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000158int VoEAudioProcessingImpl::SetAgcStatus(bool enable, AgcModes mode) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000159 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000160 "SetAgcStatus(enable=%d, mode=%d)", enable, mode);
niklase@google.com470e71d2011-07-07 08:21:25 +0000161#ifdef WEBRTC_VOICE_ENGINE_AGC
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000162 if (!_shared->statistics().Initialized()) {
163 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000164 return -1;
165 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
sjlee@webrtc.org414fa7f2012-09-11 17:25:46 +0000167#if defined(WEBRTC_IOS) || defined(ATA) || defined(WEBRTC_ANDROID)
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000168 if (mode == kAgcAdaptiveAnalog) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000169 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200170 "SetAgcStatus() invalid Agc mode for mobile device");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000171 return -1;
172 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000173#endif
174
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +0000175 GainControl::Mode agcMode = kDefaultAgcMode;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000176 switch (mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 case kAgcDefault:
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +0000178 agcMode = kDefaultAgcMode;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000179 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 case kAgcUnchanged:
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +0000181 agcMode = _shared->audio_processing()->gain_control()->mode();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000182 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183 case kAgcFixedDigital:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000184 agcMode = GainControl::kFixedDigital;
185 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 case kAgcAdaptiveAnalog:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000187 agcMode = GainControl::kAdaptiveAnalog;
188 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189 case kAgcAdaptiveDigital:
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000190 agcMode = GainControl::kAdaptiveDigital;
191 break;
192 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000193
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000194 if (_shared->audio_processing()->gain_control()->set_mode(agcMode) != 0) {
195 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200196 "SetAgcStatus() failed to set Agc mode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000197 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000198 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000199 if (_shared->audio_processing()->gain_control()->Enable(enable) != 0) {
200 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200201 "SetAgcStatus() failed to set Agc state");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000202 return -1;
203 }
204
205 if (agcMode != GainControl::kFixedDigital) {
206 // Set Agc state in the ADM when adaptive Agc mode has been selected.
207 // Note that we also enable the ADM Agc when Adaptive Digital mode is
208 // used since we want to be able to provide the APM with updated mic
209 // levels when the user modifies the mic level manually.
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000210 if (_shared->audio_device()->SetAGC(enable) != 0) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200211 _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
212 "SetAgcStatus() failed to set Agc mode");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000213 }
214 }
215
216 return 0;
217#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000218 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200219 "SetAgcStatus() Agc is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000220 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221#endif
222}
223
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000224int VoEAudioProcessingImpl::GetAgcStatus(bool& enabled, AgcModes& mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000225#ifdef WEBRTC_VOICE_ENGINE_AGC
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000226 if (!_shared->statistics().Initialized()) {
227 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000229 }
230
andrew@webrtc.orgf0a90c32013-03-05 01:12:49 +0000231 enabled = _shared->audio_processing()->gain_control()->is_enabled();
sjlee@webrtc.orgb4c441a2013-03-25 11:12:20 +0000232 GainControl::Mode agcMode =
Jelena Marusic0d266052015-05-04 14:15:32 +0200233 _shared->audio_processing()->gain_control()->mode();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000234
235 switch (agcMode) {
236 case GainControl::kFixedDigital:
237 mode = kAgcFixedDigital;
238 break;
239 case GainControl::kAdaptiveAnalog:
240 mode = kAgcAdaptiveAnalog;
241 break;
242 case GainControl::kAdaptiveDigital:
243 mode = kAgcAdaptiveDigital;
244 break;
245 }
246
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000247 return 0;
248#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000249 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200250 "GetAgcStatus() Agc is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000251 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000252#endif
253}
254
pbos@webrtc.org92135212013-05-14 08:31:39 +0000255int VoEAudioProcessingImpl::SetAgcConfig(AgcConfig config) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000256 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000257 "SetAgcConfig()");
niklase@google.com470e71d2011-07-07 08:21:25 +0000258#ifdef WEBRTC_VOICE_ENGINE_AGC
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000259 if (!_shared->statistics().Initialized()) {
260 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000261 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000262 }
263
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000264 if (_shared->audio_processing()->gain_control()->set_target_level_dbfs(
Jelena Marusic0d266052015-05-04 14:15:32 +0200265 config.targetLeveldBOv) != 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000266 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200267 "SetAgcConfig() failed to set target peak |level|"
268 " (or envelope) of the Agc");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000269 return -1;
270 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000271 if (_shared->audio_processing()->gain_control()->set_compression_gain_db(
Jelena Marusic0d266052015-05-04 14:15:32 +0200272 config.digitalCompressionGaindB) != 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000273 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200274 "SetAgcConfig() failed to set the range in |gain| "
275 "the digital compression stage may apply");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000276 return -1;
277 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000278 if (_shared->audio_processing()->gain_control()->enable_limiter(
Jelena Marusic0d266052015-05-04 14:15:32 +0200279 config.limiterEnable) != 0) {
280 _shared->SetLastError(
281 VE_APM_ERROR, kTraceError,
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000282 "SetAgcConfig() failed to set hard limiter to the signal");
283 return -1;
284 }
285
286 return 0;
287#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000288 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200289 "SetAgcConfig() EC is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000290 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000291#endif
292}
293
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000294int VoEAudioProcessingImpl::GetAgcConfig(AgcConfig& config) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000295#ifdef WEBRTC_VOICE_ENGINE_AGC
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000296 if (!_shared->statistics().Initialized()) {
297 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000298 return -1;
299 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000300
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000301 config.targetLeveldBOv =
Jelena Marusic0d266052015-05-04 14:15:32 +0200302 _shared->audio_processing()->gain_control()->target_level_dbfs();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000303 config.digitalCompressionGaindB =
Jelena Marusic0d266052015-05-04 14:15:32 +0200304 _shared->audio_processing()->gain_control()->compression_gain_db();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000305 config.limiterEnable =
Jelena Marusic0d266052015-05-04 14:15:32 +0200306 _shared->audio_processing()->gain_control()->is_limiter_enabled();
niklase@google.com470e71d2011-07-07 08:21:25 +0000307
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000308 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000310 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200311 "GetAgcConfig() EC is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000312 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313#endif
314}
315
andrew@webrtc.org55c0d4a2012-08-29 02:13:12 +0000316bool VoEAudioProcessing::DriftCompensationSupported() {
317#if defined(WEBRTC_DRIFT_COMPENSATION_SUPPORTED)
318 return true;
319#else
320 return false;
321#endif
322}
323
324int VoEAudioProcessingImpl::EnableDriftCompensation(bool enable) {
andrew@webrtc.org55c0d4a2012-08-29 02:13:12 +0000325 WEBRTC_VOICE_INIT_CHECK();
326
327 if (!DriftCompensationSupported()) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200328 _shared->SetLastError(
329 VE_APM_ERROR, kTraceWarning,
andrew@webrtc.org55c0d4a2012-08-29 02:13:12 +0000330 "Drift compensation is not supported on this platform.");
331 return -1;
332 }
333
334 EchoCancellation* aec = _shared->audio_processing()->echo_cancellation();
335 if (aec->enable_drift_compensation(enable) != 0) {
336 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200337 "aec->enable_drift_compensation() failed");
andrew@webrtc.org55c0d4a2012-08-29 02:13:12 +0000338 return -1;
339 }
340 return 0;
341}
342
343bool VoEAudioProcessingImpl::DriftCompensationEnabled() {
andrew@webrtc.org55c0d4a2012-08-29 02:13:12 +0000344 WEBRTC_VOICE_INIT_CHECK_BOOL();
345
346 EchoCancellation* aec = _shared->audio_processing()->echo_cancellation();
347 return aec->is_drift_compensation_enabled();
348}
349
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000350int VoEAudioProcessingImpl::SetEcStatus(bool enable, EcModes mode) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000351 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000352 "SetEcStatus(enable=%d, mode=%d)", enable, mode);
niklase@google.com470e71d2011-07-07 08:21:25 +0000353#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000354 if (!_shared->statistics().Initialized()) {
355 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000356 return -1;
357 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000359 // AEC mode
Jelena Marusic0d266052015-05-04 14:15:32 +0200360 if ((mode == kEcDefault) || (mode == kEcConference) || (mode == kEcAec) ||
361 ((mode == kEcUnchanged) && (_isAecMode == true))) {
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000362 if (enable) {
363 // Disable the AECM before enable the AEC
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000364 if (_shared->audio_processing()->echo_control_mobile()->is_enabled()) {
365 _shared->SetLastError(VE_APM_ERROR, kTraceWarning,
Jelena Marusic0d266052015-05-04 14:15:32 +0200366 "SetEcStatus() disable AECM before enabling AEC");
367 if (_shared->audio_processing()->echo_control_mobile()->Enable(false) !=
368 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000369 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200370 "SetEcStatus() failed to disable AECM");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000371 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000372 }
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000373 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000375 if (_shared->audio_processing()->echo_cancellation()->Enable(enable) != 0) {
376 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200377 "SetEcStatus() failed to set AEC state");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000378 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000379 }
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000380 if (mode == kEcConference) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200381 if (_shared->audio_processing()
382 ->echo_cancellation()
383 ->set_suppression_level(EchoCancellation::kHighSuppression) !=
384 0) {
385 _shared->SetLastError(
386 VE_APM_ERROR, kTraceError,
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000387 "SetEcStatus() failed to set aggressiveness to high");
niklase@google.com470e71d2011-07-07 08:21:25 +0000388 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000389 }
390 } else {
Jelena Marusic0d266052015-05-04 14:15:32 +0200391 if (_shared->audio_processing()
392 ->echo_cancellation()
393 ->set_suppression_level(EchoCancellation::kModerateSuppression) !=
394 0) {
395 _shared->SetLastError(
396 VE_APM_ERROR, kTraceError,
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000397 "SetEcStatus() failed to set aggressiveness to moderate");
niklase@google.com470e71d2011-07-07 08:21:25 +0000398 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000399 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000400 }
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000401
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000402 _isAecMode = true;
403 } else if ((mode == kEcAecm) ||
Jelena Marusic0d266052015-05-04 14:15:32 +0200404 ((mode == kEcUnchanged) && (_isAecMode == false))) {
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000405 if (enable) {
406 // Disable the AEC before enable the AECM
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000407 if (_shared->audio_processing()->echo_cancellation()->is_enabled()) {
408 _shared->SetLastError(VE_APM_ERROR, kTraceWarning,
Jelena Marusic0d266052015-05-04 14:15:32 +0200409 "SetEcStatus() disable AEC before enabling AECM");
410 if (_shared->audio_processing()->echo_cancellation()->Enable(false) !=
411 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000412 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200413 "SetEcStatus() failed to disable AEC");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000414 return -1;
415 }
416 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000417 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200418 if (_shared->audio_processing()->echo_control_mobile()->Enable(enable) !=
419 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000420 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200421 "SetEcStatus() failed to set AECM state");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000422 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 }
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000424 _isAecMode = false;
425 } else {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000426 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200427 "SetEcStatus() invalid EC mode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000428 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000429 }
430
431 return 0;
432#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000433 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200434 "SetEcStatus() EC is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000435 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000436#endif
437}
438
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000439int VoEAudioProcessingImpl::GetEcStatus(bool& enabled, EcModes& mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000440#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000441 if (!_shared->statistics().Initialized()) {
442 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000444 }
445
446 if (_isAecMode == true) {
447 mode = kEcAec;
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000448 enabled = _shared->audio_processing()->echo_cancellation()->is_enabled();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000449 } else {
450 mode = kEcAecm;
Jelena Marusic0d266052015-05-04 14:15:32 +0200451 enabled = _shared->audio_processing()->echo_control_mobile()->is_enabled();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000452 }
453
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000454 return 0;
455#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000456 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200457 "GetEcStatus() EC is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000458 return -1;
459#endif
460}
461
462void VoEAudioProcessingImpl::SetDelayOffsetMs(int offset) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000463 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000464 "SetDelayOffsetMs(offset = %d)", offset);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000465 _shared->audio_processing()->set_delay_offset_ms(offset);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000466}
467
468int VoEAudioProcessingImpl::DelayOffsetMs() {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000469 return _shared->audio_processing()->delay_offset_ms();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000470}
471
472int VoEAudioProcessingImpl::SetAecmMode(AecmModes mode, bool enableCNG) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000473 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000474 "SetAECMMode(mode = %d)", mode);
475#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000476 if (!_shared->statistics().Initialized()) {
477 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000478 return -1;
479 }
480
481 EchoControlMobile::RoutingMode aecmMode(
482 EchoControlMobile::kQuietEarpieceOrHeadset);
483
484 switch (mode) {
485 case kAecmQuietEarpieceOrHeadset:
486 aecmMode = EchoControlMobile::kQuietEarpieceOrHeadset;
487 break;
488 case kAecmEarpiece:
489 aecmMode = EchoControlMobile::kEarpiece;
490 break;
491 case kAecmLoudEarpiece:
492 aecmMode = EchoControlMobile::kLoudEarpiece;
493 break;
494 case kAecmSpeakerphone:
495 aecmMode = EchoControlMobile::kSpeakerphone;
496 break;
497 case kAecmLoudSpeakerphone:
498 aecmMode = EchoControlMobile::kLoudSpeakerphone;
499 break;
500 }
501
Jelena Marusic0d266052015-05-04 14:15:32 +0200502 if (_shared->audio_processing()->echo_control_mobile()->set_routing_mode(
503 aecmMode) != 0) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000504 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200505 "SetAECMMode() failed to set AECM routing mode");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000506 return -1;
507 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200508 if (_shared->audio_processing()->echo_control_mobile()->enable_comfort_noise(
509 enableCNG) != 0) {
510 _shared->SetLastError(
511 VE_APM_ERROR, kTraceError,
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000512 "SetAECMMode() failed to set comfort noise state for AECM");
513 return -1;
514 }
515
516 return 0;
517#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000518 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200519 "SetAECMMode() EC is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000520 return -1;
521#endif
522}
523
524int VoEAudioProcessingImpl::GetAecmMode(AecmModes& mode, bool& enabledCNG) {
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000525#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000526 if (!_shared->statistics().Initialized()) {
527 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000528 return -1;
529 }
530
531 enabledCNG = false;
532
533 EchoControlMobile::RoutingMode aecmMode =
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000534 _shared->audio_processing()->echo_control_mobile()->routing_mode();
Jelena Marusic0d266052015-05-04 14:15:32 +0200535 enabledCNG = _shared->audio_processing()
536 ->echo_control_mobile()
537 ->is_comfort_noise_enabled();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000538
539 switch (aecmMode) {
540 case EchoControlMobile::kQuietEarpieceOrHeadset:
541 mode = kAecmQuietEarpieceOrHeadset;
542 break;
543 case EchoControlMobile::kEarpiece:
544 mode = kAecmEarpiece;
545 break;
546 case EchoControlMobile::kLoudEarpiece:
547 mode = kAecmLoudEarpiece;
548 break;
549 case EchoControlMobile::kSpeakerphone:
550 mode = kAecmSpeakerphone;
551 break;
552 case EchoControlMobile::kLoudSpeakerphone:
553 mode = kAecmLoudSpeakerphone;
554 break;
555 }
556
557 return 0;
558#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000559 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200560 "GetAECMMode() EC is not supported");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000561 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000562#endif
563}
564
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000565int VoEAudioProcessingImpl::EnableHighPassFilter(bool enable) {
566 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
567 "EnableHighPassFilter(%d)", enable);
568 if (_shared->audio_processing()->high_pass_filter()->Enable(enable) !=
569 AudioProcessing::kNoError) {
570 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200571 "HighPassFilter::Enable() failed.");
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000572 return -1;
573 }
574
575 return 0;
576}
577
578bool VoEAudioProcessingImpl::IsHighPassFilterEnabled() {
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000579 return _shared->audio_processing()->high_pass_filter()->is_enabled();
580}
581
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000582int VoEAudioProcessingImpl::VoiceActivityIndicator(int channel) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000583 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000584 "VoiceActivityIndicator(channel=%d)", channel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000585 if (!_shared->statistics().Initialized()) {
586 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000587 return -1;
588 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000590 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
591 voe::Channel* channelPtr = ch.channel();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000592 if (channelPtr == NULL) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000593 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
solenberg11ace152016-09-15 04:29:13 -0700594 "VoiceActivityIndicator() failed to locate channel");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000595 return -1;
596 }
597 int activity(-1);
598 channelPtr->VoiceActivityIndicator(activity);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000600 return activity;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000603int VoEAudioProcessingImpl::SetEcMetricsStatus(bool enable) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000604 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000605 "SetEcMetricsStatus(enable=%d)", enable);
bjornv@google.com0beae672011-09-28 14:08:19 +0000606#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000607 if (!_shared->statistics().Initialized()) {
608 _shared->SetLastError(VE_NOT_INITED, kTraceError);
bjornv@google.com0beae672011-09-28 14:08:19 +0000609 return -1;
610 }
611
Jelena Marusic0d266052015-05-04 14:15:32 +0200612 if ((_shared->audio_processing()->echo_cancellation()->enable_metrics(
613 enable) != 0) ||
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000614 (_shared->audio_processing()->echo_cancellation()->enable_delay_logging(
Jelena Marusic0d266052015-05-04 14:15:32 +0200615 enable) != 0)) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000616 _shared->SetLastError(VE_APM_ERROR, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200617 "SetEcMetricsStatus() unable to set EC metrics mode");
bjornv@google.com0beae672011-09-28 14:08:19 +0000618 return -1;
619 }
620 return 0;
621#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000622 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200623 "SetEcStatus() EC is not supported");
bjornv@google.com0beae672011-09-28 14:08:19 +0000624 return -1;
625#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000626}
627
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000628int VoEAudioProcessingImpl::GetEcMetricsStatus(bool& enabled) {
bjornv@google.com0beae672011-09-28 14:08:19 +0000629#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000630 if (!_shared->statistics().Initialized()) {
631 _shared->SetLastError(VE_NOT_INITED, kTraceError);
bjornv@google.com0beae672011-09-28 14:08:19 +0000632 return -1;
633 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000635 bool echo_mode =
Jelena Marusic0d266052015-05-04 14:15:32 +0200636 _shared->audio_processing()->echo_cancellation()->are_metrics_enabled();
637 bool delay_mode = _shared->audio_processing()
638 ->echo_cancellation()
639 ->is_delay_logging_enabled();
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000640
641 if (echo_mode != delay_mode) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200642 _shared->SetLastError(
643 VE_APM_ERROR, kTraceError,
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000644 "GetEcMetricsStatus() delay logging and echo mode are not the same");
645 return -1;
646 }
647
648 enabled = echo_mode;
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
bjornv@google.com0beae672011-09-28 14:08:19 +0000650 return 0;
651#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000652 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200653 "SetEcStatus() EC is not supported");
bjornv@google.com0beae672011-09-28 14:08:19 +0000654 return -1;
655#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000656}
657
658int VoEAudioProcessingImpl::GetEchoMetrics(int& ERL,
659 int& ERLE,
660 int& RERL,
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000661 int& A_NLP) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000662#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000663 if (!_shared->statistics().Initialized()) {
664 _shared->SetLastError(VE_NOT_INITED, kTraceError);
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000665 return -1;
666 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000667 if (!_shared->audio_processing()->echo_cancellation()->is_enabled()) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200668 _shared->SetLastError(
669 VE_APM_ERROR, kTraceWarning,
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000670 "GetEchoMetrics() AudioProcessingModule AEC is not enabled");
671 return -1;
672 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000673
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000674 // Get Echo Metrics from Audio Processing Module.
675 EchoCancellation::Metrics echoMetrics;
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000676 if (_shared->audio_processing()->echo_cancellation()->GetMetrics(
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000677 &echoMetrics)) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000678 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_shared->instance_id(), -1),
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000679 "GetEchoMetrics(), AudioProcessingModule metrics error");
680 return -1;
681 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000682
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000683 // Echo quality metrics.
684 ERL = echoMetrics.echo_return_loss.instant;
685 ERLE = echoMetrics.echo_return_loss_enhancement.instant;
686 RERL = echoMetrics.residual_echo_return_loss.instant;
687 A_NLP = echoMetrics.a_nlp.instant;
niklase@google.com470e71d2011-07-07 08:21:25 +0000688
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000689 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000690#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000691 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200692 "SetEcStatus() EC is not supported");
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000693 return -1;
694#endif
695}
696
697int VoEAudioProcessingImpl::GetEcDelayMetrics(int& delay_median,
bjornv@webrtc.orgcc64a9c2015-02-05 12:52:44 +0000698 int& delay_std,
699 float& fraction_poor_delays) {
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000700#ifdef WEBRTC_VOICE_ENGINE_ECHO
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000701 if (!_shared->statistics().Initialized()) {
702 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000703 return -1;
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000704 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000705 if (!_shared->audio_processing()->echo_cancellation()->is_enabled()) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200706 _shared->SetLastError(
707 VE_APM_ERROR, kTraceWarning,
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000708 "GetEcDelayMetrics() AudioProcessingModule AEC is not enabled");
709 return -1;
710 }
711
712 int median = 0;
713 int std = 0;
bjornv@webrtc.orgcc64a9c2015-02-05 12:52:44 +0000714 float poor_fraction = 0;
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000715 // Get delay-logging values from Audio Processing Module.
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000716 if (_shared->audio_processing()->echo_cancellation()->GetDelayMetrics(
Jelena Marusic0d266052015-05-04 14:15:32 +0200717 &median, &std, &poor_fraction)) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000718 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_shared->instance_id(), -1),
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000719 "GetEcDelayMetrics(), AudioProcessingModule delay-logging "
720 "error");
721 return -1;
722 }
723
724 // EC delay-logging metrics
725 delay_median = median;
726 delay_std = std;
bjornv@webrtc.orgcc64a9c2015-02-05 12:52:44 +0000727 fraction_poor_delays = poor_fraction;
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000728
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000729 return 0;
730#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000731 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200732 "SetEcStatus() EC is not supported");
bjornv@webrtc.org3765bd22011-10-17 08:49:23 +0000733 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000734#endif
735}
736
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000737int VoEAudioProcessingImpl::StartDebugRecording(const char* fileNameUTF8) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000738 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000739 "StartDebugRecording()");
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000740 if (!_shared->statistics().Initialized()) {
741 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000742 return -1;
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000743 }
744
ivocd66b44d2016-01-15 03:06:36 -0800745 return _shared->audio_processing()->StartDebugRecording(fileNameUTF8, -1);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000746}
747
henrikg@webrtc.org863b5362013-12-06 16:05:17 +0000748int VoEAudioProcessingImpl::StartDebugRecording(FILE* file_handle) {
749 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
750 "StartDebugRecording()");
751 if (!_shared->statistics().Initialized()) {
752 _shared->SetLastError(VE_NOT_INITED, kTraceError);
753 return -1;
754 }
755
ivocd66b44d2016-01-15 03:06:36 -0800756 return _shared->audio_processing()->StartDebugRecording(file_handle, -1);
henrikg@webrtc.org863b5362013-12-06 16:05:17 +0000757}
758
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000759int VoEAudioProcessingImpl::StopDebugRecording() {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000760 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000761 "StopDebugRecording()");
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000762 if (!_shared->statistics().Initialized()) {
763 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000764 return -1;
765 }
766
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000767 return _shared->audio_processing()->StopDebugRecording();
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000768}
769
770int VoEAudioProcessingImpl::SetTypingDetectionStatus(bool enable) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000771 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000772 "SetTypingDetectionStatus()");
andrew@webrtc.org0851df82013-06-19 17:03:47 +0000773#if !defined(WEBRTC_VOICE_ENGINE_TYPING_DETECTION)
774 NOT_SUPPORTED(_shared->statistics());
775#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000776 if (!_shared->statistics().Initialized()) {
777 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000778 return -1;
779 }
780
781 // Just use the VAD state to determine if we should enable typing detection
782 // or not
783
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000784 if (_shared->audio_processing()->voice_detection()->Enable(enable)) {
785 _shared->SetLastError(VE_APM_ERROR, kTraceWarning,
Jelena Marusic0d266052015-05-04 14:15:32 +0200786 "SetTypingDetectionStatus() failed to set VAD state");
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000787 return -1;
788 }
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000789 if (_shared->audio_processing()->voice_detection()->set_likelihood(
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000790 VoiceDetection::kVeryLowLikelihood)) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200791 _shared->SetLastError(
792 VE_APM_ERROR, kTraceWarning,
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000793 "SetTypingDetectionStatus() failed to set VAD likelihood to low");
794 return -1;
795 }
796
797 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000798#endif
799}
800
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000801int VoEAudioProcessingImpl::GetTypingDetectionStatus(bool& enabled) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000802 if (!_shared->statistics().Initialized()) {
803 _shared->SetLastError(VE_NOT_INITED, kTraceError);
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000804 return -1;
805 }
806 // Just use the VAD state to determine if we should enable typing
807 // detection or not
niklase@google.com470e71d2011-07-07 08:21:25 +0000808
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000809 enabled = _shared->audio_processing()->voice_detection()->is_enabled();
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
andrew@webrtc.org8b111eb2012-03-06 19:50:12 +0000811 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000812}
813
Jelena Marusic0d266052015-05-04 14:15:32 +0200814int VoEAudioProcessingImpl::TimeSinceLastTyping(int& seconds) {
andrew@webrtc.org0851df82013-06-19 17:03:47 +0000815#if !defined(WEBRTC_VOICE_ENGINE_TYPING_DETECTION)
816 NOT_SUPPORTED(_shared->statistics());
817#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000818 if (!_shared->statistics().Initialized()) {
819 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklas.enbom@webrtc.org3dc88652012-03-30 09:53:54 +0000820 return -1;
821 }
822 // Check if typing detection is enabled
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000823 bool enabled = _shared->audio_processing()->voice_detection()->is_enabled();
Jelena Marusic0d266052015-05-04 14:15:32 +0200824 if (enabled) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000825 _shared->transmit_mixer()->TimeSinceLastTyping(seconds);
niklas.enbom@webrtc.org3dc88652012-03-30 09:53:54 +0000826 return 0;
Jelena Marusic0d266052015-05-04 14:15:32 +0200827 } else {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000828 _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
Jelena Marusic0d266052015-05-04 14:15:32 +0200829 "SetTypingDetectionStatus is not enabled");
830 return -1;
niklas.enbom@webrtc.org3dc88652012-03-30 09:53:54 +0000831 }
niklas.enbom@webrtc.org3dc88652012-03-30 09:53:54 +0000832#endif
niklas.enbom@webrtc.org3dc88652012-03-30 09:53:54 +0000833}
834
niklas.enbom@webrtc.org06e722a2012-04-04 07:44:27 +0000835int VoEAudioProcessingImpl::SetTypingDetectionParameters(int timeWindow,
836 int costPerTyping,
837 int reportingThreshold,
niklas.enbom@webrtc.orgf6edfef2012-05-09 13:16:12 +0000838 int penaltyDecay,
839 int typeEventDelay) {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000840 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklas.enbom@webrtc.org06e722a2012-04-04 07:44:27 +0000841 "SetTypingDetectionParameters()");
andrew@webrtc.org0851df82013-06-19 17:03:47 +0000842#if !defined(WEBRTC_VOICE_ENGINE_TYPING_DETECTION)
843 NOT_SUPPORTED(_shared->statistics());
844#else
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000845 if (!_shared->statistics().Initialized()) {
846 _shared->statistics().SetLastError(VE_NOT_INITED, kTraceError);
niklas.enbom@webrtc.org06e722a2012-04-04 07:44:27 +0000847 return -1;
848 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200849 return (_shared->transmit_mixer()->SetTypingDetectionParameters(
850 timeWindow, costPerTyping, reportingThreshold, penaltyDecay,
851 typeEventDelay));
niklas.enbom@webrtc.org06e722a2012-04-04 07:44:27 +0000852#endif
niklas.enbom@webrtc.org06e722a2012-04-04 07:44:27 +0000853}
854
andrew@webrtc.org02d71742012-04-24 19:47:00 +0000855void VoEAudioProcessingImpl::EnableStereoChannelSwapping(bool enable) {
andrew@webrtc.org02d71742012-04-24 19:47:00 +0000856 _shared->transmit_mixer()->EnableStereoChannelSwapping(enable);
857}
858
859bool VoEAudioProcessingImpl::IsStereoChannelSwappingEnabled() {
andrew@webrtc.org02d71742012-04-24 19:47:00 +0000860 return _shared->transmit_mixer()->IsStereoChannelSwappingEnabled();
861}
862
niklase@google.com470e71d2011-07-07 08:21:25 +0000863#endif // #ifdef WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API
864
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000865} // namespace webrtc