From 1089eb81878410416ba56bc2f3788a729985f5e9 Mon Sep 17 00:00:00 2001 From: anonymix007 <48598263+anonymix007@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:13:33 +0300 Subject: [PATCH] Implement AIDL IEffect ViPER library --- Android.bp | 117 +++++++++++++++++++++ src/ViPER4Aidl.cpp | 234 ++++++++++++++++++++++++++++++++++++++++++ src/ViPER4Aidl.h | 79 ++++++++++++++ src/ViPER4Android.cpp | 10 +- src/ViperContext.cpp | 8 +- src/ViperContext.h | 4 + 6 files changed, 446 insertions(+), 6 deletions(-) create mode 100644 Android.bp create mode 100644 src/ViPER4Aidl.cpp create mode 100644 src/ViPER4Aidl.h diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..26ea22c --- /dev/null +++ b/Android.bp @@ -0,0 +1,117 @@ +filegroup { + name: "v4aCommonFile", + srcs: [ + // Main + "src/viper/ViPER.cpp", + "src/ViperContext.cpp", + // Effects + "src/viper/effects/AnalogX.cpp", + "src/viper/effects/ColorfulMusic.cpp", + "src/viper/effects/Convolver.cpp", + "src/viper/effects/Cure.cpp", + "src/viper/effects/DiffSurround.cpp", + "src/viper/effects/DynamicSystem.cpp", + "src/viper/effects/FETCompressor.cpp", + "src/viper/effects/IIRFilter.cpp", + "src/viper/effects/PlaybackGain.cpp", + "src/viper/effects/Reverberation.cpp", + "src/viper/effects/SoftwareLimiter.cpp", + "src/viper/effects/SpeakerCorrection.cpp", + "src/viper/effects/SpectrumExtend.cpp", + "src/viper/effects/TubeSimulator.cpp", + "src/viper/effects/VHE.cpp", + "src/viper/effects/ViPERBass.cpp", + "src/viper/effects/ViPERClarity.cpp", + "src/viper/effects/ViPERDDC.cpp", + // Utils + "src/viper/utils/AdaptiveBuffer.cpp", + "src/viper/utils/Biquad.cpp", + "src/viper/utils/CAllpassFilter.cpp", + "src/viper/utils/CCombFilter.cpp", + "src/viper/utils/CRevModel.cpp", + "src/viper/utils/Crossfeed.cpp", + "src/viper/utils/DepthSurround.cpp", + "src/viper/utils/DynamicBass.cpp", + "src/viper/utils/FIR.cpp", + "src/viper/utils/Harmonic.cpp", + "src/viper/utils/HiFi.cpp", + "src/viper/utils/HighShelf.cpp", + "src/viper/utils/IIR_1st.cpp", + "src/viper/utils/IIR_NOrder_BW_BP.cpp", + "src/viper/utils/IIR_NOrder_BW_LH.cpp", + "src/viper/utils/MinPhaseIIRCoeffs.cpp", + "src/viper/utils/MultiBiquad.cpp", + "src/viper/utils/NoiseSharpening.cpp", + "src/viper/utils/PassFilter.cpp", + "src/viper/utils/PConvSingle.cpp", + "src/viper/utils/PolesFilter.cpp", + "src/viper/utils/Polyphase.cpp", + "src/viper/utils/Stereo3DSurround.cpp", + "src/viper/utils/Subwoofer.cpp", + "src/viper/utils/TimeConstDelay.cpp", + "src/viper/utils/WaveBuffer.cpp", + ], +} + +cc_defaults { + name: "v4aDefaults", + srcs: [ + ":v4aCommonFile", + ], + cflags: [ + "-O3", + "-DNDEBUG", + "-DVIPER_VERSION=20240314", + "-DAOSP_SOONG_BUILD", + ], + header_libs: [ + "libhardware_headers", + ], + lto: { + // TODO: full was removed in 0713e336d9898aad7c161e92b8d27096142b64b6 (build/soong) + thin: true, + }, +} + +cc_library_shared { + name: "libv4aidl_re", + vendor: true, + relative_install_path: "soundfx", + defaults: [ + "aidlaudioeffectservice_defaults", + "v4aDefaults", + ], + srcs: [ + "src/ViPER4Aidl.cpp", + // AOSP + ":effectCommonFile", + ], + cflags: [ + "-O3", + "-DNDEBUG", + "-DVIPER_VERSION=20240314", + "-DAOSP_SOONG_BUILD", + ], + shared_libs: [ + "libbinder", + ], + whole_static_libs: [ + "libaudio_aidl_conversion_common_ndk", + "libstagefright_foundation", + ], +} + +cc_library_shared { + name: "libv4a_re", + vendor: true, + relative_install_path: "soundfx", + defaults: [ + "v4aDefaults", + ], + srcs: [ + "src/ViPER4Android.cpp", + ], + shared_libs: [ + "liblog", + ], +} diff --git a/src/ViPER4Aidl.cpp b/src/ViPER4Aidl.cpp new file mode 100644 index 0000000..8a8075e --- /dev/null +++ b/src/ViPER4Aidl.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * 2024 anonymix007 + * + * 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 +#include + +#define LOG_TAG "ViPER4Aidl" +#include +#include +#include +#include +#include +template +using ConversionResult = ::android::error::Result; +#include + +#include "viper/constants.h" +#include "ViPER4Aidl.h" + +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::DefaultExtension; +using aidl::android::hardware::audio::effect::ViperAidl; +using aidl::android::hardware::audio::effect::getEffectImplUuidViper; +using aidl::android::hardware::audio::effect::getEffectUuidNull; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::State; +using aidl::android::hardware::audio::effect::VendorExtension; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidViper()) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created"; + return EX_NONE; + } else { + LOG(ERROR) << __func__ << " invalid input parameter!"; + return EX_ILLEGAL_ARGUMENT; + } +} + +extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) { + if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidViper()) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + *_aidl_return = ViperAidl::kDesc; + return EX_NONE; +} + +namespace aidl::android::hardware::audio::effect { + +const std::string ViperAidl::kEffectName = VIPER_NAME; + +const Descriptor ViperAidl::kDesc = {.common = {.id = {.type = getEffectUuidNull(), + .uuid = getEffectImplUuidViper()}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::LAST, + .volume = Flags::Volume::CTRL}, + .name = ViperAidl::kEffectName, + .implementor = VIPER_AUTHORS}}; + +ndk::ScopedAStatus ViperAidl::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDesc.toString(); + *_aidl_return = kDesc; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ViperAidl::setParameterSpecific(const Parameter::Specific& specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + // TODO: Handle Parameter::Common (EFFECT_CMD_SET_CONFIG) + RETURN_IF(Parameter::Specific::vendorEffect != specific.getTag(), EX_ILLEGAL_ARGUMENT, "EffectNotSupported"); + auto& vendorEffect = specific.get(); + std::optional defaultExt; + RETURN_IF(STATUS_OK != vendorEffect.extension.getParcelable(&defaultExt), EX_ILLEGAL_ARGUMENT, "getParcelableFailed"); + RETURN_IF(!defaultExt.has_value(), EX_ILLEGAL_ARGUMENT, "parcelableNull"); + + int32_t ret = 0; + uint32_t ret_size = sizeof(ret); + RETURN_IF(mContext->viperContext->handleCommand(EFFECT_CMD_SET_PARAM, defaultExt->bytes.size(), defaultExt->bytes.data(), &ret_size, &ret) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed"); + RETURN_IF(ret != 0, EX_ILLEGAL_ARGUMENT, "handleCommandInternalFailed"); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ViperAidl::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + // TODO: Handle Parameter::Common (EFFECT_CMD_GET_CONFIG) + RETURN_IF(Parameter::Id::vendorEffectTag != id.getTag(), EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + auto extensionId = id.get(); + std::optional defaultIdExt; + RETURN_IF(STATUS_OK != extensionId.extension.getParcelable(&defaultIdExt), EX_ILLEGAL_ARGUMENT, "getIdParcelableFailed"); + RETURN_IF(!defaultIdExt.has_value(), EX_ILLEGAL_ARGUMENT, "parcelableIdNull"); + + VendorExtension extension; + DefaultExtension defaultExt; + defaultExt.bytes.resize(sizeof(effect_param_t)); + uint32_t data_size = defaultExt.bytes.size(); + RETURN_IF(mContext->viperContext->handleCommand(EFFECT_CMD_GET_PARAM, defaultIdExt->bytes.size(), defaultIdExt->bytes.data(), &data_size, defaultExt.bytes.data()) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed"); + RETURN_IF(STATUS_OK != extension.extension.setParcelable(defaultExt), EX_ILLEGAL_ARGUMENT, "setParcelableFailed"); + specific->set(extension); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr ViperAidl::createContext(const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + } else { + mContext = std::make_shared(1 /* statusFmqDepth */, common); + int32_t ret = 0; + uint32_t ret_size = sizeof(ret); + int32_t status = mContext->viperContext->handleCommand(EFFECT_CMD_INIT, 0, NULL, &ret_size, &ret); + if (status < 0) { + LOG(ERROR) << __func__ << ": ViperContext::handleCommand failed: " << status; + mContext = nullptr; + return mContext; + } + if (ret < 0) { + LOG(ERROR) << __func__ << ": ViperContext::handleCommand failed (internal): " << ret; + mContext = nullptr; + return mContext; + } + ret = 0; + ret_size = sizeof(ret); + effect_config_t conf = {}; + + + auto tmp = ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.input, true); + if (tmp.ok()) { + conf.inputCfg = tmp.value(); + } else { + mContext = nullptr; + return mContext; + } + + tmp = ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.output, false); + if (tmp.ok()) { + conf.outputCfg = tmp.value(); + } else { + mContext = nullptr; + return mContext; + } + + status = mContext->viperContext->handleCommand(EFFECT_CMD_SET_CONFIG, sizeof(conf), &conf, &ret_size, &ret); + if (status < 0) { + LOG(ERROR) << __func__ << ": ViperContext::handleCommand failed: " << status; + mContext = nullptr; + return mContext; + } + if (ret < 0) { + LOG(ERROR) << __func__ << ": ViperContext::handleCommand failed (internal): " << ret; + mContext = nullptr; + return mContext; + } + } + + return mContext; +} + +ndk::ScopedAStatus ViperAidl::commandImpl(CommandId command) { + RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); + int32_t ret = 0; + uint32_t ret_size = sizeof(ret); + switch (command) { + case CommandId::START: + RETURN_IF(mContext->viperContext->handleCommand(EFFECT_CMD_ENABLE, 0, NULL, &ret_size, &ret) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed"); + RETURN_IF(ret != 0, EX_ILLEGAL_ARGUMENT, "handleCommandInternalFailed"); + break; + case CommandId::STOP: + RETURN_IF(mContext->viperContext->handleCommand(EFFECT_CMD_DISABLE, 0, NULL, &ret_size, &ret) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed"); + RETURN_IF(ret != 0, EX_ILLEGAL_ARGUMENT, "handleCommandInternalFailed"); + break; + case CommandId::RESET: + mImplContext->resetBuffer(); + break; + default: + break; + } + return ndk::ScopedAStatus::ok(); +} + + +RetCode ViperAidl::releaseContext() { + if (mContext) { + int32_t ret = 0; + uint32_t ret_size = sizeof(ret); + int32_t status = mContext->viperContext->handleCommand(EFFECT_CMD_RESET, 0, NULL, &ret_size, &ret); + if (status < 0) { + LOG(ERROR) << __func__ << ": ViperContext::handleCommand failed: " << status; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + if (ret < 0) { + LOG(ERROR) << __func__ << ": ViperContext::handleCommand failed (internal): " << ret; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status ViperAidl::effectProcessImpl(float* in_, float* out_, int samples) { + audio_buffer_t in{static_cast(samples), {in_}}, out{static_cast(samples), {out_}}; + LOG(DEBUG) << __func__ << " in " << in_ << " out " << out_ << " samples " << samples; + + switch(mContext->viperContext->process(&in, &out)) { + case 0: + return {STATUS_OK, samples, samples}; + case -ENODATA: + return {STATUS_NOT_ENOUGH_DATA, 0, 0}; + default: + return {STATUS_INVALID_OPERATION, 0, 0}; + } +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/src/ViPER4Aidl.h b/src/ViPER4Aidl.h new file mode 100644 index 0000000..ec8bf40 --- /dev/null +++ b/src/ViPER4Aidl.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * 2024 anonymix007 + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include "effect-impl/EffectImpl.h" + +#include "ViperContext.h" + +namespace aidl::android::hardware::audio::effect { + +class ViperAidlContext final : public EffectContext { + public: + ViperAidlContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common), + viperContext{} { + LOG(DEBUG) << __func__; + } + std::shared_ptr viperContext; +}; + +class ViperAidl final : public EffectImpl { + public: + static const std::string kEffectName; + static const Capability kEqCap; + static const Descriptor kDesc; + + ViperAidl() { LOG(DEBUG) << __func__; } + ~ViperAidl() { + cleanUp(); + LOG(DEBUG) << __func__; + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override; + ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) + REQUIRES(mImplMutex) override; + ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) + REQUIRES(mImplMutex) override; + + std::shared_ptr createContext(const Parameter::Common& common) + REQUIRES(mImplMutex) override; + ndk::ScopedAStatus commandImpl(CommandId id) REQUIRES(mImplMutex); + + RetCode releaseContext() REQUIRES(mImplMutex) override; + + IEffect::Status effectProcessImpl(float* in, float* out, int samples) + REQUIRES(mImplMutex) override; + std::string getEffectName() override { return kEffectName; } + + private: + std::shared_ptr mContext; +}; + +constexpr char kEffectImplUuidViper[] = "90380da3-8536-4744-a6a3-5731970e640f"; +inline const AudioUuid& getEffectImplUuidViper() { + static const ::android::base::NoDestructor uuid(stringToUuid(kEffectImplUuidViper)); + return *uuid; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/src/ViPER4Android.cpp b/src/ViPER4Android.cpp index 10217e7..e1a3fc1 100644 --- a/src/ViPER4Android.cpp +++ b/src/ViPER4Android.cpp @@ -1,6 +1,12 @@ #include -#include "viper/ViPER.h" + +#ifdef AOSP_SOONG_BUILD +#include +#else #include "essential.h" +#endif + +#include "viper/ViPER.h" #include "viper/constants.h" #include "ViperContext.h" @@ -89,4 +95,4 @@ audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { .release_effect = viperLibraryRelease, .get_descriptor = viperLibraryGetDescriptor, }; -} // extern "C" \ No newline at end of file +} // extern "C" diff --git a/src/ViperContext.cpp b/src/ViperContext.cpp index 414866e..c3cde95 100644 --- a/src/ViperContext.cpp +++ b/src/ViperContext.cpp @@ -38,9 +38,9 @@ void ViperContext::copyBufferConfig(buffer_config_t *dest, buffer_config_t *src) dest->accessMode = src->accessMode; } - if (src->mask & EFFECT_CONFIG_PROVIDER) { - dest->bufferProvider = src->bufferProvider; - } + //if (src->mask & EFFECT_CONFIG_PROVIDER) { + // dest->bufferProvider = src->bufferProvider; + //} dest->mask |= src->mask; } @@ -809,7 +809,7 @@ int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffe if (!enabled) { return -ENODATA; } - + inBuffer = getBuffer(&config.inputCfg, inBuffer); outBuffer = getBuffer(&config.outputCfg, outBuffer); if (inBuffer == nullptr || outBuffer == nullptr || diff --git a/src/ViperContext.h b/src/ViperContext.h index de05007..16e60e4 100644 --- a/src/ViperContext.h +++ b/src/ViperContext.h @@ -2,7 +2,11 @@ #include #include +#ifdef AOSP_SOONG_BUILD +#include +#else #include "essential.h" +#endif #include "viper/ViPER.h" #include