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

Commit 77ceb6d0 authored by Ahmad Khalil's avatar Ahmad Khalil
Browse files

Add adaptive haptics to HapticGenerator

We're adding the ability to use the adaptive haptics scale in the HapticGenerator.

Bug: 324559333
Test: N/A
Change-Id: I99a9bd334174464d63b065170124f923845073bd
parent 52800b19
Loading
Loading
Loading
Loading
+22 −18
Original line number Diff line number Diff line
@@ -114,10 +114,11 @@ std::string hapticSettingToString(const struct HapticGeneratorParam& param) {
    std::stringstream ss;
    ss << "\t\tHaptic setting:\n";
    ss << "\t\t- tracks intensity map:\n";
    for (const auto&[id, intensity] : param.id2Intensity) {
        ss << "\t\t\t- id=" << id << ", intensity=" << (int) intensity;
    for (const auto&[id, hapticScale] : param.id2HapticScale) {
        ss << "\t\t\t- id=" << id << ", hapticLevel=" << (int) hapticScale.getLevel()
           << ", adaptiveScaleFactor=" << hapticScale.getAdaptiveScaleFactor();
    }
    ss << "\t\t- max intensity: " << (int) param.maxHapticIntensity << '\n';
    ss << "\t\t- max scale level: " << (int) param.maxHapticScale.getLevel() << '\n';
    ss << "\t\t- max haptic amplitude: " << param.maxHapticAmplitude << '\n';
    return ss.str();
}
@@ -145,7 +146,7 @@ int HapticGenerator_Init(struct HapticGeneratorContext *context) {
    memset(context->param.hapticChannelSource, 0, sizeof(context->param.hapticChannelSource));
    context->param.hapticChannelCount = 0;
    context->param.audioChannelCount = 0;
    context->param.maxHapticIntensity = os::HapticLevel::MUTE;
    context->param.maxHapticScale = os::HapticScale::mute();

    context->param.resonantFrequency = DEFAULT_RESONANT_FREQUENCY;
    context->param.bpfQ = 1.0f;
@@ -312,22 +313,25 @@ int HapticGenerator_SetParameter(struct HapticGeneratorContext *context,
                                 void *value) {
    switch (param) {
    case HG_PARAM_HAPTIC_INTENSITY: {
        if (value == nullptr || size != (uint32_t) (2 * sizeof(int))) {
        if (value == nullptr || size != (uint32_t) (2 * sizeof(int) + sizeof(float))) {
            return -EINVAL;
        }
        int id = *(int *) value;
        os::HapticLevel hapticIntensity =
                static_cast<os::HapticLevel>(*((int *) value + 1));
        ALOGD("Setting haptic intensity as %d", static_cast<int>(hapticIntensity));
        if (hapticIntensity == os::HapticLevel::MUTE) {
            context->param.id2Intensity.erase(id);
        const int id = *(int *) value;
        const os::HapticLevel hapticLevel = static_cast<os::HapticLevel>(*((int *) value + 1));
        const float adaptiveScaleFactor = (*((float *) value + 2));
        const os::HapticScale hapticScale = {hapticLevel, adaptiveScaleFactor};
        ALOGD("Updating haptic scale, hapticLevel=%d, adaptiveScaleFactor=%f",
              static_cast<int>(hapticLevel), adaptiveScaleFactor);
        if (hapticScale.isScaleMute()) {
            context->param.id2HapticScale.erase(id);
        } else {
            context->param.id2Intensity.emplace(id, hapticIntensity);
            context->param.id2HapticScale.emplace(id, hapticScale);
        }
        context->param.maxHapticScale = hapticScale;
        for (const auto&[id, scale] : context->param.id2HapticScale) {
            if (scale.getLevel() > context->param.maxHapticScale.getLevel()) {
                context->param.maxHapticScale = scale;
            }
        context->param.maxHapticIntensity = hapticIntensity;
        for (const auto&[id, intensity] : context->param.id2Intensity) {
            context->param.maxHapticIntensity = std::max(
                    context->param.maxHapticIntensity, intensity);
        }
        break;
    }
@@ -479,7 +483,7 @@ int32_t HapticGenerator_Process(effect_handle_t self,
        return -ENODATA;
    }

    if (context->param.maxHapticIntensity == os::HapticLevel::MUTE) {
    if (context->param.maxHapticScale.isScaleMute()) {
        // Haptic channels are muted, not need to generate haptic data.
        return 0;
    }
@@ -506,7 +510,7 @@ int32_t HapticGenerator_Process(effect_handle_t self,
            context->processingChain, context->inputBuffer.data(),
            context->outputBuffer.data(), inBuffer->frameCount);
        os::scaleHapticData(hapticOutBuffer, hapticSampleCount,
                            { /*level=*/context->param.maxHapticIntensity},
                            context->param.maxHapticScale,
                            context->param.maxHapticAmplitude);

    // For haptic data, the haptic playback thread will copy the data from effect input buffer,
+3 −3
Original line number Diff line number Diff line
@@ -48,9 +48,9 @@ struct HapticGeneratorParam {
    uint32_t audioChannelCount;
    uint32_t hapticChannelCount;

    // A map from track id to haptic intensity.
    std::map<int, os::HapticLevel> id2Intensity;
    os::HapticLevel maxHapticIntensity; // max intensity will be used to scale haptic data.
    // A map from track id to haptic scale.
    std::map<int, os::HapticScale> id2HapticScale;
    os::HapticScale maxHapticScale; // max haptic scale will be used to scale haptic data.
    float maxHapticAmplitude; // max amplitude will be used to limit haptic data absolute values.

    float resonantFrequency;
+7 −4
Original line number Diff line number Diff line
@@ -1545,13 +1545,16 @@ status_t EffectModule::setHapticScale_l(int id, os::HapticScale hapticScale) {
        return INVALID_OPERATION;
    }

    std::vector<uint8_t> request(sizeof(effect_param_t) + 3 * sizeof(uint32_t));
    std::vector<uint8_t> request(sizeof(effect_param_t) + 3 * sizeof(uint32_t) + sizeof(float));
    effect_param_t *param = (effect_param_t*) request.data();
    param->psize = sizeof(int32_t);
    param->vsize = sizeof(int32_t) * 2;
    param->vsize = sizeof(int32_t) * 2 + sizeof(float);
    *(int32_t*)param->data = HG_PARAM_HAPTIC_INTENSITY;
    *((int32_t*)param->data + 1) = id;
    *((int32_t*)param->data + 2) = static_cast<int32_t>(hapticScale.getLevel());
    int32_t* hapticScalePtr = reinterpret_cast<int32_t*>(param->data + sizeof(int32_t));
    hapticScalePtr[0] = id;
    hapticScalePtr[1] = static_cast<int32_t>(hapticScale.getLevel());
    float* adaptiveScaleFactorPtr = reinterpret_cast<float*>(param->data + 3 * sizeof(int32_t));
    *adaptiveScaleFactorPtr = hapticScale.getAdaptiveScaleFactor();
    std::vector<uint8_t> response;
    status_t status = command(EFFECT_CMD_SET_PARAM, request, sizeof(int32_t), &response);
    if (status == NO_ERROR) {
+0 −1
Original line number Diff line number Diff line
@@ -2927,7 +2927,6 @@ status_t PlaybackThread::addTrack_l(const sp<IAfTrack>& track)

            // Set haptic intensity for effect
            if (chain != nullptr) {
                // TODO(b/324559333): Add adaptive haptics scaling support for the HapticGenerator.
                chain->setHapticScale_l(track->id(), hapticScale);
            }
        }