1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <cstddef>
18 #define LOG_TAG "PreProcessingContext"
19 #include <Utils.h>
20
21 #include "PreProcessingContext.h"
22
23 namespace aidl::android::hardware::audio::effect {
24
25 using aidl::android::media::audio::common::AudioDeviceDescription;
26 using aidl::android::media::audio::common::AudioDeviceType;
27
init(const Parameter::Common & common)28 RetCode PreProcessingContext::init(const Parameter::Common& common) {
29 webrtc::AudioProcessingBuilder apBuilder;
30 mAudioProcessingModule = apBuilder.Create();
31 if (mAudioProcessingModule == nullptr) {
32 LOG(ERROR) << "init could not get apm engine";
33 return RetCode::ERROR_EFFECT_LIB_ERROR;
34 }
35
36 updateConfigs(common);
37
38 mEnabledMsk = 0;
39 mProcessedMsk = 0;
40 mRevEnabledMsk = 0;
41 mRevProcessedMsk = 0;
42
43 auto config = mAudioProcessingModule->GetConfig();
44 switch (mType) {
45 case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
46 config.echo_canceller.mobile_mode = true;
47 break;
48 case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
49 config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
50 config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
51 config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
52 break;
53 case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
54 config.gain_controller2.fixed_digital.gain_db = 0.f;
55 break;
56 case PreProcessingEffectType::NOISE_SUPPRESSION:
57 config.noise_suppression.level = kNsDefaultLevel;
58 break;
59 }
60 mAudioProcessingModule->ApplyConfig(config);
61 mState = PRE_PROC_STATE_INITIALIZED;
62 return RetCode::SUCCESS;
63 }
64
deInit()65 RetCode PreProcessingContext::deInit() {
66 mAudioProcessingModule = nullptr;
67 mState = PRE_PROC_STATE_UNINITIALIZED;
68 return RetCode::SUCCESS;
69 }
70
enable()71 RetCode PreProcessingContext::enable() {
72 if (mState != PRE_PROC_STATE_INITIALIZED) {
73 return RetCode::ERROR_EFFECT_LIB_ERROR;
74 }
75 int typeMsk = (1 << int(mType));
76 // Check if effect is already enabled.
77 if ((mEnabledMsk & typeMsk) == typeMsk) {
78 return RetCode::ERROR_ILLEGAL_PARAMETER;
79 }
80 mEnabledMsk |= typeMsk;
81 auto config = mAudioProcessingModule->GetConfig();
82 switch (mType) {
83 case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
84 config.echo_canceller.enabled = true;
85 // AEC has reverse stream
86 mRevEnabledMsk |= typeMsk;
87 mRevProcessedMsk = 0;
88 break;
89 case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
90 config.gain_controller1.enabled = true;
91 break;
92 case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
93 config.gain_controller2.enabled = true;
94 break;
95 case PreProcessingEffectType::NOISE_SUPPRESSION:
96 config.noise_suppression.enabled = true;
97 break;
98 }
99 mProcessedMsk = 0;
100 mAudioProcessingModule->ApplyConfig(config);
101 mState = PRE_PROC_STATE_ACTIVE;
102 return RetCode::SUCCESS;
103 }
104
disable()105 RetCode PreProcessingContext::disable() {
106 if (mState != PRE_PROC_STATE_ACTIVE) {
107 return RetCode::ERROR_EFFECT_LIB_ERROR;
108 }
109 int typeMsk = (1 << int(mType));
110 // Check if effect is already disabled.
111 if ((mEnabledMsk & typeMsk) != typeMsk) {
112 return RetCode::ERROR_ILLEGAL_PARAMETER;
113 }
114 mEnabledMsk &= ~typeMsk;
115 auto config = mAudioProcessingModule->GetConfig();
116 switch (mType) {
117 case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
118 config.echo_canceller.enabled = false;
119 // AEC has reverse stream
120 mRevEnabledMsk &= ~typeMsk;
121 mRevProcessedMsk = 0;
122 break;
123 case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
124 config.gain_controller1.enabled = false;
125 break;
126 case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
127 config.gain_controller2.enabled = false;
128 break;
129 case PreProcessingEffectType::NOISE_SUPPRESSION:
130 config.noise_suppression.enabled = false;
131 break;
132 }
133 mProcessedMsk = 0;
134 mAudioProcessingModule->ApplyConfig(config);
135 mState = PRE_PROC_STATE_INITIALIZED;
136 return RetCode::SUCCESS;
137 }
138
setCommon(const Parameter::Common & common)139 RetCode PreProcessingContext::setCommon(const Parameter::Common& common) {
140 if(auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
141 return ret;
142 }
143 mCommon = common;
144 updateConfigs(common);
145 return RetCode::SUCCESS;
146 }
147
updateConfigs(const Parameter::Common & common)148 void PreProcessingContext::updateConfigs(const Parameter::Common& common) {
149 mInputConfig.set_sample_rate_hz(common.input.base.sampleRate);
150 mInputConfig.set_num_channels(::aidl::android::hardware::audio::common::getChannelCount(
151 common.input.base.channelMask));
152 mOutputConfig.set_sample_rate_hz(common.input.base.sampleRate);
153 mOutputConfig.set_num_channels(::aidl::android::hardware::audio::common::getChannelCount(
154 common.output.base.channelMask));
155 }
156
setAcousticEchoCancelerEchoDelay(int echoDelayUs)157 RetCode PreProcessingContext::setAcousticEchoCancelerEchoDelay(int echoDelayUs) {
158 mEchoDelayUs = echoDelayUs;
159 mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
160 return RetCode::SUCCESS;
161 }
162
getAcousticEchoCancelerEchoDelay() const163 int PreProcessingContext::getAcousticEchoCancelerEchoDelay() const {
164 return mEchoDelayUs;
165 }
166
setAcousticEchoCancelerMobileMode(bool mobileMode)167 RetCode PreProcessingContext::setAcousticEchoCancelerMobileMode(bool mobileMode) {
168 mMobileMode = mobileMode;
169 auto config = mAudioProcessingModule->GetConfig();
170 config.echo_canceller.mobile_mode = mobileMode;
171 mAudioProcessingModule->ApplyConfig(config);
172 return RetCode::SUCCESS;
173 }
174
getAcousticEchoCancelerMobileMode() const175 bool PreProcessingContext::getAcousticEchoCancelerMobileMode() const {
176 return mMobileMode;
177 }
178
setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel)179 RetCode PreProcessingContext::setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel) {
180 mTargetPeakLevel = targetPeakLevel;
181 auto config = mAudioProcessingModule->GetConfig();
182 config.gain_controller1.target_level_dbfs = -(mTargetPeakLevel / 100);
183 mAudioProcessingModule->ApplyConfig(config);
184 return RetCode::SUCCESS;
185 }
186
getAutomaticGainControlV1TargetPeakLevel() const187 int PreProcessingContext::getAutomaticGainControlV1TargetPeakLevel() const {
188 return mTargetPeakLevel;
189 }
190
setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain)191 RetCode PreProcessingContext::setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain) {
192 mMaxCompressionGain = maxCompressionGain;
193 auto config = mAudioProcessingModule->GetConfig();
194 config.gain_controller1.compression_gain_db = mMaxCompressionGain / 100;
195 mAudioProcessingModule->ApplyConfig(config);
196 return RetCode::SUCCESS;
197 }
198
getAutomaticGainControlV1MaxCompressionGain() const199 int PreProcessingContext::getAutomaticGainControlV1MaxCompressionGain() const {
200 return mMaxCompressionGain;
201 }
202
setAutomaticGainControlV1EnableLimiter(bool enableLimiter)203 RetCode PreProcessingContext::setAutomaticGainControlV1EnableLimiter(bool enableLimiter) {
204 mEnableLimiter = enableLimiter;
205 auto config = mAudioProcessingModule->GetConfig();
206 config.gain_controller1.enable_limiter = mEnableLimiter;
207 mAudioProcessingModule->ApplyConfig(config);
208 return RetCode::SUCCESS;
209 }
210
getAutomaticGainControlV1EnableLimiter() const211 bool PreProcessingContext::getAutomaticGainControlV1EnableLimiter() const {
212 return mEnableLimiter;
213 }
214
setAutomaticGainControlV2DigitalGain(int gain)215 RetCode PreProcessingContext::setAutomaticGainControlV2DigitalGain(int gain) {
216 mDigitalGain = gain;
217 auto config = mAudioProcessingModule->GetConfig();
218 config.gain_controller2.fixed_digital.gain_db = mDigitalGain;
219 mAudioProcessingModule->ApplyConfig(config);
220 return RetCode::SUCCESS;
221 }
222
getAutomaticGainControlV2DigitalGain() const223 int PreProcessingContext::getAutomaticGainControlV2DigitalGain() const {
224 return mDigitalGain;
225 }
226
setAutomaticGainControlV2LevelEstimator(AutomaticGainControlV2::LevelEstimator levelEstimator)227 RetCode PreProcessingContext::setAutomaticGainControlV2LevelEstimator(
228 AutomaticGainControlV2::LevelEstimator levelEstimator) {
229 mLevelEstimator = levelEstimator;
230 return RetCode::SUCCESS;
231 }
232
233 AutomaticGainControlV2::LevelEstimator
getAutomaticGainControlV2LevelEstimator() const234 PreProcessingContext::getAutomaticGainControlV2LevelEstimator() const {
235 return mLevelEstimator;
236 }
237
setAutomaticGainControlV2SaturationMargin(int saturationMargin)238 RetCode PreProcessingContext::setAutomaticGainControlV2SaturationMargin(int saturationMargin) {
239 mSaturationMargin = saturationMargin;
240 return RetCode::SUCCESS;
241 }
242
getAutomaticGainControlV2SaturationMargin() const243 int PreProcessingContext::getAutomaticGainControlV2SaturationMargin() const {
244 return mSaturationMargin;
245 }
246
setNoiseSuppressionLevel(NoiseSuppression::Level level)247 RetCode PreProcessingContext::setNoiseSuppressionLevel(NoiseSuppression::Level level) {
248 mLevel = level;
249 auto config = mAudioProcessingModule->GetConfig();
250 config.noise_suppression.level =
251 (webrtc::AudioProcessing::Config::NoiseSuppression::Level)level;
252 mAudioProcessingModule->ApplyConfig(config);
253 return RetCode::SUCCESS;
254 }
255
getNoiseSuppressionLevel() const256 NoiseSuppression::Level PreProcessingContext::getNoiseSuppressionLevel() const {
257 return mLevel;
258 }
259
process(float * in,float * out,int samples)260 IEffect::Status PreProcessingContext::process(float* in, float* out, int samples) {
261 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
262 RETURN_VALUE_IF(!in, status, "nullInput");
263 RETURN_VALUE_IF(!out, status, "nullOutput");
264 status = {EX_ILLEGAL_STATE, 0, 0};
265 int64_t inputFrameCount = getCommon().input.frameCount;
266 int64_t outputFrameCount = getCommon().output.frameCount;
267 RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
268 RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
269
270 mProcessedMsk |= (1 << int(mType));
271
272 // webrtc implementation clear out was_stream_delay_set every time after ProcessStream() call
273 mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
274
275 if ((mProcessedMsk & mEnabledMsk) == mEnabledMsk) {
276 mProcessedMsk = 0;
277 int processStatus = mAudioProcessingModule->ProcessStream(
278 (const int16_t* const)in, mInputConfig, mOutputConfig, (int16_t* const)out);
279 if (processStatus != 0) {
280 LOG(ERROR) << "Process stream failed with error " << processStatus;
281 return status;
282 }
283 }
284
285 mRevProcessedMsk |= (1 << int(mType));
286
287 if ((mRevProcessedMsk & mRevEnabledMsk) == mRevEnabledMsk) {
288 mRevProcessedMsk = 0;
289 int revProcessStatus = mAudioProcessingModule->ProcessReverseStream(
290 (const int16_t* const)in, mInputConfig, mInputConfig, (int16_t* const)out);
291 if (revProcessStatus != 0) {
292 LOG(ERROR) << "Process reverse stream failed with error " << revProcessStatus;
293 return status;
294 }
295 }
296
297 return {STATUS_OK, samples, samples};
298 }
299
300 } // namespace aidl::android::hardware::audio::effect
301