diff --git a/Android.bp b/Android.bp index c707935..623f61a 100644 --- a/Android.bp +++ b/Android.bp @@ -4,7 +4,7 @@ cc_defaults { srcs: [ // Main "src/viper/ViPER.cpp", - "src/ViperContext.cpp", + "src/ViPERContext.cpp", "src/ViPER4Aidl.cpp", "src/ViPER4Android.cpp", "src/EffectThread.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 868ab1c..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -cmake_minimum_required(VERSION 3.16.3) - -set(CMAKE_CXX_STANDARD 20) - -project("ViPER4Android") -add_compile_definitions(VIPER_VERSION=20240314) - -# ViPERFX -include_directories(src/include) - -set(FILES - # Main - src/viper/ViPER.cpp - src/ViPER4Android.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) - -add_library(v4a_re SHARED - ${FILES}) - -target_link_libraries(v4a_re log) -target_compile_options(v4a_re PRIVATE -flto -O3 -DNDEBUG) -#target_compile_options(v4afx_r PRIVATE -O2 -DNDEBUG -Wall -Wsign-conversion -Wno-unused-result -Wno-unneeded-internal-declaration -fstrict-aliasing -fvisibility=hidden -Wextra -Wno-unused-parameter) diff --git a/src/AidlUtils.h b/src/AidlUtils.h index e1beec4..64789a8 100644 --- a/src/AidlUtils.h +++ b/src/AidlUtils.h @@ -3,80 +3,79 @@ #include #include +using aidl::android::media::audio::common::AudioChannelLayout; +using aidl::android::media::audio::common::AudioFormatDescription; +using aidl::android::media::audio::common::AudioFormatType; using aidl::android::media::audio::common::AudioUuid; using aidl::android::media::audio::common::PcmType; -inline AudioUuid stringToUuid(const char* str) { - AudioUuid uuid{}; - uint32_t tmp[10]; - if (!str || sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", tmp, - tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5, tmp + 6, - tmp + 7, tmp + 8, tmp + 9) < 10) { +namespace ViPER4Android { + inline AudioUuid stringToUuid(const char *str) { + AudioUuid uuid{}; + uint32_t tmp[10]; + if (!str || sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", tmp, + tmp + 1, tmp + 2, tmp + 3, tmp + 4, tmp + 5, tmp + 6, + tmp + 7, tmp + 8, tmp + 9) < 10) { + return uuid; + } + + uuid.timeLow = (uint32_t) tmp[0]; + uuid.timeMid = (uint16_t) tmp[1]; + uuid.timeHiAndVersion = (uint16_t) tmp[2]; + uuid.clockSeq = (uint16_t) tmp[3]; + uuid.node.insert(uuid.node.end(), {(uint8_t) tmp[4], (uint8_t) tmp[5], (uint8_t) tmp[6], + (uint8_t) tmp[7], (uint8_t) tmp[8], (uint8_t) tmp[9]}); return uuid; } - uuid.timeLow = (uint32_t)tmp[0]; - uuid.timeMid = (uint16_t)tmp[1]; - uuid.timeHiAndVersion = (uint16_t)tmp[2]; - uuid.clockSeq = (uint16_t)tmp[3]; - uuid.node.insert(uuid.node.end(), {(uint8_t)tmp[4], (uint8_t)tmp[5], (uint8_t)tmp[6], - (uint8_t)tmp[7], (uint8_t)tmp[8], (uint8_t)tmp[9]}); - return uuid; -} - -constexpr size_t getPcmSampleSizeInBytes(::aidl::android::media::audio::common::PcmType pcm) { - using ::aidl::android::media::audio::common::PcmType; - switch (pcm) { - case PcmType::UINT_8_BIT: - return 1; - case PcmType::INT_16_BIT: - return 2; - case PcmType::INT_32_BIT: - return 4; - case PcmType::FIXED_Q_8_24: - return 4; - case PcmType::FLOAT_32_BIT: - return 4; - case PcmType::INT_24_BIT: - return 3; - } - return 0; -} - -constexpr size_t getChannelCount( - const ::aidl::android::media::audio::common::AudioChannelLayout& layout, - int32_t mask = std::numeric_limits::max()) { - using Tag = ::aidl::android::media::audio::common::AudioChannelLayout::Tag; - switch (layout.getTag()) { - case Tag::none: - return 0; - case Tag::invalid: - return 0; - case Tag::indexMask: - return __builtin_popcount(layout.get() & mask); - case Tag::layoutMask: - return __builtin_popcount(layout.get() & mask); - case Tag::voiceMask: - return __builtin_popcount(layout.get() & mask); - } - return 0; -} - -constexpr size_t getFrameSizeInBytes( - const ::aidl::android::media::audio::common::AudioFormatDescription& format, - const ::aidl::android::media::audio::common::AudioChannelLayout& layout) { - if (format == ::aidl::android::media::audio::common::AudioFormatDescription{}) { - // Unspecified format. + constexpr size_t getPcmSampleSizeInBytes(PcmType pcm) { + switch (pcm) { + case PcmType::UINT_8_BIT: + return 1; + case PcmType::INT_16_BIT: + return 2; + case PcmType::INT_32_BIT: + return 4; + case PcmType::FIXED_Q_8_24: + return 4; + case PcmType::FLOAT_32_BIT: + return 4; + case PcmType::INT_24_BIT: + return 3; + } return 0; } - using ::aidl::android::media::audio::common::AudioFormatType; - if (format.type == AudioFormatType::PCM) { - return getPcmSampleSizeInBytes(format.pcm) * getChannelCount(layout); - } else if (format.type == AudioFormatType::NON_PCM) { - // For non-PCM formats always use the underlying PCM size. The default value for - // PCM is "UINT_8_BIT", thus non-encapsulated streams have the frame size of 1. - return getPcmSampleSizeInBytes(format.pcm); + + constexpr size_t getChannelCount(const AudioChannelLayout &layout, + int32_t mask = std::numeric_limits::max()) { + switch (layout.getTag()) { + case AudioChannelLayout::Tag::none: + return 0; + case AudioChannelLayout::Tag::invalid: + return 0; + case AudioChannelLayout::Tag::indexMask: + return __builtin_popcount(layout.get() & mask); + case AudioChannelLayout::Tag::layoutMask: + return __builtin_popcount(layout.get() & mask); + case AudioChannelLayout::Tag::voiceMask: + return __builtin_popcount(layout.get() & mask); + } + return 0; } - // Something unexpected. - return 0; -} + + constexpr size_t getFrameSizeInBytes(const AudioFormatDescription &format, const AudioChannelLayout &layout) { + if (format == AudioFormatDescription{}) { + // Unspecified format. + return 0; + } + if (format.type == AudioFormatType::PCM) { + return getPcmSampleSizeInBytes(format.pcm) * getChannelCount(layout); + } else if (format.type == AudioFormatType::NON_PCM) { + // For non-PCM formats always use the underlying PCM size. The default value for + // PCM is "UINT_8_BIT", thus non-encapsulated streams have the frame size of 1. + return getPcmSampleSizeInBytes(format.pcm); + } + // Something unexpected. + return 0; + } +} // namespace ViPER4Android \ No newline at end of file diff --git a/src/ViPER4Aidl.cpp b/src/ViPER4Aidl.cpp index a571d3f..e3bffc5 100644 --- a/src/ViPER4Aidl.cpp +++ b/src/ViPER4Aidl.cpp @@ -1,8 +1,8 @@ #define LOG_TAG "ViPER4AIDL" #include "ViPER4Aidl.h" +#include "ViPER4Android.h" #include "AidlUtils.h" -#include #include #include @@ -20,8 +20,11 @@ using aidl::android::media::audio::common::AudioUuid; using aidl::android::media::audio::common::PcmType; using android::hardware::EventFlag; -static const AudioUuid kType = stringToUuid("b9bc100c-26cd-42e6-acb6-cad8c3f778de"); -static const AudioUuid kUuid = stringToUuid("90380da3-8536-4744-a6a3-5731970e640f"); +using ViPER4Android::getFrameSizeInBytes; +using ViPER4Android::stringToUuid; + +static const AudioUuid kType = stringToUuid(ViPER4Android::kTypeString); +static const AudioUuid kUuid = stringToUuid(ViPER4Android::kUuidString); static const Descriptor kDescriptor = { .common = { .id = { @@ -33,19 +36,19 @@ static const Descriptor kDescriptor = { .type = Flags::Type::INSERT, .insert = Flags::Insert::LAST, }, - .name = "ViPER4Android", - .implementor = "Iscle", + .name = ViPER4Android::kName, + .implementor = ViPER4Android::kImplementor, }, }; ndk::ScopedAStatus ViPER4AIDL::open(const Parameter::Common &common, - const std::optional &specific, - IEffect::OpenEffectReturn *ret) { + const std::optional &specific, + IEffect::OpenEffectReturn *oer) { if (common.input.base.format.pcm != PcmType::FLOAT_32_BIT || common.output.base.format.pcm != PcmType::FLOAT_32_BIT) { - ALOGE("open: unsupported PCM type (input: %d, output: %d)", - static_cast(common.input.base.format.pcm), - static_cast(common.output.base.format.pcm)); + ALOGE("open: unsupported PCM type (input: %s, output: %s)", + toString(common.input.base.format.pcm).c_str(), + toString(common.output.base.format.pcm).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } @@ -56,32 +59,25 @@ ndk::ScopedAStatus ViPER4AIDL::open(const Parameter::Common &common, return ndk::ScopedAStatus::ok(); } - size_t inputFrameSize = getFrameSizeInBytes( - common.input.base.format, common.input.base.channelMask); - size_t outputFrameSize = getFrameSizeInBytes( - common.output.base.format, common.output.base.channelMask); + size_t inputFrameSize = getFrameSizeInBytes(common.input.base.format, common.input.base.channelMask); + size_t outputFrameSize = getFrameSizeInBytes(common.output.base.format, common.output.base.channelMask); /* EffectContext constructor start */ mCommon = common; size_t inBufferSizeInFloat = common.input.frameCount * inputFrameSize / sizeof(float); size_t outBufferSizeInFloat = common.output.frameCount * outputFrameSize / sizeof(float); - ALOGD("open: inBufferSizeInFloat %zu, outBufferSizeInFloat %zu", inBufferSizeInFloat, - outBufferSizeInFloat); - // only status FMQ use the EventFlag mStatusMQ = std::make_shared(1, true /* configureEventFlagWord */); mInputMQ = std::make_shared(inBufferSizeInFloat); mOutputMQ = std::make_shared(outBufferSizeInFloat); - if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) { - ALOGE("open: invalid FMQ (status: %d, input: %d, output: %d)", + ALOGE("open: invalid FMQs (status: %d, input: %d, output: %d)", mStatusMQ->isValid(), mInputMQ->isValid(), mOutputMQ->isValid()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } - android::status_t status = EventFlag::createEventFlag( - mStatusMQ->getEventFlagWord(), &mEventFlag); + android::status_t status = EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEventFlag); if (status != android::OK || mEventFlag == nullptr) { ALOGE("open: failed to create event flag"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); @@ -90,17 +86,13 @@ ndk::ScopedAStatus ViPER4AIDL::open(const Parameter::Common &common, mWorkBuffer.resize(std::max(inBufferSizeInFloat, outBufferSizeInFloat)); /* EffectContext constructor end */ - if (specific.has_value()) { - ALOGD("open: specific parameters provided, ignoring for now..."); - } - mState = State::IDLE; - dupeFmq(ret); + dupeFmq(oer); - if (createThread("ViPER4Android") != RetCode::SUCCESS) { + if (createThread(ViPER4Android::kName) != RetCode::SUCCESS) { ALOGE("open: failed to create thread"); - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } return ndk::ScopedAStatus::ok(); @@ -130,7 +122,7 @@ ndk::ScopedAStatus ViPER4AIDL::close() { if (destroyThread() != RetCode::SUCCESS) { ALOGE("close: failed to destroy thread"); - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } { @@ -150,7 +142,7 @@ ndk::ScopedAStatus ViPER4AIDL::getDescriptor(Descriptor *descriptor) { return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus ViPER4AIDL::command(CommandId command) { +ndk::ScopedAStatus ViPER4AIDL::command(CommandId commandId) { std::lock_guard lg(mImplMutex); if (mState == State::INIT) { @@ -158,15 +150,12 @@ ndk::ScopedAStatus ViPER4AIDL::command(CommandId command) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } - switch (command) { + switch (commandId) { case CommandId::START: { if (mState == State::PROCESSING) { ALOGD("command: already started"); return ndk::ScopedAStatus::ok(); } - - //RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); - mState = State::PROCESSING; if (notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS) { @@ -183,7 +172,6 @@ ndk::ScopedAStatus ViPER4AIDL::command(CommandId command) { ALOGD("command: already stopped"); return ndk::ScopedAStatus::ok(); } - mState = State::IDLE; if (notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS) { @@ -192,8 +180,6 @@ ndk::ScopedAStatus ViPER4AIDL::command(CommandId command) { } stopThread(); - - //RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); break; } @@ -206,14 +192,12 @@ ndk::ScopedAStatus ViPER4AIDL::command(CommandId command) { } stopThread(); - resetBuffer(); - //RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); break; } default: - ALOGE("command: unknown command %d", static_cast(command)); + ALOGE("command: unknown commandId (%s)", toString(commandId).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } @@ -229,8 +213,7 @@ ndk::ScopedAStatus ViPER4AIDL::getState(State *state) { return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus -ViPER4AIDL::setParameter(const Parameter ¶meter) { +ndk::ScopedAStatus ViPER4AIDL::setParameter(const Parameter ¶meter) { std::lock_guard lg(mImplMutex); const auto &tag = parameter.getTag(); @@ -239,14 +222,14 @@ ViPER4AIDL::setParameter(const Parameter ¶meter) { auto common = parameter.get(); if (common.input.base.format.pcm != PcmType::FLOAT_32_BIT || common.output.base.format.pcm != PcmType::FLOAT_32_BIT) { - ALOGE("setParameter: common: unsupported PCM type (input: %d, output: %d)", - static_cast(common.input.base.format.pcm), - static_cast(common.output.base.format.pcm)); + ALOGE("setParameter: common: unsupported PCM type (input: %s, output: %s)", + toString(common.input.base.format.pcm).c_str(), + toString(common.output.base.format.pcm).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } #if VIPER_AIDL_VERSION >= 2 - if (mWorkBuffer.size() != 0 && mInputMQ != nullptr && mOutputMQ != nullptr) { + if (!mWorkBuffer.empty() && mInputMQ != nullptr && mOutputMQ != nullptr) { size_t prevInputFrameSize = getFrameSizeInBytes( mCommon.input.base.format, mCommon.input.base.channelMask); size_t prevOutputFrameSize = getFrameSizeInBytes( @@ -258,24 +241,16 @@ ViPER4AIDL::setParameter(const Parameter ¶meter) { common.output.base.format, common.output.base.channelMask); bool needUpdateMq = false; - if (inputFrameSize != prevInputFrameSize || - mCommon.input.frameCount != common.input.frameCount) { - ALOGD("setParameter: common: reset input MQ"); + if (inputFrameSize != prevInputFrameSize || mCommon.input.frameCount != common.input.frameCount) { mInputMQ.reset(); needUpdateMq = true; } if (outputFrameSize != prevOutputFrameSize || mCommon.output.frameCount != common.output.frameCount) { - ALOGD("setParameter: common: reset output MQ"); mOutputMQ.reset(); needUpdateMq = true; } - ALOGD("setParameter: common: inBufferSizeInFloat %zu, outBufferSizeInFloat %zu, needUpdateMq %d", - (size_t) (common.input.frameCount * inputFrameSize / sizeof(float)), - (size_t) (common.output.frameCount * outputFrameSize / sizeof(float)), - needUpdateMq); - if (needUpdateMq && mEventFlag->wake(kEventFlagDataMqUpdate) != ::android::OK) { ALOGE("setParameter: common: failed to wake event flag"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); @@ -288,8 +263,7 @@ ViPER4AIDL::setParameter(const Parameter ¶meter) { case Parameter::Tag::specific: { auto specific = parameter.get(); if (specific.getTag() != Parameter::Specific::Tag::vendorEffect) { - ALOGE("setParameter: specific: unsupported tag %d", - static_cast(specific.getTag())); + ALOGE("setParameter: specific: unsupported tag (%s)", toString(specific.getTag()).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } @@ -300,37 +274,25 @@ ViPER4AIDL::setParameter(const Parameter ¶meter) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - auto data = defaultExtension->bytes; + auto cmd = defaultExtension->bytes; - ALOGD("setParameter: specific: vendorEffect data size %zu", data.size()); - - int32_t ret = 0; - uint32_t retSize = sizeof(ret); - if (viperContext.handleCommand( - EFFECT_CMD_SET_PARAM, - data.size(), - data.data(), - &retSize, - &ret - ) != 0) { + int32_t replyData = 0; + uint32_t replySize = sizeof(replyData); + if (viperContext.handleCommand(EFFECT_CMD_SET_PARAM, + cmd.size(), cmd.data(), &replySize, &replyData) != 0 || replyData != 0) { ALOGE("setParameter: specific: failed to handle command"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - if (ret != 0) { - ALOGE("setParameter: specific: command failed with ret %d", ret); - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); - } return ndk::ScopedAStatus::ok(); } default: - ALOGE("setParameter: unsupported parameter tag %d", static_cast(tag)); + ALOGE("setParameter: unsupported parameter tag (%s)", toString(tag).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } -ndk::ScopedAStatus -ViPER4AIDL::getParameter(const Parameter::Id &id, Parameter *param) { +ndk::ScopedAStatus ViPER4AIDL::getParameter(const Parameter::Id ¶meterId, Parameter *param) { if (param == nullptr) { ALOGE("getParameter: param is null"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); @@ -338,66 +300,36 @@ ViPER4AIDL::getParameter(const Parameter::Id &id, Parameter *param) { std::lock_guard lg(mImplMutex); - const auto &tag = id.getTag(); + const auto &tag = parameterId.getTag(); switch (tag) { case Parameter::Id::commonTag: { - auto commonTag = id.get(); + auto commonTag = parameterId.get(); if (commonTag != Parameter::Tag::common) { - ALOGE("getParameter: commonTag: unsupported tag %d", - static_cast(commonTag)); + ALOGE("getParameter: commonTag: unsupported tag (%s)", toString(commonTag).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } param->set(mCommon); return ndk::ScopedAStatus::ok(); } case Parameter::Id::vendorEffectTag: { - auto vendorEffectTag = id.get(); + const auto &vendorEffectTag = parameterId.get(); std::optional cmdDefaultExtension; if (vendorEffectTag.extension.getParcelable(&cmdDefaultExtension) != STATUS_OK || !cmdDefaultExtension.has_value()) { ALOGE("getParameter: vendorEffectTag: failed to get default extension"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - VendorExtension replyVendorExtension; - DefaultExtension replyDefaultExtension; - replyDefaultExtension.bytes.resize(sizeof(effect_param_t) + 2 * sizeof(int32_t)); - - auto cmdData = cmdDefaultExtension->bytes; - auto replyData = replyDefaultExtension.bytes; - uint32_t replySize = replyData.size(); - - if (viperContext.handleCommand( - EFFECT_CMD_GET_PARAM, - cmdData.size(), - cmdData.data(), - &replySize, - replyData.data() - ) != 0) { - ALOGE("getParameter: vendorEffectTag: failed to handle command"); - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); - } - - replyData.resize(replySize); - - if (replyVendorExtension.extension.setParcelable(replyDefaultExtension) != STATUS_OK) { - ALOGE("getParameter: vendorEffectTag: failed to set default extension"); - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); - } - - Parameter::Specific specific; - specific.set(replyVendorExtension); - param->set(specific); - - return ndk::ScopedAStatus::ok(); + ALOGW("getParameter: vendorEffectTag: getParameter not implemented"); + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } default: - ALOGD("getParameter: unsupported parameter tag %d", static_cast(tag)); + ALOGD("getParameter: unsupported parameter tag (%s)", toString(tag).c_str()); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } #if VIPER_AIDL_VERSION >= 2 -ndk::ScopedAStatus ViPER4AIDL::reopen(IEffect::OpenEffectReturn *ret) { +ndk::ScopedAStatus ViPER4AIDL::reopen(IEffect::OpenEffectReturn *oer) { std::lock_guard lg(mImplMutex); if (mState == State::INIT) { @@ -405,9 +337,7 @@ ndk::ScopedAStatus ViPER4AIDL::reopen(IEffect::OpenEffectReturn *ret) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } - ALOGD("reopen: reopening effect"); - - dupeFmqWithReopen(ret); + dupeFmqWithReopen(oer); return ndk::ScopedAStatus::ok(); } @@ -419,8 +349,9 @@ void ViPER4AIDL::process() { * in the life cycle of workerThread (threadLoop). */ uint32_t efState = 0; - if (!mEventFlag || mEventFlag->wait(mDataMqNotEmptyEf, &efState, 0 /* no timeout */, true /* retry */) != ::android::OK || !(efState & mDataMqNotEmptyEf)) { - ALOGE("process: mEventFlag - %p, efState - %x", mEventFlag, efState); + if (!mEventFlag || + mEventFlag->wait(mDataMqNotEmptyEf, &efState, 0 /* no timeout */, true /* retry */) != ::android::OK || + !(efState & mDataMqNotEmptyEf)) { return; } @@ -431,45 +362,37 @@ void ViPER4AIDL::process() { #else if (mState != State::PROCESSING) { #endif - ALOGD("process: skip process in state: %s", toString(mState).c_str()); return; } - ALOGD("process: processing in state: %s, mInputMQ - %p, mOutputMQ - %p", - toString(mState).c_str(), mInputMQ.get(), mOutputMQ.get()); - if (!mInputMQ || !mOutputMQ) { - ALOGE("process: mInputMQ or mOutputMQ is null"); return; } assert(mWorkBuffer.size() >= std::max(mInputMQ->availableToRead(), mOutputMQ->availableToWrite())); + auto processSamples = std::min(mInputMQ->availableToRead(), mOutputMQ->availableToWrite()); if (processSamples) { - auto buffer = static_cast(mWorkBuffer.data()); + auto buffer = static_cast(mWorkBuffer.data()); mInputMQ->read(buffer, processSamples); - IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples); + IEffect::Status status = effectProcessImpl(buffer, buffer, static_cast(processSamples)); mOutputMQ->write(buffer, status.fmqProduced); mStatusMQ->writeBlocking(&status, 1); } } } -void ViPER4AIDL::dupeFmq(IEffect::OpenEffectReturn* ret) { - ALOGD("dupeFmq: mStatusMQ - %p, mInputMQ - %p, mOutputMQ - %p", - mStatusMQ.get(), mInputMQ.get(), mOutputMQ.get()); - if (ret && mStatusMQ && mInputMQ && mOutputMQ) { - ret->statusMQ = mStatusMQ->dupeDesc(); - ret->inputDataMQ = mInputMQ->dupeDesc(); - ret->outputDataMQ = mOutputMQ->dupeDesc(); +void ViPER4AIDL::dupeFmq(IEffect::OpenEffectReturn* oer) { + if (oer && mStatusMQ && mInputMQ && mOutputMQ) { + oer->statusMQ = mStatusMQ->dupeDesc(); + oer->inputDataMQ = mInputMQ->dupeDesc(); + oer->outputDataMQ = mOutputMQ->dupeDesc(); } } -void ViPER4AIDL::dupeFmqWithReopen(IEffect::OpenEffectReturn* ret) { - size_t inputFrameSize = getFrameSizeInBytes( - mCommon.input.base.format, mCommon.input.base.channelMask); - size_t outputFrameSize = getFrameSizeInBytes( - mCommon.output.base.format, mCommon.output.base.channelMask); +void ViPER4AIDL::dupeFmqWithReopen(IEffect::OpenEffectReturn* oer) { + size_t inputFrameSize = getFrameSizeInBytes(mCommon.input.base.format, mCommon.input.base.channelMask); + size_t outputFrameSize = getFrameSizeInBytes(mCommon.output.base.format, mCommon.output.base.channelMask); const size_t inBufferSizeInFloat = mCommon.input.frameCount * inputFrameSize / sizeof(float); const size_t outBufferSizeInFloat = mCommon.output.frameCount * outputFrameSize / sizeof(float); const size_t bufferSize = std::max(inBufferSizeInFloat, outBufferSizeInFloat); @@ -482,7 +405,7 @@ void ViPER4AIDL::dupeFmqWithReopen(IEffect::OpenEffectReturn* ret) { if (mWorkBuffer.size() != bufferSize) { mWorkBuffer.resize(bufferSize); } - dupeFmq(ret); + dupeFmq(oer); } RetCode ViPER4AIDL::notifyEventFlag(uint32_t flag) { @@ -490,17 +413,18 @@ RetCode ViPER4AIDL::notifyEventFlag(uint32_t flag) { ALOGE("notifyEventFlag: StatusEventFlag invalid"); return RetCode::ERROR_EVENT_FLAG_ERROR; } - if (const auto ret = mEventFlag->wake(flag); ret != ::android::OK) { - ALOGE("notifyEventFlag: wake failure with ret %d", ret); + if (mEventFlag->wake(flag) != ::android::OK) { + ALOGE("notifyEventFlag: failed to wake event flag"); return RetCode::ERROR_EVENT_FLAG_ERROR; } return RetCode::SUCCESS; } -// reset buffer status by abandon input data in FMQ void ViPER4AIDL::resetBuffer() { + // reset buffer status by abandon input data in FMQ if (mStatusMQ) { std::vector status(mStatusMQ->availableToRead()); + mStatusMQ->read(status.data(), status.size()); } if (mInputMQ) { auto buffer = static_cast(mWorkBuffer.data()); @@ -508,18 +432,21 @@ void ViPER4AIDL::resetBuffer() { } } -// A placeholder processing implementation to copy samples from input to output -IEffect::Status ViPER4AIDL::effectProcessImpl(float* in, float* out, int samples) { +IEffect::Status ViPER4AIDL::effectProcessImpl(float *in, float *out, int32_t samples) { viperContext.process(in, out, samples); - return {STATUS_OK, samples, samples}; + return { + .status = STATUS_OK, + .fmqConsumed = samples, + .fmqProduced = samples + }; } -extern "C" binder_exception_t queryEffect(const AudioUuid *audio_uuid, Descriptor *descriptor) { - if (audio_uuid == nullptr || descriptor == nullptr) { - ALOGE("queryEffect: audio_uuid or descriptor is null"); +extern "C" binder_exception_t queryEffect(const AudioUuid *audioUuid, Descriptor *descriptor) { + if (audioUuid == nullptr || descriptor == nullptr) { + ALOGE("queryEffect: audioUuid or descriptor is null"); return EX_ILLEGAL_ARGUMENT; } - if (*audio_uuid != kUuid) { + if (*audioUuid != kUuid) { ALOGE("queryEffect: invalid uuid"); return EX_ILLEGAL_ARGUMENT; } @@ -527,9 +454,10 @@ extern "C" binder_exception_t queryEffect(const AudioUuid *audio_uuid, Descripto return EX_NONE; } -extern "C" binder_exception_t createEffect(const AudioUuid *audio_uuid, std::shared_ptr *instanceSp) { - if (audio_uuid == nullptr || instanceSp == nullptr) { - ALOGE("createEffect: audio_uuid or instanceSp is null"); +extern "C" binder_exception_t createEffect(const AudioUuid *audioUuid, + std::shared_ptr *instanceSp) { + if (audioUuid == nullptr || instanceSp == nullptr) { + ALOGE("createEffect: audioUuid or instanceSp is null"); return EX_ILLEGAL_ARGUMENT; } *instanceSp = ndk::SharedRefBase::make(); @@ -542,8 +470,8 @@ extern "C" binder_exception_t destroyEffect(const std::shared_ptr &inst return EX_ILLEGAL_ARGUMENT; } - Descriptor desc; - ndk::ScopedAStatus status = instanceSp->getDescriptor(&desc); + Descriptor descriptor; + ndk::ScopedAStatus status = instanceSp->getDescriptor(&descriptor); if (!status.isOk()) { ALOGE("destroyEffect: failed to get descriptor, status: %s", status.getDescription().c_str()); return EX_ILLEGAL_STATE; diff --git a/src/ViPER4Aidl.h b/src/ViPER4Aidl.h index 79ce668..dd1423d 100644 --- a/src/ViPER4Aidl.h +++ b/src/ViPER4Aidl.h @@ -1,11 +1,7 @@ #pragma once -#include -#include -#include -#include #include -#include "ViperContext.h" +#include "ViPERContext.h" using aidl::android::hardware::common::fmq::SynchronizedReadWrite; #if VIPER_AIDL_VERSION >= 2 @@ -26,15 +22,17 @@ using android::hardware::EventFlag; class ViPER4AIDL : public BnEffect, public EffectThread { public: // BnEffect - ndk::ScopedAStatus open(const Parameter::Common &common, const std::optional &specific, IEffect::OpenEffectReturn *ret) override; + ndk::ScopedAStatus open(const Parameter::Common &common, + const std::optional &specific, + IEffect::OpenEffectReturn *oer) override; ndk::ScopedAStatus close() override; - ndk::ScopedAStatus getDescriptor(Descriptor *_aidl_return) override; - ndk::ScopedAStatus command(CommandId id) override; + ndk::ScopedAStatus getDescriptor(Descriptor *descriptor) override; + ndk::ScopedAStatus command(CommandId command_id) override; ndk::ScopedAStatus getState(State *state) override; - ndk::ScopedAStatus setParameter(const Parameter &in_param) override; - ndk::ScopedAStatus getParameter(const Parameter::Id &in_paramId, Parameter *param) override; + ndk::ScopedAStatus setParameter(const Parameter ¶meter) override; + ndk::ScopedAStatus getParameter(const Parameter::Id ¶meter_id, Parameter *parameter) override; #if VIPER_AIDL_VERSION >= 2 - ndk::ScopedAStatus reopen(IEffect::OpenEffectReturn *ret) override; + ndk::ScopedAStatus reopen(IEffect::OpenEffectReturn *oer) override; #endif // EffectThread @@ -43,11 +41,11 @@ private: typedef android::AidlMessageQueue StatusMQ; typedef android::AidlMessageQueue DataMQ; - void dupeFmq(IEffect::OpenEffectReturn* ret); - void dupeFmqWithReopen(IEffect::OpenEffectReturn* ret); + void dupeFmq(IEffect::OpenEffectReturn* oer); + void dupeFmqWithReopen(IEffect::OpenEffectReturn* oer); RetCode notifyEventFlag(uint32_t flag); void resetBuffer(); - IEffect::Status effectProcessImpl(float* in, float* out, int samples); + IEffect::Status effectProcessImpl(float *in, float *out, int32_t samples); std::mutex mImplMutex; State mState = State::INIT; @@ -59,12 +57,10 @@ private: #endif Parameter::Common mCommon; - std::shared_ptr mStatusMQ; std::shared_ptr mInputMQ; std::shared_ptr mOutputMQ; EventFlag *mEventFlag; std::vector mWorkBuffer; - - ViperContext viperContext; + ViPERContext viperContext; }; diff --git a/src/ViPER4Android.cpp b/src/ViPER4Android.cpp index d1b2ab9..bd3c4f0 100644 --- a/src/ViPER4Android.cpp +++ b/src/ViPER4Android.cpp @@ -2,12 +2,15 @@ #include #include "viper/ViPER.h" #include -#include "ViperContext.h" +#include "ViPERContext.h" + +#define VIPER_NAME "ViPER4Android" +#define VIPER_IMPLEMENTOR "Iscle, Martmists, ViPER ACOUSTIC" extern "C" { struct ViperHandle { const struct effect_interface_s *iface; // Always keep as first member - ViperContext *context; + ViPERContext *context; }; static const effect_descriptor_t viperDescriptor = { @@ -19,7 +22,7 @@ static const effect_descriptor_t viperDescriptor = { .cpuLoad = 8, // In 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS .memoryUsage = 1, // In KB and includes only dynamically allocated memory .name = VIPER_NAME, - .implementor = VIPER_AUTHORS + .implementor = VIPER_IMPLEMENTOR }; static int32_t viperInterfaceProcess(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { @@ -58,7 +61,7 @@ viperLibraryCreate(const effect_uuid_t *uuid, int32_t sessionId __unused, int32_ ViperHandle *viperHandle = new ViperHandle(); viperHandle->iface = &viperInterface; - viperHandle->context = new ViperContext(); + viperHandle->context = new ViPERContext(); *pHandle = reinterpret_cast(viperHandle); return 0; } @@ -83,8 +86,8 @@ __attribute__ ((visibility ("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { .tag = AUDIO_EFFECT_LIBRARY_TAG, .version = EFFECT_LIBRARY_API_VERSION, - .name = VIPER_NAME, - .implementor = VIPER_AUTHORS, + .name = ViPER4Android::kName, + .implementor = ViPER4Android::kImplementor, .create_effect = viperLibraryCreate, .release_effect = viperLibraryRelease, .get_descriptor = viperLibraryGetDescriptor, diff --git a/src/ViPER4Android.h b/src/ViPER4Android.h index 029b2d2..655d0cf 100644 --- a/src/ViPER4Android.h +++ b/src/ViPER4Android.h @@ -1,7 +1,12 @@ #pragma once -// Source: https://github.com/vipersaudio/viperfx_core_binary/blob/master/viperfx_intf.h -// Updated parameters source: https://github.com/vipersaudio/viper4android_fx/blob/master/android_4.x/src/com/vipercn/viper4android_v2/service/ViPER4AndroidService.java +namespace ViPER4Android { + static const char *const kName = "ViPER4Android"; + static const char *const kImplementor = "Iscle, Martmists, ViPER ACOUSTIC"; + + static const char *const kTypeString = "b9bc100c-26cd-42e6-acb6-cad8c3f778de"; + static const char *const kUuidString = "90380da3-8536-4744-a6a3-5731970e640f"; +}; typedef enum { PARAM_GET_ENABLED = 0, diff --git a/src/ViperContext.cpp b/src/ViPERContext.cpp similarity index 98% rename from src/ViperContext.cpp rename to src/ViPERContext.cpp index 9a1da81..ba695d2 100644 --- a/src/ViperContext.cpp +++ b/src/ViPERContext.cpp @@ -1,22 +1,22 @@ #include #include #include -#include "ViperContext.h" +#include "ViPERContext.h" #include #include #define SET(type, ptr, value) (*(type *) (ptr) = (value)) -ViperContext::ViperContext() : +ViPERContext::ViPERContext() : config({}), disableReason(DisableReason::UNKNOWN), buffer(std::vector()), bufferFrameCount(0), enabled(false) { - ALOGI("ViperContext created"); + ALOGI("ViPERContext created"); } -void ViperContext::copyBufferConfig(buffer_config_t *dest, buffer_config_t *src) { +void ViPERContext::copyBufferConfig(buffer_config_t *dest, buffer_config_t *src) { if (src->mask & EFFECT_CONFIG_BUFFER) { dest->buffer = src->buffer; } @@ -44,7 +44,7 @@ void ViperContext::copyBufferConfig(buffer_config_t *dest, buffer_config_t *src) dest->mask |= src->mask; } -void ViperContext::handleSetConfig(effect_config_t *newConfig) { +void ViPERContext::handleSetConfig(effect_config_t *newConfig) { ALOGI("Checking input and output configuration ..."); ALOGI("Input mask: 0x%04X", newConfig->inputCfg.mask); @@ -129,7 +129,7 @@ void ViperContext::handleSetConfig(effect_config_t *newConfig) { viper.reset(); } -int32_t ViperContext::handleSetParam(effect_param_t *pCmdParam, void *pReplyData) { +int32_t ViPERContext::handleSetParam(effect_param_t *pCmdParam, void *pReplyData) { // The value offset of an effect parameter is computed by rounding up // the parameter size to the next 32 bit alignment. uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); @@ -608,7 +608,7 @@ int32_t ViperContext::handleSetParam(effect_param_t *pCmdParam, void *pReplyData } } -int32_t ViperContext::handleGetParam(effect_param_t *pCmdParam, effect_param_t *pReplyParam, uint32_t *pReplySize) { +int32_t ViPERContext::handleGetParam(effect_param_t *pCmdParam, effect_param_t *pReplyParam, uint32_t *pReplySize) { // The value offset of an effect parameter is computed by rounding up // the parameter size to the next 32 bit alignment. uint32_t vOffset = ((pCmdParam->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); @@ -684,7 +684,7 @@ int32_t ViperContext::handleGetParam(effect_param_t *pCmdParam, effect_param_t * } } -int32_t ViperContext::handleCommand(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *pReplySize, void *pReplyData) { +int32_t ViPERContext::handleCommand(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *pReplySize, void *pReplyData) { uint32_t replySize = pReplySize == nullptr ? 0 : *pReplySize; switch (cmdCode) { case EFFECT_CMD_INIT: { @@ -801,7 +801,7 @@ static audio_buffer_t *getBuffer(buffer_config_s *config, audio_buffer_t *buffer return nullptr; } -int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { +int32_t ViPERContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { if (disableReason != DisableReason::NONE) { return -EINVAL; } @@ -860,7 +860,7 @@ int32_t ViperContext::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffe return 0; } -int32_t ViperContext::process(float *inBuffer, float *outBuffer, size_t count) { +int32_t ViPERContext::process(float *inBuffer, float *outBuffer, size_t count) { memcpy(outBuffer, inBuffer, count * sizeof(float)); // The viper process function expects the count to be the number of // stereo frames, not the number of samples. Thus, we divide by 2. @@ -868,6 +868,6 @@ int32_t ViperContext::process(float *inBuffer, float *outBuffer, size_t count) { return 0; } -void ViperContext::setDisableReason(DisableReason reason) { +void ViPERContext::setDisableReason(DisableReason reason) { this->disableReason = reason; } diff --git a/src/ViperContext.h b/src/ViPERContext.h similarity index 96% rename from src/ViperContext.h rename to src/ViPERContext.h index 1a68062..1c1e9e2 100644 --- a/src/ViperContext.h +++ b/src/ViPERContext.h @@ -6,7 +6,7 @@ #include "viper/ViPER.h" #include -class ViperContext { +class ViPERContext { public: enum class DisableReason : int32_t { UNKNOWN = -1, @@ -17,7 +17,7 @@ public: INVALID_FORMAT, }; - ViperContext(); + ViPERContext(); int32_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData); int32_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer); diff --git a/src/include/constants.h b/src/include/constants.h index 5508daa..869e2a2 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -35,6 +35,4 @@ enum class Architecture : uint8_t { */ #endif -#define VIPER_NAME "ViPER4Android" -#define VIPER_AUTHORS "viper.WYF, Martmists, Iscle" #define VIPER_DEFAULT_SAMPLING_RATE 44100 \ No newline at end of file