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