Merge "Fix volume problems with insert revert" into gingerbread
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index e86ed99..90756d0 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -65,6 +65,7 @@
 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 @@
         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 @@
 
     // 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 @@
         // 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 @@
         GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE;
         GlobalSessionMemory[i].pBundledContext          = LVM_NULL;
 
-        SessionIndex[i] = -1;
+        SessionIndex[i] = LVM_UNUSED_SESSION;
     }
     return;
 }
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 35e1114..91963af 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -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 @@
 #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
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 60f4288..26c5aca 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -59,17 +59,17 @@
         // 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 @@
         {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 @@
         {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 @@
     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,9 +441,20 @@
     if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
         Reverb_LoadPreset(pContext);
     }
+
+
+
     // Convert to Input 32 bits
-    for(int i=0; i<frameCount*samplesPerFrame; i++){
-        pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
+    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) {
@@ -458,6 +484,42 @@
         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 @@
     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 @@
         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 @@
                                       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 @@
             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 @@
             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");
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3770b55..886c25b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1752,14 +1752,15 @@
             }
 
             // 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,35 +1775,36 @@
                 }
 #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;
 
-                // 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
-                    param = AudioMixer::VOLUME;
-                    track->mHasVolumeController = true;
-                } else {
-                    // force no volume ramp when volume controller was just disabled or removed
-                    // from effect chain to avoid volume spike
-                    if (track->mHasVolumeController) {
-                        param = AudioMixer::VOLUME;
-                    }
-                    track->mHasVolumeController = false;
-                }
-
-                // Convert volumes from 8.24 to 4.12 format
-                uint32_t v_clamped = (vl + (1 << 11)) >> 12;
-                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
-                left = int16_t(v_clamped);
-                v_clamped = (vr + (1 << 11)) >> 12;
-                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);
+                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 if volume is controlled by effect
+                param = AudioMixer::VOLUME;
+                track->mHasVolumeController = true;
+            } else {
+                // force no volume ramp when volume controller was just disabled or removed
+                // from effect chain to avoid volume spike
+                if (track->mHasVolumeController) {
+                    param = AudioMixer::VOLUME;
+                }
+                track->mHasVolumeController = false;
+            }
+
+            // 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);
+            v_clamped = (vr + (1 << 11)) >> 12;
+            if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+            right = 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 @@
                         // 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 @@
         // 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;
         }