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

Commit 27a2fdfb authored by Eric Laurent's avatar Eric Laurent
Browse files

Fix volume problems with insert revert

- Use a constant input level to the reverb engine and implement volume control in the
insert reverb. This avoids the volume spikes when an effect that was inserted after
the reverb is disabled or removed.
- Fix clicks (one silent buffer) at the end of the reverb disable period.
- Modified volume management in audioflinger so that the volume ramp is also done by
the insert effect if present when the track is paused (avoids clicks).
- Increased room level for all presets.

Also fixed problems with output stage session (-1):
- effect bundle wrapper was not designed to support session -1
- the permission check in audioflinger for using session -1 failed due to a wrong usage of
getCallingPid()

Change-Id: Id1ff51327263364bf71d3f2668fa5cde4311d84f
parent e442fb6c
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ namespace {
int LvmInitFlag = LVM_FALSE;
int LvmSessionsActive = 0;
SessionContext GlobalSessionMemory[LVM_MAX_SESSIONS];

int SessionIndex[LVM_MAX_SESSIONS];

// NXP SW BassBoost UUID
@@ -199,11 +200,6 @@ extern "C" int EffectCreate(effect_uuid_t *uuid,
        return -EINVAL;
    }

    if(sessionId < 0){
        LOGV("\tLVM_ERROR : EffectCreate sessionId is less than 0");
        return -EINVAL;
    }

    if(LvmInitFlag == LVM_FALSE){
        LvmInitFlag = LVM_TRUE;
        LOGV("\tEffectCreate - Initializing all global memory");
@@ -214,7 +210,7 @@ extern "C" int EffectCreate(effect_uuid_t *uuid,

    // Find next available sessionNo
    for(i=0; i<LVM_MAX_SESSIONS; i++){
        if((SessionIndex[i] == -1)||(SessionIndex[i] == sessionId)){
        if((SessionIndex[i] == LVM_UNUSED_SESSION)||(SessionIndex[i] == sessionId)){
            sessionNo       = i;
            SessionIndex[i] = sessionId;
            LOGV("\tEffectCreate: Allocating SessionNo %d for SessionId %d\n", sessionNo,sessionId);
@@ -398,7 +394,7 @@ extern "C" int EffectRelease(effect_interface_t interface){
        // Clear the SessionIndex
        for(int i=0; i<LVM_MAX_SESSIONS; i++){
            if(SessionIndex[i] == pContext->pBundledContext->SessionId){
                SessionIndex[i] = -1;
                SessionIndex[i] = LVM_UNUSED_SESSION;
                LOGV("\tEffectRelease: Clearing SessionIndex SessionNo %d for SessionId %d\n",
                        i, pContext->pBundledContext->SessionId);
                break;
@@ -432,7 +428,7 @@ void LvmGlobalBundle_init(){
        GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE;
        GlobalSessionMemory[i].pBundledContext          = LVM_NULL;

        SessionIndex[i] = -1;
        SessionIndex[i] = LVM_UNUSED_SESSION;
    }
    return;
}
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <media/EffectBassBoostApi.h>
#include <media/EffectVirtualizerApi.h>
#include <LVM.h>
#include <limits.h>

#if __cplusplus
extern "C" {
@@ -30,6 +31,7 @@ extern "C" {
#define MAX_NUM_BANDS              5
#define MAX_CALL_SIZE              256
#define LVM_MAX_SESSIONS           32
#define LVM_UNUSED_SESSION         INT_MAX
#define BASS_BOOST_CUP_LOAD_ARM9E  150    // Expressed in 0.1 MIPS
#define VIRTUALIZER_CUP_LOAD_ARM9E 120    // Expressed in 0.1 MIPS
#define EQUALIZER_CUP_LOAD_ARM9E   220    // Expressed in 0.1 MIPS
+115 −20
Original line number Diff line number Diff line
@@ -59,17 +59,17 @@ const static t_reverb_settings sReverbPresets[] = {
        // REVERB_PRESET_NONE: values are unused
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        // REVERB_PRESET_SMALLROOM
        {-1000, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
        {-400, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
        // REVERB_PRESET_MEDIUMROOM
        {-1000, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
        {-400, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
        // REVERB_PRESET_LARGEROOM
        {-1000, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
        {-400, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
        // REVERB_PRESET_MEDIUMHALL
        {-1000, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
        {-400, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
        // REVERB_PRESET_LARGEHALL
        {-1000, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
        {-400, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
        // REVERB_PRESET_PLATE
        {-1000, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
        {-400, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
};


@@ -90,7 +90,7 @@ static const effect_descriptor_t gInsertEnvReverbDescriptor = {
        {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
        {0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
        EFFECT_API_VERSION,
        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL,
        LVREV_CUP_LOAD_ARM9E,
        LVREV_MEM_USAGE,
        "Insert Environmental Reverb",
@@ -114,7 +114,7 @@ static const effect_descriptor_t gInsertPresetReverbDescriptor = {
        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
        {0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
        EFFECT_API_VERSION,
        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL,
        LVREV_CUP_LOAD_ARM9E,
        LVREV_MEM_USAGE,
        "Insert Preset Reverb",
@@ -153,10 +153,25 @@ struct ReverbContext{
    uint16_t                        curPreset;
    uint16_t                        nextPreset;
    int                             SamplesToExitCount;
    LVM_INT16                       leftVolume;
    LVM_INT16                       rightVolume;
    LVM_INT16                       prevLeftVolume;
    LVM_INT16                       prevRightVolume;
    int                             volumeMode;
};

enum {
    REVERB_VOLUME_OFF,
    REVERB_VOLUME_FLAT,
    REVERB_VOLUME_RAMP,
};

#define REVERB_DEFAULT_PRESET REVERB_PRESET_MEDIUMROOM


#define REVERB_SEND_LEVEL   (0x0C00) // 0.75 in 4.12 format
#define REVERB_UNIT_VOLUME  (0x1000) // 1.0 in 4.12 format

//--- local function prototypes
int  Reverb_init            (ReverbContext *pContext);
void Reverb_free            (ReverbContext *pContext);
@@ -426,10 +441,21 @@ int process( LVM_INT16 *pIn,
    if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
        Reverb_LoadPreset(pContext);
    }



    // Convert to Input 32 bits
    if (pContext->auxiliary) {
        for(int i=0; i<frameCount*samplesPerFrame; i++){
            pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
        }
    } else {
        // insert reverb input is always stereo
        for (int i = 0; i < frameCount; i++) {
            pContext->InFrames32[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
            pContext->InFrames32[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
        }
    }

    if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
        memset(pContext->OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2); //always stereo here
@@ -458,6 +484,42 @@ int process( LVM_INT16 *pIn,
        for (int i=0; i < frameCount*2; i++) { //always stereo here
            OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
        }

        // apply volume with ramp if needed
        if ((pContext->leftVolume != pContext->prevLeftVolume ||
                pContext->rightVolume != pContext->prevRightVolume) &&
                pContext->volumeMode == REVERB_VOLUME_RAMP) {
            LVM_INT32 vl = (LVM_INT32)pContext->prevLeftVolume << 16;
            LVM_INT32 incl = (((LVM_INT32)pContext->leftVolume << 16) - vl) / frameCount;
            LVM_INT32 vr = (LVM_INT32)pContext->prevRightVolume << 16;
            LVM_INT32 incr = (((LVM_INT32)pContext->rightVolume << 16) - vr) / frameCount;

            for (int i = 0; i < frameCount; i++) {
                OutFrames16[2*i] =
                        clamp16((LVM_INT32)((vl >> 16) * OutFrames16[2*i]) >> 12);
                OutFrames16[2*i+1] =
                        clamp16((LVM_INT32)((vr >> 16) * OutFrames16[2*i+1]) >> 12);

                vl += incl;
                vr += incr;
            }

            pContext->prevLeftVolume = pContext->leftVolume;
            pContext->prevRightVolume = pContext->rightVolume;
        } else if (pContext->volumeMode != REVERB_VOLUME_OFF) {
            if (pContext->leftVolume != REVERB_UNIT_VOLUME ||
                pContext->rightVolume != REVERB_UNIT_VOLUME) {
                for (int i = 0; i < frameCount; i++) {
                    OutFrames16[2*i] =
                            clamp16((LVM_INT32)(pContext->leftVolume * OutFrames16[2*i]) >> 12);
                    OutFrames16[2*i+1] =
                            clamp16((LVM_INT32)(pContext->rightVolume * OutFrames16[2*i+1]) >> 12);
                }
            }
            pContext->prevLeftVolume = pContext->leftVolume;
            pContext->prevRightVolume = pContext->rightVolume;
            pContext->volumeMode = REVERB_VOLUME_RAMP;
        }
    }

    #ifdef LVM_PCM
@@ -658,6 +720,12 @@ int Reverb_init(ReverbContext *pContext){
    pContext->config.outputCfg.bufferProvider.cookie        = NULL;
    pContext->config.outputCfg.mask                         = EFFECT_CONFIG_ALL;

    pContext->leftVolume = REVERB_UNIT_VOLUME;
    pContext->rightVolume = REVERB_UNIT_VOLUME;
    pContext->prevLeftVolume = REVERB_UNIT_VOLUME;
    pContext->prevRightVolume = REVERB_UNIT_VOLUME;
    pContext->volumeMode = REVERB_VOLUME_FLAT;

    LVREV_ReturnStatus_en     LvmStatus=LVREV_SUCCESS;        /* Function call status */
    LVREV_ControlParams_st    params;                         /* Control Parameters */
    LVREV_InstanceParams_st   InstParams;                     /* Instance parameters */
@@ -1781,15 +1849,6 @@ extern "C" int Reverb_process(effect_interface_t self,
        LOGV("\tLVM_ERROR : Reverb_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
        return -EINVAL;
    }
    if (pContext->bEnabled == LVM_FALSE){
        if( pContext->SamplesToExitCount > 0){
            pContext->SamplesToExitCount -= outBuffer->frameCount;
            LOGV("\tReverb_process() Effect is being stopped %d", pContext->SamplesToExitCount);
        }else{
            LOGV("\tReverb_process() Effect is being stopped");
            return -ENODATA;
        }
    }
    //LOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
    /* Process all the available frames, block processing is handled internalLY by the LVM bundle */
    status = process(    (LVM_INT16 *)inBuffer->raw,
@@ -1797,6 +1856,14 @@ extern "C" int Reverb_process(effect_interface_t self,
                                      outBuffer->frameCount,
                                      pContext);

    if (pContext->bEnabled == LVM_FALSE) {
        if (pContext->SamplesToExitCount > 0) {
            pContext->SamplesToExitCount -= outBuffer->frameCount;
        } else {
            status = -ENODATA;
        }
    }

    return status;
}   /* end Reverb_process */

@@ -1943,6 +2010,8 @@ extern "C" int Reverb_command(effect_interface_t self,
            LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "EFFECT_CMD_ENABLE")
            pContext->SamplesToExitCount =
                    (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
            // force no volume ramp for first buffer processed after enabling the effect
            pContext->volumeMode = android::REVERB_VOLUME_FLAT;
            //LOGV("\tEFFECT_CMD_ENABLE SamplesToExitCount = %d", pContext->SamplesToExitCount);
            break;
        case EFFECT_CMD_DISABLE:
@@ -1963,8 +2032,34 @@ extern "C" int Reverb_command(effect_interface_t self,
            pContext->bEnabled = LVM_FALSE;
            break;

        case EFFECT_CMD_SET_DEVICE:
        case EFFECT_CMD_SET_VOLUME:
            if (pCmdData == NULL ||
                cmdSize != 2 * sizeof(uint32_t)) {
                LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
                        "EFFECT_CMD_SET_VOLUME: ERROR");
                return -EINVAL;
            }


            if (pReplyData != NULL) { // we have volume control
                pContext->leftVolume = (LVM_INT16)((*(uint32_t *)pCmdData + (1 << 11)) >> 12);
                pContext->rightVolume = (LVM_INT16)((*((uint32_t *)pCmdData + 1) + (1 << 11)) >> 12);
                *(uint32_t *)pReplyData = (1 << 24);
                *((uint32_t *)pReplyData + 1) = (1 << 24);
                if (pContext->volumeMode == android::REVERB_VOLUME_OFF) {
                    // force no volume ramp for first buffer processed after getting volume control
                    pContext->volumeMode = android::REVERB_VOLUME_FLAT;
                }
            } else { // we don't have volume control
                pContext->leftVolume = REVERB_UNIT_VOLUME;
                pContext->rightVolume = REVERB_UNIT_VOLUME;
                pContext->volumeMode = android::REVERB_VOLUME_OFF;
            }
            LOGV("EFFECT_CMD_SET_VOLUME left %d, right %d mode %d",
                    pContext->leftVolume, pContext->rightVolume,  pContext->volumeMode);
            break;

        case EFFECT_CMD_SET_DEVICE:
        case EFFECT_CMD_SET_AUDIO_MODE:
        //LOGV("\tReverb_command cmdCode Case: "
        //        "EFFECT_CMD_SET_DEVICE/EFFECT_CMD_SET_VOLUME/EFFECT_CMD_SET_AUDIO_MODE start");
+31 −29
Original line number Diff line number Diff line
@@ -1752,14 +1752,15 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
            }

            // compute volume for this track
            int16_t left, right, aux;
            uint32_t vl, vr, va;
            if (track->isMuted() || track->isPausing() ||
                mStreamTypes[track->type()].mute) {
                left = right = aux = 0;
                vl = vr = va = 0;
                if (track->isPausing()) {
                    track->setPaused();
                }
            } else {

                // read original volumes with volume control
                float typeVolume = mStreamTypes[track->type()].volume;
#ifdef LVMX
@@ -1774,12 +1775,14 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
                }
#endif
                float v = masterVolume * typeVolume;
                uint32_t vl = (uint32_t)(v * cblk->volume[0]) << 12;
                uint32_t vr = (uint32_t)(v * cblk->volume[1]) << 12;
                vl = (uint32_t)(v * cblk->volume[0]) << 12;
                vr = (uint32_t)(v * cblk->volume[1]) << 12;

                va = (uint32_t)(v * cblk->sendLevel);
            }
            // Delegate volume control to effect in track effect chain if needed
            if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
                    // Do not ramp volume is volume is controlled by effect
                // Do not ramp volume if volume is controlled by effect
                param = AudioMixer::VOLUME;
                track->mHasVolumeController = true;
            } else {
@@ -1792,6 +1795,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
            }

            // Convert volumes from 8.24 to 4.12 format
            int16_t left, right, aux;
            uint32_t v_clamped = (vl + (1 << 11)) >> 12;
            if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
            left = int16_t(v_clamped);
@@ -1799,10 +1803,8 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
            if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
            right = int16_t(v_clamped);

                v_clamped = (uint32_t)(v * cblk->sendLevel);
                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
                aux = int16_t(v_clamped);
            }
            if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
            aux = int16_t(va);

#ifdef LVMX
            if ( tracksConnectedChanged || stateChanged )
@@ -2283,7 +2285,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
                        // only one effect chain can be present on DirectOutputThread, so if
                        // there is one, the track is connected to it
                        if (!effectChains.isEmpty()) {
                            // Do not ramp volume is volume is controlled by effect
                            // Do not ramp volume if volume is controlled by effect
                            if(effectChains[0]->setVolume_l(&vl, &vr)) {
                                rampVolume = false;
                            }
@@ -4728,7 +4730,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
        // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
        // that can only be created by audio policy manager (running in same process)
        if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE &&
                getpid() != IPCThreadState::self()->getCallingPid()) {
                getpid() != pid) {
            lStatus = INVALID_OPERATION;
            goto Exit;
        }