Merge "Biquad filter integration to LVM : Continuation"
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index 1f0b459..814280f 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -23,6 +23,7 @@
 
 #ifdef BIQUAD_OPT
 #include <audio_utils/BiquadFilter.h>
+#include <system/audio.h>
 #endif
 #include "LVDBE.h"
 #include "LVDBE_Private.h"
@@ -114,7 +115,7 @@
     std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
             LVDBE_HPF_Table[Offset].A0, LVDBE_HPF_Table[Offset].A1, LVDBE_HPF_Table[Offset].A2,
             -(LVDBE_HPF_Table[Offset].B1), -(LVDBE_HPF_Table[Offset].B2)};
-    pInstance->pBqInstance
+    pInstance->pHPFBiquad
             ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
 #else
     LoadConst_Float(0,                                      /* Clear the history, value 0 */
@@ -128,12 +129,19 @@
     /*
      * Setup the band pass filter
      */
+#ifdef BIQUAD_OPT
+    coefs = {LVDBE_BPF_Table[Offset].A0, 0.0, -(LVDBE_BPF_Table[Offset].A0),
+             -(LVDBE_BPF_Table[Offset].B1), -(LVDBE_BPF_Table[Offset].B2)};
+    pInstance->pBPFBiquad
+            ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
+#else
     LoadConst_Float(0,                                      /* Clear the history, value 0 */
                     (LVM_FLOAT*)&pInstance->pData->BPFTaps, /* Destination */
                     sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
                                     &pInstance->pData->BPFTaps,
                                     (BP_FLOAT_Coefs_t*)&LVDBE_BPF_Table[Offset]);
+#endif
 }
 
 /************************************************************************************/
@@ -290,9 +298,8 @@
     /*
      * Create biquad instance
      */
-    pInstance->pBqInstance.reset(
-            new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels));
-    pInstance->pBqInstance->clear();
+    pInstance->pHPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
+            (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
 #endif
 
     /*
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
index 611b762..6bdb7fe 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
@@ -20,8 +20,11 @@
 /*    Includes                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
-#include <stdlib.h>
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
+#include <stdlib.h>
 #include "LVDBE.h"
 #include "LVDBE_Private.h"
 
@@ -89,17 +92,18 @@
     if (pInstance->pData == NULL) {
         return LVDBE_NULLADDRESS;
     }
-    pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
-    if (pInstance->pCoef == NULL) {
-        return LVDBE_NULLADDRESS;
-    }
-
 #ifdef BIQUAD_OPT
     /*
      * Create biquad instance
      */
-    pInstance->pBqInstance.reset(
+    pInstance->pHPFBiquad.reset(
             new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+    pInstance->pBPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
+#else
+    pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
+    if (pInstance->pCoef == NULL) {
+        return LVDBE_NULLADDRESS;
+    }
 #endif
 
     /*
@@ -190,10 +194,12 @@
         free(pInstance->pData);
         pInstance->pData = LVM_NULL;
     }
+#ifndef BIQUAD_OPT
     if (pInstance->pCoef != LVM_NULL) {
         free(pInstance->pCoef);
         pInstance->pCoef = LVM_NULL;
     }
+#endif
     free(pInstance);
     *phInstance = LVM_NULL;
 }
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index fa85638..23be2aa 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -68,21 +68,22 @@
     /* Process variables */
 #ifndef BIQUAD_OPT
     Biquad_2I_Order2_FLOAT_Taps_t HPFTaps; /* High pass filter taps */
-#endif
     Biquad_1I_Order2_FLOAT_Taps_t BPFTaps; /* Band pass filter taps */
+#endif
     LVMixer3_1St_FLOAT_st BypassVolume;    /* Bypass volume scaler */
     LVMixer3_2St_FLOAT_st BypassMixer;     /* Bypass Mixer for Click Removal */
 
 } LVDBE_Data_FLOAT_t;
 
+#ifndef BIQUAD_OPT
 /* Coefs structure */
 typedef struct {
     /* Process variables */
-#ifndef BIQUAD_OPT
     Biquad_FLOAT_Instance_t HPFInstance; /* High pass filter instance */
-#endif
     Biquad_FLOAT_Instance_t BPFInstance; /* Band pass filter instance */
 } LVDBE_Coef_FLOAT_t;
+#endif
+
 /* Instance structure */
 typedef struct {
     /* Public parameters */
@@ -91,11 +92,15 @@
 
     /* Data and coefficient pointers */
     LVDBE_Data_FLOAT_t* pData; /* Instance data */
+#ifndef BIQUAD_OPT
     LVDBE_Coef_FLOAT_t* pCoef; /* Instance coefficients */
+#endif
     void* pScratch;            /* scratch pointer */
 #ifdef BIQUAD_OPT
     std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
-            pBqInstance; /* Biquad filter instance */
+            pHPFBiquad; /* Biquad filter instance for HPF */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pBPFBiquad; /* Biquad filter instance for BPF */
 #endif
 } LVDBE_Instance_t;
 
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
index bd04a02..4a72834 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -129,7 +129,7 @@
          */
         if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
 #ifdef BIQUAD_OPT
-            pInstance->pBqInstance->process(pScratch, pScratch, NrFrames);
+            pInstance->pHPFBiquad->process(pScratch, pScratch, NrFrames);
 #else
             BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance      */
                                        pScratch,                       /* Source               */
@@ -149,10 +149,14 @@
         /*
          * Apply the band pass filter
          */
+#ifdef BIQUAD_OPT
+        pInstance->pBPFBiquad->process(pMono, pMono, NrFrames);
+#else
         BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
                                    pMono,                          /* Source                */
                                    pMono,                          /* Destination           */
                                    (LVM_INT16)NrFrames);
+#endif
 
         /*
          * Apply the AGC and mix
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
index 3118e77..7e8664a 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
@@ -276,6 +276,16 @@
              */
             Offset = (LVM_INT16)(EffectLevel - 1 +
                                  TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+#ifdef BIQUAD_OPT
+            /*
+             * Create biquad instance
+             */
+            std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                    LVM_TrebleBoostCoefs[Offset].A0, LVM_TrebleBoostCoefs[Offset].A1, 0.0,
+                    -(LVM_TrebleBoostCoefs[Offset].B1), 0.0};
+            pInstance->pTEBiquad.reset(
+                    new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels, coefs));
+#else
             FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
                                                  &pInstance->pTE_Taps->TrebleBoost_Taps,
                                                  &LVM_TrebleBoostCoefs[Offset]);
@@ -288,6 +298,7 @@
                                                    Cast to void: no dereferencing in function */
                             (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) /
                                          sizeof(LVM_FLOAT))); /* Number of words */
+#endif
         }
     } else {
         /*
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
index bb962df..bbfa0dc 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
@@ -174,6 +174,7 @@
     /*
      * Treble Enhancement
      */
+#ifndef BIQUAD_OPT
     pInstance->pTE_Taps = (LVM_TE_Data_t*)calloc(1, sizeof(*(pInstance->pTE_Taps)));
     if (pInstance->pTE_Taps == LVM_NULL) {
         return LVM_NULLADDRESS;
@@ -182,6 +183,7 @@
     if (pInstance->pTE_State == LVM_NULL) {
         return LVM_NULLADDRESS;
     }
+#endif
     pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
     pInstance->Params.TE_EffectLevel = 0;
     pInstance->TE_Active = LVM_FALSE;
@@ -494,6 +496,7 @@
     /*
      * Treble Enhancement
      */
+#ifndef BIQUAD_OPT
     if (pInstance->pTE_Taps != LVM_NULL) {
         free(pInstance->pTE_Taps);
         pInstance->pTE_Taps = LVM_NULL;
@@ -502,6 +505,7 @@
         free(pInstance->pTE_State);
         pInstance->pTE_State = LVM_NULL;
     }
+#endif
 
     /*
      * Free the default EQNB pre-gain and pointer to the band definitions
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 90a1f19..56bbfd1 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -33,6 +33,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVM.h"            /* LifeVibes */
 #include "LVM_Common.h"     /* LifeVibes common */
 #include "BIQUAD.h"         /* Biquad library */
@@ -127,6 +130,7 @@
     LVM_INT16 SamplesToOutput; /* Samples to write to the output */
 } LVM_Buffer_t;
 
+#ifndef BIQUAD_OPT
 /* Filter taps */
 typedef struct {
     Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps; /* Treble boost Taps */
@@ -136,6 +140,7 @@
 typedef struct {
     Biquad_FLOAT_Instance_t TrebleBoost_State; /* State for the treble boost filter */
 } LVM_TE_Coefs_t;
+#endif
 
 typedef struct {
     /* Public parameters */
@@ -185,8 +190,13 @@
     LVM_INT16 VC_AVLFixedVolume;         /* AVL fixed volume */
 
     /* Treble Enhancement */
+#ifdef BIQUAD_OPT
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pTEBiquad; /* Biquad filter instance */
+#else
     LVM_TE_Data_t* pTE_Taps;   /* Treble boost Taps */
     LVM_TE_Coefs_t* pTE_State; /* State for the treble boost filter */
+#endif
     LVM_INT16 TE_Active;       /* Control flag */
 
     /* Headroom */
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index c94c469..acd594f 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -190,9 +190,13 @@
                 /*
                  * Apply the filter
                  */
+#ifdef BIQUAD_OPT
+                pInstance->pTEBiquad->process(pProcessed, pProcessed, NrFrames);
+#else
                 FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
                                                 pProcessed, pProcessed, (LVM_INT16)NrFrames,
                                                 (LVM_INT16)NrChannels);
+#endif
             }
             /*
              * Volume balance
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index bad9aef..a5952fb 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -21,6 +21,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVCS.h"
 #include "LVCS_Private.h"
 #include "LVCS_Equaliser.h"
@@ -56,14 +59,18 @@
 LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
     LVM_UINT16 Offset;
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
     LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
     LVCS_Data_t* pData;
     LVCS_Coefficient_t* pCoefficients;
     BQ_FLOAT_Coefs_t Coeffs;
+#endif
     const BiquadA012B12CoefsSP_t* pEqualiserCoefTable;
 
+#ifndef BIQUAD_OPT
     pData = (LVCS_Data_t*)pInstance->pData;
     pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
     /*
      * If the sample rate changes re-initialise the filters
      */
@@ -75,6 +82,13 @@
         Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
         pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
 
+#ifdef BIQUAD_OPT
+        std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                pEqualiserCoefTable[Offset].A0, pEqualiserCoefTable[Offset].A1,
+                pEqualiserCoefTable[Offset].A2, -(pEqualiserCoefTable[Offset].B1),
+                -(pEqualiserCoefTable[Offset].B2)};
+        pInstance->pEqBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
         /* Left and right filters */
         /* Convert incoming coefficients to the required format/ordering */
         Coeffs.A0 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A0;
@@ -103,6 +117,7 @@
                 pConfig->pBiquadCallBack = BQ_2I_D16F32C15_TRC_WRA_01;
                 break;
         }
+#endif
     }
 
     return (LVCS_SUCCESS);
@@ -129,19 +144,25 @@
 LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance, LVM_FLOAT* pInputOutput,
                                     LVM_UINT16 NumSamples) {
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
     LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
     LVCS_Coefficient_t* pCoefficients;
 
     pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
 
     /*
      * Check if the equaliser is required
      */
     if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0) {
         /* Apply filter to the left and right channels */
+#ifdef BIQUAD_OPT
+        pInstance->pEqBiquad->process(pInputOutput, pInputOutput, NumSamples);
+#else
         (pConfig->pBiquadCallBack)(
                 (Biquad_FLOAT_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
                 (LVM_FLOAT*)pInputOutput, (LVM_FLOAT*)pInputOutput, (LVM_INT16)NumSamples);
+#endif
     }
 
     return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
index 5c8f1ae..f23261f 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
@@ -123,6 +123,7 @@
     if (pInstance == LVM_NULL) {
         return;
     }
+#ifndef BIQUAD_OPT
     if (pInstance->pCoeff != LVM_NULL) {
         free(pInstance->pCoeff);
         pInstance->pCoeff = LVM_NULL;
@@ -131,6 +132,7 @@
         free(pInstance->pData);
         pInstance->pData = LVM_NULL;
     }
+#endif
     free(pInstance);
     *phInstance = LVM_NULL;
     return;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index f9c23b3..a150e90 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -33,6 +33,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVCS.h"                 /* Calling or Application layer definitions */
 #include "LVCS_StereoEnhancer.h"  /* Stereo enhancer module definitions */
 #include "LVCS_ReverbGenerator.h" /* Reverberation module definitions */
@@ -120,12 +123,24 @@
     LVM_INT16 bTimerDone;                 /* Timer completion flag */
     LVM_Timer_Params_t TimerParams;       /* Timer parameters */
     LVM_Timer_Instance_t TimerInstance;   /* Timer instance */
+#ifdef BIQUAD_OPT
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pEqBiquad; /* Biquad filter instance for Equaliser */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pRevBiquad; /* Biquad filter instance for Reverberation */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pSEMidBiquad; /* Biquad filter instance for Stereo enhancement mid */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pSESideBiquad; /* Biquad filter instance for Stereo enhancement side */
+#else
     void* pCoeff;                         /* pointer to buffer for equaliser filter coeffs */
     void* pData;                          /* pointer to buffer for equaliser filter states */
+#endif
     void* pScratch;                       /* Pointer to bundle scratch buffer */
 
 } LVCS_Instance_t;
 
+#ifndef BIQUAD_OPT
 /* Coefficient Structure */
 typedef struct {
     Biquad_FLOAT_Instance_t EqualiserBiquadInstance;
@@ -141,6 +156,7 @@
     Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
     Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
 } LVCS_Data_t;
+#endif
 
 void LVCS_TimerCallBack(void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam);
 
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index f6d2453..82a3a43 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -20,6 +20,9 @@
 /*  Includes                                                                        */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include <stdlib.h>
 #include "LVCS.h"
 #include "LVCS_Private.h"
@@ -62,11 +65,14 @@
     LVM_UINT16 Offset;
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
     LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
     LVCS_Data_t* pData;
     LVCS_Coefficient_t* pCoefficients;
     BQ_FLOAT_Coefs_t Coeffs;
+#endif
     const BiquadA012B12CoefsSP_t* pReverbCoefTable;
 
+#ifndef BIQUAD_OPT
     if (pInstance->pData == LVM_NULL) {
         pInstance->pData = pData = (LVCS_Data_t*)calloc(1, sizeof(*pData));
         if (pData == LVM_NULL) {
@@ -83,6 +89,7 @@
     } else {
         pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
     }
+#endif
 
     /*
      * Initialise the delay and filters if:
@@ -109,6 +116,14 @@
         Offset = (LVM_UINT16)pParams->SampleRate;
         pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
 
+#ifdef BIQUAD_OPT
+        std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                pReverbCoefTable[Offset].A0, pReverbCoefTable[Offset].A1,
+                pReverbCoefTable[Offset].A2, -(pReverbCoefTable[Offset].B1),
+                -(pReverbCoefTable[Offset].B2)};
+        pInstance->pRevBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
         /* Convert incoming coefficients to the required format/ordering */
         Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
         Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
@@ -133,6 +148,7 @@
                 pConfig->pBiquadCallBack = BQ_2I_D16F16C15_TRC_WRA_01;
                 break;
         }
+#endif
 
         /*
          * Setup the mixer
@@ -190,10 +206,14 @@
                                           LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
     LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
     LVCS_Coefficient_t* pCoefficients;
+#endif
     LVM_FLOAT* pScratch;
 
+#ifndef BIQUAD_OPT
     pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
     pScratch = (LVM_FLOAT*)pInstance->pScratch;
 
     /*
@@ -233,9 +253,13 @@
         /*
          * Filter the data
          */
+#ifdef BIQUAD_OPT
+        pInstance->pRevBiquad->process(pScratch, pScratch, NumSamples);
+#else
         (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
                                    (LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch,
                                    (LVM_INT16)NumSamples);
+#endif
 
         Mult3s_Float((LVM_FLOAT*)pScratch, pConfig->ReverbLevel, (LVM_FLOAT*)pScratch,
                      (LVM_INT16)(2 * NumSamples));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index ffa9c9b..0e488f5 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -21,6 +21,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVCS.h"
 #include "LVCS_Private.h"
 #include "LVCS_StereoEnhancer.h"
@@ -52,15 +55,19 @@
 LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
     LVM_UINT16 Offset;
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
     LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
     LVCS_Data_t* pData;
     LVCS_Coefficient_t* pCoefficient;
     FO_FLOAT_Coefs_t CoeffsMid;
     BQ_FLOAT_Coefs_t CoeffsSide;
+#endif
     const BiquadA012B12CoefsSP_t* pSESideCoefs;
 
+#ifndef BIQUAD_OPT
     pData = (LVCS_Data_t*)pInstance->pData;
     pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
 
     /*
      * If the sample rate or speaker type has changed update the filters
@@ -73,6 +80,13 @@
         /* Mid filter */
         Offset = (LVM_UINT16)pParams->SampleRate;
 
+#ifdef BIQUAD_OPT
+        std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                LVCS_SEMidCoefTable[Offset].A0, LVCS_SEMidCoefTable[Offset].A1, 0.0,
+                -(LVCS_SEMidCoefTable[Offset].B1), 0.0};
+        pInstance->pSEMidBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
         /* Convert incoming coefficients to the required format/ordering */
         CoeffsMid.A0 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A0;
         CoeffsMid.A1 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A1;
@@ -91,11 +105,18 @@
         if (LVCS_SEMidCoefTable[Offset].Scale == 15) {
             pConfig->pBiquadCallBack_Mid = FO_1I_D16F16C15_TRC_WRA_01;
         }
+#endif
 
         Offset = (LVM_UINT16)(pParams->SampleRate);
         pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
 
         /* Side filter */
+#ifdef BIQUAD_OPT
+        coefs = {pSESideCoefs[Offset].A0, pSESideCoefs[Offset].A1, pSESideCoefs[Offset].A2,
+                 -(pSESideCoefs[Offset].B1), -(pSESideCoefs[Offset].B2)};
+        pInstance->pSESideBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
         /* Convert incoming coefficients to the required format/ordering */
         CoeffsSide.A0 = (LVM_FLOAT)pSESideCoefs[Offset].A0;
         CoeffsSide.A1 = (LVM_FLOAT)pSESideCoefs[Offset].A1;
@@ -123,6 +144,7 @@
                 pConfig->pBiquadCallBack_Side = BQ_1I_D16F16C15_TRC_WRA_01;
                 break;
         }
+#endif
     }
 
     return (LVCS_SUCCESS);
@@ -169,9 +191,13 @@
                                          LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
     LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
+#ifndef BIQUAD_OPT
     LVCS_Coefficient_t* pCoefficient;
+#endif
     LVM_FLOAT* pScratch;
+#ifndef BIQUAD_OPT
     pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
     pScratch = (LVM_FLOAT*)pInstance->pScratch;
     /*
      * Check if the Stereo Enhancer is enabled
@@ -186,9 +212,13 @@
          * Apply filter to the middle signal
          */
         if (pInstance->OutputDevice == LVCS_HEADPHONE) {
+#ifdef BIQUAD_OPT
+            pInstance->pSEMidBiquad->process(pScratch, pScratch, NumSamples);
+#else
             (pConfig->pBiquadCallBack_Mid)(
                     (Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
                     (LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
+#endif
         } else {
             Mult3s_Float(pScratch,                    /* Source */
                          (LVM_FLOAT)pConfig->MidGain, /* Gain */
@@ -201,10 +231,15 @@
          * and in all modes for mobile speakers
          */
         if (pInstance->Params.SourceFormat == LVCS_STEREO) {
+#ifdef BIQUAD_OPT
+            pInstance->pSESideBiquad->process(pScratch + NumSamples, pScratch + NumSamples,
+                                              NumSamples);
+#else
             (pConfig->pBiquadCallBack_Side)(
                     (Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
                     (LVM_FLOAT*)(pScratch + NumSamples), (LVM_FLOAT*)(pScratch + NumSamples),
                     (LVM_INT16)NumSamples);
+#endif
         }
 
         /*