LVCS_StereoEnhancer.c revision 09d5ca3766d4bab91cdaad7206716a5747ebad77
12c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*
22c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2004-2010 NXP Software
32c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2010 The Android Open Source Project
42c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
52c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
62c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * you may not use this file except in compliance with the License.
72c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * You may obtain a copy of the License at
82c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
92c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Unless required by applicable law or agreed to in writing, software
122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * See the License for the specific language governing permissions and
152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * limitations under the License.
162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */
172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************
192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2009d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent     $Author: nxp007753 $
2109d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent     $Revision: 1315 $
2209d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent     $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent*************************************************************************************/
252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Includes                                                                        */
292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS.h"
332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_Private.h"
342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_StereoEnhancer.h"
352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "VectorArithmetic.h"
362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_Tables.h"
372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_StereoEnhanceInit                                  */
412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Initialises the stereo enhancement module based on the sample rate.             */
442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The function selects the coefficients for the filters and clears the data       */
462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  history. It is also used for re-initialisation when one of the system control   */
472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  parameters changes but will only change the coefficients and clear the history  */
482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  if the sample rate or speaker type has changed.                                 */
492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance               Instance Handle                                         */
522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pParams                 Initialisation parameters                               */
532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_Success            Always succeeds                                         */
562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES:                                                                           */
582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
612c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        LVCS_Params_t       *pParams)
632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_UINT16              Offset;
662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Data_t             *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Coefficient_t      *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    FO_C16_Coefs_t          CoeffsMid;
712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    BQ_C16_Coefs_t          CoeffsSide;
722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    const BiquadA012B12CoefsSP_t *pSESideCoefs;
732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * If the sample rate or speaker type has changed update the filters
762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (pInstance->Params.SpeakerType != pParams->SpeakerType))
792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Set the filter coefficients based on the sample rate
822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Mid filter */
842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Offset = (LVM_UINT16)pParams->SampleRate;
852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Convert incoming coefficients to the required format/ordering */
872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsMid.A0 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A0;
882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsMid.A1 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A1;
892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsMid.B1 = (LVM_INT16)-LVCS_SEMidCoefTable[Offset].B1;
902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Clear the taps */
922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LoadConst_16(0,                                                                 /* Value */
9309d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent                     (void *)&pData->SEBiquadTapsMid,              /* Destination Cast to void:\
9409d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent                                                                      no dereferencing in function*/
952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                     (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid)/sizeof(LVM_UINT16)));  /* Number of words */
962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        &pData->SEBiquadTapsMid,
992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        &CoeffsMid);
1002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Callbacks */
1022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if(LVCS_SEMidCoefTable[Offset].Scale==15)
1032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
1042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            pConfig->pBiquadCallBack_Mid  = FO_1I_D16F16C15_TRC_WRA_01;
1052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Offset = (LVM_UINT16)(pParams->SampleRate);
1082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
1092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Side filter */
1112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Convert incoming coefficients to the required format/ordering */
1122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsSide.A0 = (LVM_INT16) pSESideCoefs[Offset].A0;
1132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsSide.A1 = (LVM_INT16) pSESideCoefs[Offset].A1;
1142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsSide.A2 = (LVM_INT16) pSESideCoefs[Offset].A2;
1152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsSide.B1 = (LVM_INT16)-pSESideCoefs[Offset].B1;
1162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        CoeffsSide.B2 = (LVM_INT16)-pSESideCoefs[Offset].B2;
1172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Clear the taps */
1192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LoadConst_16(0,                                                                 /* Value */
12009d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent                     (void *)&pData->SEBiquadTapsSide,             /* Destination Cast to void:\
12109d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent                                                                      no dereferencing in function*/
1222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                     (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide)/sizeof(LVM_UINT16))); /* Number of words */
1232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Callbacks */
1262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        switch(pSESideCoefs[Offset].Scale)
1272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
1282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            case 14:
1292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
1302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                                &pData->SEBiquadTapsSide,
1312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                                &CoeffsSide);
1322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F32C14_TRC_WRA_01;
1342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                break;
1352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            case 15:
1362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
1372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                                &pData->SEBiquadTapsSide,
1382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                                &CoeffsSide);
1392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F16C15_TRC_WRA_01;
1412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                break;
1422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVCS_SUCCESS);
1482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
1492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
1512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_StereoEnhance                                      */
1532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
1552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Enhance the stereo image in the input samples based on the following block      */
1562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  diagram:                                                                        */
1572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                               ________                                           */
1592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*          ________            |        |          ________                        */
1602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*         |        |  Middle   | Treble |         |        |                       */
1612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*         |        |---------->| Boost  |-------->|        |                       */
1622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*         | Stereo |           |________|         | M & S  |                       */
1632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*      -->|   to   |            ________          |   to   |-->                    */
1642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*         | M & S  |  Side     |        |         | Stereo |                       */
1652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*         |        |---------->| Side   |-------->|        |                       */
1662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*         |________|           | Boost  |         |________|                       */
1672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                              |________|                                          */
1682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  If the input signal is a mono signal there will be no side signal and hence     */
1712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  the side filter will not be run. In mobile speaker mode the middle filter is    */
1722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  not required and the Trebble boost filter is replaced by a simple gain block.   */
1732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
1762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance               Instance Handle                                         */
1772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pInData                 Pointer to the input data                               */
1782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pOutData                Pointer to the output data                              */
1792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  NumSamples              Number of samples to process                            */
1802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
1822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_Success            Always succeeds                                         */
1832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES:                                                                           */
1852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  1.  The side filter is not used in Mobile Speaker mode                          */
1862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
1882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1892c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
1902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                         const LVM_INT16        *pInData,
1912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                         LVM_INT16              *pOutData,
1922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                         LVM_UINT16             NumSamples)
1932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
1942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
1962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
1972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Coefficient_t      *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
1982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT16               *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
1992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
2012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Check if the Stereo Enhancer is enabled
2022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
2032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
2042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Convert from stereo to middle and side
2072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        From2iToMS_16x16(pInData,
2092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pScratch,
2102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pScratch+NumSamples,
2112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         (LVM_INT16)NumSamples);
2122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Apply filter to the middle signal
2152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if (pInstance->OutputDevice == LVCS_HEADPHONE)
2172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            (pConfig->pBiquadCallBack_Mid)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
2192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                           (LVM_INT16 *)pScratch,
2202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                           (LVM_INT16 *)pScratch,
2212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                           (LVM_INT16)NumSamples);
2222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        else
2242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            Mult3s_16x16(pScratch,              /* Source */
2262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         (LVM_INT16)pConfig->MidGain,      /* Gain */
2272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pScratch,              /* Destination */
2282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         (LVM_INT16)NumSamples);           /* Number of samples */
2292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Apply the filter the side signal only in stereo mode for headphones
2332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * and in all modes for mobile speakers
2342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if (pInstance->Params.SourceFormat == LVCS_STEREO)
2362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            (pConfig->pBiquadCallBack_Side)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
2382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                            (LVM_INT16 *)(pScratch + NumSamples),
2392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                            (LVM_INT16 *)(pScratch + NumSamples),
2402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                            (LVM_INT16)NumSamples);
2412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Convert from middle and side to stereo
2452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        MSTo2i_Sat_16x16(pScratch,
2472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pScratch+NumSamples,
2482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pOutData,
2492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         (LVM_INT16)NumSamples);
2502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    else
2532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * The stereo enhancer is disabled so just copy the data
2562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Copy_16((LVM_INT16 *)pInData,           /* Source */
2582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (LVM_INT16 *)pOutData,          /* Destination */
2592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (LVM_INT16)(2*NumSamples));     /* Left and right */
2602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVCS_SUCCESS);
2642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
2652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
269