Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4ee62b7 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Bass Boost : Add libeffect bundle implementation"

parents e777420a 1db8945c
Loading
Loading
Loading
Loading
+120 −1
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@

namespace aidl::android::hardware::audio::effect {

using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;

RetCode BundleContext::init() {
    std::lock_guard lg(mMutex);
    // init with pre-defined preset NORMAL
@@ -69,6 +72,9 @@ void BundleContext::deInit() {

RetCode BundleContext::enable() {
    if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
    // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due to
    // their nature.
    bool tempDisabled = false;
    switch (mType) {
        case lvm::BundleEffectType::EQUALIZER:
            LOG(DEBUG) << __func__ << " enable bundle EQ";
@@ -76,12 +82,19 @@ RetCode BundleContext::enable() {
            mSamplesToExitCountEq = (mSamplesPerSecond * 0.1);
            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
            break;
        case lvm::BundleEffectType::BASS_BOOST:
            LOG(DEBUG) << __func__ << " enable bundle BB";
            if (mSamplesToExitCountBb <= 0) mNumberEffectsEnabled++;
            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
            mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
            tempDisabled = mBassTempDisabled;
            break;
        default:
            // Add handling for other effects
            break;
    }
    mEnabled = true;
    return enableOperatingMode();
    return (tempDisabled ? RetCode::SUCCESS : enableOperatingMode());
}

RetCode BundleContext::enableOperatingMode() {
@@ -95,6 +108,10 @@ RetCode BundleContext::enableOperatingMode() {
                LOG(DEBUG) << __func__ << " enable bundle EQ";
                params.EQNB_OperatingMode = LVM_EQNB_ON;
                break;
            case lvm::BundleEffectType::BASS_BOOST:
                LOG(DEBUG) << __func__ << " enable bundle BB";
                params.BE_OperatingMode = LVM_BE_ON;
                break;
            default:
                // Add handling for other effects
                break;
@@ -112,6 +129,10 @@ RetCode BundleContext::disable() {
            LOG(DEBUG) << __func__ << " disable bundle EQ";
            mEffectInDrain |= 1 << int(lvm::BundleEffectType::EQUALIZER);
            break;
        case lvm::BundleEffectType::BASS_BOOST:
            LOG(DEBUG) << __func__ << " disable bundle BB";
            mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
            break;
        default:
            // Add handling for other effects
            break;
@@ -131,6 +152,10 @@ RetCode BundleContext::disableOperatingMode() {
                LOG(DEBUG) << __func__ << " disable bundle EQ";
                params.EQNB_OperatingMode = LVM_EQNB_OFF;
                break;
            case lvm::BundleEffectType::BASS_BOOST:
                LOG(DEBUG) << __func__ << " disable bundle BB";
                params.BE_OperatingMode = LVM_BE_OFF;
                break;
            default:
                // Add handling for other effects
                break;
@@ -156,6 +181,7 @@ RetCode BundleContext::limitLevel() {
                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");

        bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
        bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;

        if (eqEnabled) {
            for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
@@ -182,6 +208,22 @@ RetCode BundleContext::limitLevel() {
            bandFactorSum -= 1.0;
            if (bandFactorSum > 0) crossCorrection = bandFactorSum * 0.7;
        }
        // BassBoost contribution
        if (bbEnabled) {
            float boostFactor = mBassStrengthSaved / 1000.0;
            float boostCoefficient = lvm::kBassBoostEnergyCoefficient;

            energyContribution += boostFactor * boostCoefficient * boostCoefficient;

            if (eqEnabled) {
                for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
                    float bandFactor = mBandGaindB[i] / 15.0;
                    float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
                    float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
                    if (bandEnergy > 0) energyBassBoost += bandEnergy;
                }
            }
        }

        double totalEnergyEstimation =
                sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
@@ -216,6 +258,39 @@ RetCode BundleContext::limitLevel() {
    return RetCode::SUCCESS;
}

bool BundleContext::isDeviceSupportedBassBoost(
        const aidl::android::media::audio::common::AudioDeviceDescription& device) {
    return (device == AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER, ""} ||
            device == AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
                                             AudioDeviceDescription::CONNECTION_BT_SCO} ||
            device == AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
                                             AudioDeviceDescription::CONNECTION_BT_A2DP});
}

RetCode BundleContext::setOutputDevice(
        const aidl::android::media::audio::common::AudioDeviceDescription& device) {
    mOutputDevice = device;
    if (mType == lvm::BundleEffectType::BASS_BOOST) {
        if (isDeviceSupportedBassBoost(device)) {
            // If a device doesn't support bass boost, the effect must be temporarily disabled.
            // The effect must still report its original state as this can only be changed by the
            // start/stop commands.
            if (mEnabled) {
                disableOperatingMode();
            }
            mBassTempDisabled = true;
        } else {
            // If a device supports bass boost and the effect has been temporarily disabled
            // previously then re-enable it
            if (!mEnabled) {
                enableOperatingMode();
            }
            mBassTempDisabled = false;
        }
    }
    return RetCode::SUCCESS;
}

LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const {
    LVM_INT16 db_fix;
    LVM_INT16 Shift;
@@ -366,6 +441,31 @@ RetCode BundleContext::updateControlParameter(const std::vector<Equalizer::BandL
    return RetCode::SUCCESS;
}

RetCode BundleContext::setBassBoostStrength(int strength) {
    if (strength < BassBoost::MIN_PER_MILLE_STRENGTH ||
        strength > BassBoost::MAX_PER_MILLE_STRENGTH) {
        LOG(ERROR) << __func__ << " invalid strength: " << strength;
        return RetCode::ERROR_ILLEGAL_PARAMETER;
    }

    // Update Control Parameter
    LVM_ControlParams_t params;
    {
        std::lock_guard lg(mMutex);
        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");

        params.BE_EffectLevel = (LVM_INT16)((15 * strength) / 1000);
        params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;

        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
    }
    mBassStrengthSaved = strength;
    LOG(INFO) << __func__ << " success with strength " << strength;
    return limitLevel();
}

void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
    /* General parameters */
    params.OperatingMode = LVM_MODE_ON;
@@ -473,6 +573,12 @@ IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
            --mNumberEffectsEnabled;
            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
        }
        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
            LOG(DEBUG) << "Draining BASS_BOOST";
            mSamplesToExitCountBb = 0;
            --mNumberEffectsEnabled;
            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
        }
    }
    mEffectProcessCalled |= 1 << int(mType);
    if (!mEnabled) {
@@ -490,6 +596,19 @@ IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
                    LOG(DEBUG) << "Effect_process() this is the last frame for EQUALIZER";
                }
                break;
            case lvm::BundleEffectType::BASS_BOOST:
                if (mSamplesToExitCountBb > 0) {
                    mSamplesToExitCountBb -= samples;
                }
                if (mSamplesToExitCountBb <= 0) {
                    isDataAvailable = false;
                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
                        mNumberEffectsEnabled--;
                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
                    }
                    LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
                }
                break;
            default:
                // Add handling for other effects
                break;
+7 −0
Original line number Diff line number Diff line
@@ -56,12 +56,19 @@ class BundleContext final : public EffectContext {
    aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
        return mChMask;
    }
    bool isDeviceSupportedBassBoost(
            const aidl::android::media::audio::common::AudioDeviceDescription& device);
    RetCode setOutputDevice(
            const aidl::android::media::audio::common::AudioDeviceDescription& device) override;

    RetCode setEqualizerPreset(const std::size_t presetIdx);
    int getEqualizerPreset() const { return mCurPresetIdx; }
    RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
    std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;

    RetCode setBassBoostStrength(int strength);
    int getBassBoostStrength() const { return mBassStrengthSaved; }

    RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
    Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }

+20 −1
Original line number Diff line number Diff line
@@ -83,9 +83,28 @@ static const Descriptor kEqualizerDesc = {
                   .implementor = "NXP Software Ltd."},
        .capability = Capability::make<Capability::equalizer>(kEqCap)};

static const bool mStrengthSupported = true;

static const BassBoost::Capability kBassBoostCap = {.strengthSupported = mStrengthSupported};

static const std::string kBassBoostEffectName = "Dynamic Bass Boost";

static const Descriptor kBassBoostDesc = {
        .common = {.id = {.type = kBassBoostTypeUUID,
                          .uuid = kBassBoostBundleImplUUID,
                          .proxy = kBassBoostProxyUUID},
                   .flags = {.type = Flags::Type::INSERT,
                             .insert = Flags::Insert::FIRST,
                             .volume = Flags::Volume::CTRL,
                             .deviceIndication = true},
                   .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
                   .memoryUsage = BUNDLE_MEM_USAGE,
                   .name = kBassBoostEffectName,
                   .implementor = "NXP Software Ltd."},
        .capability = Capability::make<Capability::bassBoost>(kBassBoostCap)};

// TODO: add descriptors for other bundle effect types here.
static const Descriptor kVirtualizerDesc;
static const Descriptor kBassBoostDesc;
static const Descriptor kVolumeDesc;

/* The following tables have been computed using the actual levels measured by the output of
+57 −3
Original line number Diff line number Diff line
@@ -32,12 +32,13 @@
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::EffectBundleAidl;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kBassBoostBundleImplUUID;
using aidl::android::hardware::audio::effect::kEqualizerBundleImplUUID;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioUuid;

bool isUuidSupported(const AudioUuid* uuid) {
    return *uuid == kEqualizerBundleImplUUID;
    return (*uuid == kEqualizerBundleImplUUID || *uuid == kBassBoostBundleImplUUID);
}

extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
@@ -57,11 +58,15 @@ extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
}

extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
    if (!in_impl_uuid || *in_impl_uuid != kEqualizerBundleImplUUID) {
    if (!in_impl_uuid || !isUuidSupported(in_impl_uuid)) {
        LOG(ERROR) << __func__ << "uuid not supported";
        return EX_ILLEGAL_ARGUMENT;
    }
    if (*in_impl_uuid == kEqualizerBundleImplUUID) {
        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kEqualizerDesc;
    } else if (*in_impl_uuid == kBassBoostBundleImplUUID) {
        *_aidl_return = aidl::android::hardware::audio::effect::lvm:: kBassBoostDesc;
    }
    return EX_NONE;
}

@@ -73,6 +78,10 @@ EffectBundleAidl::EffectBundleAidl(const AudioUuid& uuid) {
        mType = lvm::BundleEffectType::EQUALIZER;
        mDescriptor = &lvm::kEqualizerDesc;
        mEffectName = &lvm::kEqualizerEffectName;
    } else if (uuid == kBassBoostBundleImplUUID) {
        mType = lvm::BundleEffectType::BASS_BOOST;
        mDescriptor = &lvm::kBassBoostDesc;
        mEffectName = &lvm::kBassBoostEffectName;
    } else {
        // TODO: add other bundle effect types here.
        LOG(ERROR) << __func__ << uuid.toString() << " not supported yet!";
@@ -135,6 +144,8 @@ ndk::ScopedAStatus EffectBundleAidl::setParameterSpecific(const Parameter::Speci
    switch (tag) {
        case Parameter::Specific::equalizer:
            return setParameterEqualizer(specific);
        case Parameter::Specific::bassBoost:
            return setParameterBassBoost(specific);
        default:
            LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -162,6 +173,23 @@ ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Spec
    }
}

ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
    auto& bb = specific.get<Parameter::Specific::bassBoost>();
    auto bbTag = bb.getTag();
    switch (bbTag) {
        case BassBoost::strengthPm: {
            RETURN_IF(mContext->setBassBoostStrength(bb.get<BassBoost::strengthPm>()) !=
                              RetCode::SUCCESS,
                      EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
            return ndk::ScopedAStatus::ok();
        }
        default:
            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                    "bbTagNotSupported");
    }
}

ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
                                                          Parameter::Specific* specific) {
    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
@@ -170,6 +198,8 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& i
    switch (tag) {
        case Parameter::Id::equalizerTag:
            return getParameterEqualizer(id.get<Parameter::Id::equalizerTag>(), specific);
        case Parameter::Id::bassBoostTag:
            return getParameterBassBoost(id.get<Parameter::Id::bassBoostTag>(), specific);
        default:
            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -205,6 +235,30 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Id&
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus EffectBundleAidl::getParameterBassBoost(const BassBoost::Id& id,
                                                           Parameter::Specific* specific) {
    RETURN_IF(id.getTag() != BassBoost::Id::commonTag, EX_ILLEGAL_ARGUMENT,
              "BassBoostTagNotSupported");
    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
    BassBoost bbParam;

    auto tag = id.get<BassBoost::Id::commonTag>();
    switch (tag) {
        case BassBoost::strengthPm: {
            bbParam.set<BassBoost::strengthPm>(mContext->getBassBoostStrength());
            break;
        }
        default: {
            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                    "BassBoostTagNotSupported");
        }
    }

    specific->set<Parameter::Specific::bassBoost>(bbParam);
    return ndk::ScopedAStatus::ok();
}

std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
    if (mContext) {
        LOG(DEBUG) << __func__ << " context already exist";
+4 −0
Original line number Diff line number Diff line
@@ -60,6 +60,10 @@ class EffectBundleAidl final : public EffectImpl {

    IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);

    ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific);
    ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id,
                                             Parameter::Specific* specific);

    ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
    ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
                                             Parameter::Specific* specific);