PreProcessing : Add libeffect pre-processing effects implementation

Bug: 258124419
Test: atest VtsHalAECTargetTest
Test: atest VtsHalAGC1TargetTest
Test: atest VtsHalAGC2TargetTest
Test: atest VtsHalNSTargetTest
Change-Id: Idfecf978b87419f54f1c930434821ba2a348d9dd
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
new file mode 100644
index 0000000..104277e
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+#define LOG_TAG "PreProcessingContext"
+#include <Utils.h>
+
+#include "PreProcessingContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+RetCode PreProcessingContext::init(const Parameter::Common& common) {
+    std::lock_guard lg(mMutex);
+    webrtc::AudioProcessingBuilder apBuilder;
+    mAudioProcessingModule = apBuilder.Create();
+    if (mAudioProcessingModule == nullptr) {
+        LOG(ERROR) << "init could not get apm engine";
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+
+    updateConfigs(common);
+
+    mEnabledMsk = 0;
+    mProcessedMsk = 0;
+    mRevEnabledMsk = 0;
+    mRevProcessedMsk = 0;
+
+    auto config = mAudioProcessingModule->GetConfig();
+    switch (mType) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            config.echo_canceller.mobile_mode = true;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
+            config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
+            config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            config.gain_controller2.fixed_digital.gain_db = 0.f;
+            break;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            config.noise_suppression.level = kNsDefaultLevel;
+            break;
+    }
+    mAudioProcessingModule->ApplyConfig(config);
+    mState = PRE_PROC_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::deInit() {
+    std::lock_guard lg(mMutex);
+    mAudioProcessingModule = nullptr;
+    mState = PRE_PROC_STATE_UNINITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::enable() {
+    if (mState != PRE_PROC_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    int typeMsk = (1 << int(mType));
+    std::lock_guard lg(mMutex);
+    // Check if effect is already enabled.
+    if ((mEnabledMsk & typeMsk) == typeMsk) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    mEnabledMsk |= typeMsk;
+    auto config = mAudioProcessingModule->GetConfig();
+    switch (mType) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            config.echo_canceller.enabled = true;
+            // AEC has reverse stream
+            mRevEnabledMsk |= typeMsk;
+            mRevProcessedMsk = 0;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            config.gain_controller1.enabled = true;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            config.gain_controller2.enabled = true;
+            break;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            config.noise_suppression.enabled = true;
+            break;
+    }
+    mProcessedMsk = 0;
+    mAudioProcessingModule->ApplyConfig(config);
+    mState = PRE_PROC_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::disable() {
+    if (mState != PRE_PROC_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    int typeMsk = (1 << int(mType));
+    std::lock_guard lg(mMutex);
+    // Check if effect is already disabled.
+    if ((mEnabledMsk & typeMsk) != typeMsk) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    mEnabledMsk &= ~typeMsk;
+    auto config = mAudioProcessingModule->GetConfig();
+    switch (mType) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            config.echo_canceller.enabled = false;
+            // AEC has reverse stream
+            mRevEnabledMsk &= ~typeMsk;
+            mRevProcessedMsk = 0;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            config.gain_controller1.enabled = false;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            config.gain_controller2.enabled = false;
+            break;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            config.noise_suppression.enabled = false;
+            break;
+    }
+    mProcessedMsk = 0;
+    mAudioProcessingModule->ApplyConfig(config);
+    mState = PRE_PROC_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::setCommon(const Parameter::Common& common) {
+    mCommon = common;
+    updateConfigs(common);
+    return RetCode::SUCCESS;
+}
+
+void PreProcessingContext::updateConfigs(const Parameter::Common& common) {
+    mInputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+    mInputConfig.set_num_channels(
+            ::android::hardware::audio::common::getChannelCount(common.input.base.channelMask));
+    mOutputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+    mOutputConfig.set_num_channels(
+            ::android::hardware::audio::common::getChannelCount(common.output.base.channelMask));
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerEchoDelay(int echoDelayUs) {
+    mEchoDelayUs = echoDelayUs;
+    std::lock_guard lg(mMutex);
+    mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAcousticEchoCancelerEchoDelay() const {
+    return mEchoDelayUs;
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerMobileMode(bool mobileMode) {
+    mMobileMode = mobileMode;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.echo_canceller.mobile_mode = mobileMode;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAcousticEchoCancelerMobileMode() const {
+    return mMobileMode;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel) {
+    mTargetPeakLevel = targetPeakLevel;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller1.target_level_dbfs = -(mTargetPeakLevel / 100);
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1TargetPeakLevel() const {
+    return mTargetPeakLevel;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain) {
+    mMaxCompressionGain = maxCompressionGain;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller1.compression_gain_db = mMaxCompressionGain / 100;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1MaxCompressionGain() const {
+    return mMaxCompressionGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1EnableLimiter(bool enableLimiter) {
+    mEnableLimiter = enableLimiter;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller1.enable_limiter = mEnableLimiter;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAutomaticGainControlV1EnableLimiter() const {
+    return mEnableLimiter;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2DigitalGain(int gain) {
+    mDigitalGain = gain;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller2.fixed_digital.gain_db = mDigitalGain;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2DigitalGain() const {
+    return mDigitalGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2LevelEstimator(
+        AutomaticGainControlV2::LevelEstimator levelEstimator) {
+    mLevelEstimator = levelEstimator;
+    return RetCode::SUCCESS;
+}
+
+AutomaticGainControlV2::LevelEstimator
+PreProcessingContext::getAutomaticGainControlV2LevelEstimator() const {
+    return mLevelEstimator;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2SaturationMargin(int saturationMargin) {
+    mSaturationMargin = saturationMargin;
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2SaturationMargin() const {
+    return mSaturationMargin;
+}
+
+RetCode PreProcessingContext::setNoiseSuppressionLevel(NoiseSuppression::Level level) {
+    mLevel = level;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.noise_suppression.level =
+            (webrtc::AudioProcessing::Config::NoiseSuppression::Level)level;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+NoiseSuppression::Level PreProcessingContext::getNoiseSuppressionLevel() const {
+    return mLevel;
+}
+
+IEffect::Status PreProcessingContext::lvmProcess(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    int64_t inputFrameCount = getCommon().input.frameCount;
+    int64_t outputFrameCount = getCommon().output.frameCount;
+    RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+    RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    std::lock_guard lg(mMutex);
+
+    mProcessedMsk |= (1 << int(mType));
+
+    // webrtc implementation clear out was_stream_delay_set every time after ProcessStream() call
+    mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+
+    if ((mProcessedMsk & mEnabledMsk) == mEnabledMsk) {
+        mProcessedMsk = 0;
+        int processStatus = mAudioProcessingModule->ProcessStream(
+                (const int16_t* const)in, mInputConfig, mOutputConfig, (int16_t* const)out);
+        if (processStatus != 0) {
+            LOG(ERROR) << "Process stream failed with error " << processStatus;
+            return status;
+        }
+    }
+
+    mRevProcessedMsk |= (1 << int(mType));
+
+    if ((mRevProcessedMsk & mRevEnabledMsk) == mRevEnabledMsk) {
+        mRevProcessedMsk = 0;
+        int revProcessStatus = mAudioProcessingModule->ProcessReverseStream(
+                (const int16_t* const)in, mInputConfig, mInputConfig, (int16_t* const)out);
+        if (revProcessStatus != 0) {
+            LOG(ERROR) << "Process reverse stream failed with error " << revProcessStatus;
+            return status;
+        }
+    }
+
+    return {STATUS_OK, samples, samples};
+}
+
+}  // namespace aidl::android::hardware::audio::effect