Merge "Fix for Bundled Effects level compensation" into lmp-mr1-dev
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 3ddeb4e..6aeb919 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -766,6 +766,122 @@
     return 0;
 }    /* end LvmBundle_process */
 
+
+//----------------------------------------------------------------------------
+// EqualizerUpdateActiveParams()
+//----------------------------------------------------------------------------
+// Purpose: Update ActiveParams for Equalizer
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+void EqualizerUpdateActiveParams(EffectContext *pContext) {
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerUpdateActiveParams")
+    //ALOGV("\tEqualizerUpdateActiveParams Succesfully returned from LVM_GetControlParameters\n");
+    //ALOGV("\tEqualizerUpdateActiveParams just Got -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+
+    for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+           ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+           ActiveParams.pEQNB_BandDefinition[i].QFactor   = EQNB_5BandPresetsQFactors[i];
+           ActiveParams.pEQNB_BandDefinition[i].Gain = pContext->pBundledContext->bandGaindB[i];
+       }
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerUpdateActiveParams")
+    //ALOGV("\tEqualizerUpdateActiveParams just Set -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+}
+
+//----------------------------------------------------------------------------
+// LvmEffect_limitLevel()
+//----------------------------------------------------------------------------
+// Purpose: limit the overall level to a value less than 0 dB preserving
+//          the overall EQ band gain and BassBoost relative levels.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+void LvmEffect_limitLevel(EffectContext *pContext) {
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_limitLevel")
+    //ALOGV("\tLvmEffect_limitLevel Succesfully returned from LVM_GetControlParameters\n");
+    //ALOGV("\tLvmEffect_limitLevel just Got -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+    int gainCorrection = 0;
+    //Count the energy contribution per band for EQ and BassBoost only if they are active.
+    float energyContribution = 0;
+
+    //EQ contribution
+    if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
+        for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+            float bandEnergy = (pContext->pBundledContext->bandGaindB[i] *
+                    LimitLevel_bandEnergyContribution[i])/15.0;
+            if (bandEnergy > 0)
+                energyContribution += bandEnergy;
+        }
+    }
+
+    //BassBoost contribution
+    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
+        float bandEnergy = (pContext->pBundledContext->BassStrengthSaved *
+                LimitLevel_bassBoostEnergyContribution)/1000.0;
+        if (bandEnergy > 0)
+            energyContribution += bandEnergy;
+    }
+
+    //Virtualizer contribution
+    if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
+                   energyContribution += LimitLevel_virtualizerContribution;
+        }
+
+    //roundoff
+    int maxLevelRound = (int)(energyContribution + 0.99);
+    if (maxLevelRound + pContext->pBundledContext->volume > 0) {
+        gainCorrection = maxLevelRound + pContext->pBundledContext->volume;
+    }
+
+    ActiveParams.VC_EffectLevel  = pContext->pBundledContext->volume - gainCorrection;
+    if (ActiveParams.VC_EffectLevel < -96) {
+        ActiveParams.VC_EffectLevel = -96;
+    }
+    ALOGV("\tVol:%d, GainCorrection: %d, Actual vol: %d", pContext->pBundledContext->volume,
+            gainCorrection, ActiveParams.VC_EffectLevel);
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_limitLevel")
+    //ALOGV("\tLvmEffect_limitLevel just Set -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+    //ALOGV("\tLvmEffect_limitLevel just set (-96dB -> 0dB) -> %d\n",ActiveParams.VC_EffectLevel );
+    if (pContext->pBundledContext->firstVolume == LVM_TRUE){
+        LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
+        LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
+        ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
+        pContext->pBundledContext->firstVolume = LVM_FALSE;
+    }
+}
+
 //----------------------------------------------------------------------------
 // LvmEffect_enable()
 //----------------------------------------------------------------------------
@@ -814,6 +930,7 @@
 
     //ALOGV("\tLvmEffect_enable Succesfully called LVM_SetControlParameters\n");
     //ALOGV("\tLvmEffect_enable end");
+    LvmEffect_limitLevel(pContext);
     return 0;
 }
 
@@ -864,6 +981,7 @@
 
     //ALOGV("\tLvmEffect_disable Succesfully called LVM_SetControlParameters\n");
     //ALOGV("\tLvmEffect_disable end");
+    LvmEffect_limitLevel(pContext);
     return 0;
 }
 
@@ -1099,6 +1217,8 @@
 
     LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "BassSetStrength")
     //ALOGV("\tBassSetStrength Succesfully called LVM_SetControlParameters\n");
+
+    LvmEffect_limitLevel(pContext);
 }    /* end BassSetStrength */
 
 //----------------------------------------------------------------------------
@@ -1159,13 +1279,14 @@
     /* Virtualizer parameters */
     ActiveParams.CS_EffectLevel             = (int)((strength*32767)/1000);
 
-    //ALOGV("\tVirtualizerSetStrength() (0-1000)   -> %d\n", strength );
-    //ALOGV("\tVirtualizerSetStrength() (0- 100)   -> %d\n", ActiveParams.CS_EffectLevel );
+    ALOGV("\tVirtualizerSetStrength() (0-1000)   -> %d\n", strength );
+    ALOGV("\tVirtualizerSetStrength() (0- 100)   -> %d\n", ActiveParams.CS_EffectLevel );
 
     /* Activate the initial settings */
     LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
     LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VirtualizerSetStrength")
     //ALOGV("\tVirtualizerSetStrength Succesfully called LVM_SetControlParameters\n\n");
+    LvmEffect_limitLevel(pContext);
 }    /* end setStrength */
 
 //----------------------------------------------------------------------------
@@ -1343,104 +1464,6 @@
 }
 
 //----------------------------------------------------------------------------
-// EqualizerLimitBandLevels()
-//----------------------------------------------------------------------------
-// Purpose: limit all EQ band gains to a value less than 0 dB while
-//          preserving the relative band levels.
-//
-// Inputs:
-//  pContext:   effect engine context
-//
-// Outputs:
-//
-//----------------------------------------------------------------------------
-void EqualizerLimitBandLevels(EffectContext *pContext) {
-    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
-    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
-
-    /* Get the current settings */
-    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
-    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerLimitBandLevels")
-    //ALOGV("\tEqualizerLimitBandLevels Succesfully returned from LVM_GetControlParameters\n");
-    //ALOGV("\tEqualizerLimitBandLevels just Got -> %d\n",
-    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
-
-    // Apply a volume correction to avoid clipping in the EQ based on 2 factors:
-    // - the maximum EQ band gain: the volume correction is such that the total of volume + max
-    // band gain is <= 0 dB
-    // - the average gain in all bands weighted by their proximity to max gain band.
-    int maxGain = 0;
-    int avgGain = 0;
-    int avgCount = 0;
-    for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
-        if (pContext->pBundledContext->bandGaindB[i] >= maxGain) {
-            int tmpMaxGain = pContext->pBundledContext->bandGaindB[i];
-            int tmpAvgGain = 0;
-            int tmpAvgCount = 0;
-            for (int j = 0; j < FIVEBAND_NUMBANDS; j++) {
-                int gain = pContext->pBundledContext->bandGaindB[j];
-                // skip current band and gains < 0 dB
-                if (j == i || gain < 0)
-                    continue;
-                // no need to continue if one band not processed yet has a higher gain than current
-                // max
-                if (gain > tmpMaxGain) {
-                    // force skipping "if (tmpAvgGain >= avgGain)" below as tmpAvgGain is not
-                    // meaningful in this case
-                    tmpAvgGain = -1;
-                    break;
-                }
-
-                int weight = 1;
-                if (j < (i + 2) && j > (i - 2))
-                    weight = 4;
-                tmpAvgGain += weight * gain;
-                tmpAvgCount += weight;
-            }
-            if (tmpAvgGain >= avgGain) {
-                maxGain = tmpMaxGain;
-                avgGain = tmpAvgGain;
-                avgCount = tmpAvgCount;
-            }
-        }
-        ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
-        ActiveParams.pEQNB_BandDefinition[i].QFactor   = EQNB_5BandPresetsQFactors[i];
-        ActiveParams.pEQNB_BandDefinition[i].Gain = pContext->pBundledContext->bandGaindB[i];
-    }
-
-    int gainCorrection = 0;
-    if (maxGain + pContext->pBundledContext->volume > 0) {
-        gainCorrection = maxGain + pContext->pBundledContext->volume;
-    }
-    if (avgCount) {
-        gainCorrection += avgGain/avgCount;
-    }
-
-    ALOGV("EqualizerLimitBandLevels() gainCorrection %d maxGain %d avgGain %d avgCount %d",
-            gainCorrection, maxGain, avgGain, avgCount);
-
-    ActiveParams.VC_EffectLevel  = pContext->pBundledContext->volume - gainCorrection;
-    if (ActiveParams.VC_EffectLevel < -96) {
-        ActiveParams.VC_EffectLevel = -96;
-    }
-
-    /* Activate the initial settings */
-    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
-    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerLimitBandLevels")
-    //ALOGV("\tEqualizerLimitBandLevels just Set -> %d\n",
-    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
-
-    //ALOGV("\tEqualizerLimitBandLevels just set (-96dB -> 0dB)   -> %d\n",ActiveParams.VC_EffectLevel );
-    if(pContext->pBundledContext->firstVolume == LVM_TRUE){
-        LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
-        LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
-        ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
-        pContext->pBundledContext->firstVolume = LVM_FALSE;
-    }
-}
-
-
-//----------------------------------------------------------------------------
 // EqualizerGetBandLevel()
 //----------------------------------------------------------------------------
 // Purpose: Retrieve the gain currently being used for the band passed in
@@ -1482,7 +1505,8 @@
     pContext->pBundledContext->bandGaindB[band] = gainRounded;
     pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
 
-    EqualizerLimitBandLevels(pContext);
+    EqualizerUpdateActiveParams(pContext);
+    LvmEffect_limitLevel(pContext);
 }
 
 //----------------------------------------------------------------------------
@@ -1617,7 +1641,8 @@
                 EQNB_5BandSoftPresets[i + preset * FIVEBAND_NUMBANDS];
     }
 
-    EqualizerLimitBandLevels(pContext);
+    EqualizerUpdateActiveParams(pContext);
+    LvmEffect_limitLevel(pContext);
 
     //ALOGV("\tEqualizerSetPreset Succesfully called LVM_SetControlParameters\n");
     return;
@@ -1672,7 +1697,7 @@
         pContext->pBundledContext->volume = level / 100;
     }
 
-    EqualizerLimitBandLevels(pContext);
+    LvmEffect_limitLevel(pContext);
 
     return 0;
 }    /* end VolumeSetVolumeLevel */
@@ -1721,7 +1746,7 @@
         pContext->pBundledContext->volume = pContext->pBundledContext->levelSaved;
     }
 
-    EqualizerLimitBandLevels(pContext);
+    LvmEffect_limitLevel(pContext);
 
     return 0;
 }    /* end setMute */
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 420f973..b3071f4 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -142,6 +142,7 @@
                                        {1800001, 7000000},
                                        {7000001, 1}};
 
+//Note: If these frequencies change, please update LimitLevel values accordingly.
 static const LVM_UINT16  EQNB_5BandPresetsFrequencies[] = {
                                        60,           /* Frequencies in Hz */
                                        230,
@@ -192,6 +193,20 @@
                                         {"Pop"},
                                         {"Rock"}};
 
+/* The following tables have been computed using the actual levels measured by the output of
+ * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
+ * the actual energy that 'could' be present in the given band.
+ * If the frequency values in EQNB_5BandPresetsFrequencies change, these values might need to be
+ * updated.
+ */
+
+static const float LimitLevel_bandEnergyContribution[FIVEBAND_NUMBANDS] = {
+        5.0, 6.5, 6.45, 4.8, 1.7 };
+
+static const float LimitLevel_bassBoostEnergyContribution = 6.7;
+
+static const float LimitLevel_virtualizerContribution = 1.9;
+
 #if __cplusplus
 }  // extern "C"
 #endif