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/*                                                                                  */
202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Includes                                                                        */
212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS.h"
252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_Private.h"
262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_BypassMix.h"
272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "VectorArithmetic.h"
282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_Tables.h"
292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/
312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                      */
322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Function Prototypes                                                                 */
332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                      */
342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/
352c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVM_INT32 LVCS_MixerCallback(   LVCS_Handle_t   hInstance,
362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                void            *pGeneralPurpose,
372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                LVM_INT16       CallbackParam);
382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_BypassMixInit                                      */
422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Initialises the bypass mixer module                                             */
452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The overall gain of the processed path is set by the gains in the individual    */
472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  processing blocks and by the effect level gain.                                 */
482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The unprocessed path must have matching gain for the processed path to ensure   */
502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  as they are mixed together the correct effect is achieved, this is the value    */
512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  UnprocLoss.                                                                     */
522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The overall gain is corrected by a combination of a shift with saturation and a */
542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  linear scaler, loss. The loss ensures the sum in the mixer does not saturate    */
552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  and also corrects for any excess gain in the shift.                             */
562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance               Instance Handle                                         */
592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pParams                 Initialisation parameters                               */
602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_Success            Always succeeds                                         */
632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES:                                                                           */
652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
682c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        LVCS_Params_t       *pParams)
702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_UINT16          Offset;
732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_UINT32          Gain;
742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_BypassMix_t    *pConfig   = (LVCS_BypassMix_t *)&pInstance->BypassMix;
762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    const Gain_t        *pOutputGainTable;
772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT32           Current;
782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Set the transition gain
822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if ((pParams->OperatingMode == LVCS_ON) &&
842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (pInstance->bTimerDone == LVM_TRUE)
8509d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent        && (pInstance->MSTarget1 != 0x7FFF) /* this indicates an off->on transtion */
862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        )
872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInstance->TransitionGain = pParams->EffectLevel;
892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    else
912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Select no effect level */
932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInstance->TransitionGain = 0;
942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Calculate the output gain table offset
982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Offset = (LVM_UINT16)(pParams->SpeakerType + (pParams->SourceFormat*(1+LVCS_EX_HEADPHONES)));
1002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
1012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Setup the mixer gain for the processed path
1042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
1062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[0].CallbackParam = 0;
1082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[0].pCallbackHandle = LVM_NULL;
1092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[0].pCallBack = LVM_NULL;
1102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[0].CallbackSet=1;
1112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
1122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0],(LVM_INT32)(Gain >> 15),Current);
1132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
1142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Setup the mixer gain for the unprocessed path
1162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * (0x7FFF - pInstance->TransitionGain));
1182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
1192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
1202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1],(LVM_INT32)(Gain >> 15),Current);
1212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
1222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[1].CallbackParam = 0;
1232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[1].pCallbackHandle = hInstance;
1242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[1].CallbackSet=1;
1252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Mixer_Instance.MixerStream[1].pCallBack = LVCS_MixerCallback;
1262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Setup the output gain shift
1292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pConfig->Output_Shift = pOutputGainTable[Offset].Shift;
1312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Correct gain for the effect level
1352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVM_INT16           GainCorrect;
1392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVM_INT32           Gain1;
1402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVM_INT32           Gain2;
1412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
1432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
1442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
1452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Calculate the gain correction
1462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
1472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if (pInstance->Params.CompressorMode == LVM_MODE_ON)
1482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
1492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        GainCorrect = (LVM_INT16)(  pInstance->VolCorrect.GainMin
1502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                    - (((LVM_INT32)pInstance->VolCorrect.GainMin * (LVM_INT32)pInstance->TransitionGain) >> 15)
1512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                    + (((LVM_INT32)pInstance->VolCorrect.GainFull * (LVM_INT32)pInstance->TransitionGain) >> 15) );
1522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
1542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Apply the gain correction and shift, note the result is in Q3.13 format
1552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
1562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Gain1 = (Gain1 * GainCorrect) << 4;
1572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Gain2 = (Gain2 * GainCorrect) << 4;
1582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        else
1602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
1612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            Gain1 = Gain1 << 16;
1622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            Gain2 = Gain2 << 16;
1632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
1682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Set the gain values
1692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
1702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pConfig->Output_Shift = pConfig->Output_Shift;
1712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1>>16);
1722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
1732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2>>16);
1742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
1752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVCS_SUCCESS);
1782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
1802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
1822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_BypassMixer                                        */
1842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
1862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Apply Bypass Mix.                                                               */
1872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  This mixes the processed and unprocessed data streams together to correct the   */
1892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  overall system gain and allow progressive control of the Concert Sound effect.  */
1902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  When the bypass mixer is enabled the output is the processed signal only and    */
1922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  without gain correction.                                                        */
1932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
1952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance               Instance Handle                                         */
1962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pProcessed              Pointer to the processed data                           */
1972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pUnprocessed            Pointer to the unprocessed data                         */
1982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pOutData                Pointer to the output data                              */
1992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  NumSamples              Number of samples to process                            */
2002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
2022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_Success            Always succeeds                                         */
2032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES:                                                                           */
2052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
2072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2082c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
2092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                      const LVM_INT16       *pProcessed,
2102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                      const LVM_INT16       *pUnprocessed,
2112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                      LVM_INT16             *pOutData,
2122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                      LVM_UINT16            NumSamples)
2132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
2142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t     *pInstance      = (LVCS_Instance_t  *)hInstance;
2162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_BypassMix_t    *pConfig        = (LVCS_BypassMix_t *)&pInstance->BypassMix;
2172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
2192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Check if the bypass mixer is enabled
2202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
2212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if ((pInstance->Params.OperatingMode & LVCS_BYPASSMIXSWITCH) != 0)
2222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Apply the bypass mix
2252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
2272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        pProcessed,
2282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        (LVM_INT16 *) pUnprocessed,
2292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        pOutData,
2302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                        (LVM_INT16)(2*NumSamples));
2312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
2332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Apply output gain correction shift
2342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
2352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Shift_Sat_v16xv16 ((LVM_INT16)pConfig->Output_Shift,
2362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                          (LVM_INT16*)pOutData,
2372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                          (LVM_INT16*)pOutData,
2382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                          (LVM_INT16)(2*NumSamples));          /* Left and right*/
2392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVCS_SUCCESS);
2422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
2432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
2462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_MixerCallback                                      */
2482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
2502c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVM_INT32 LVCS_MixerCallback(LVCS_Handle_t      hInstance,
2512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                            void                *pGeneralPurpose,
2522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                            LVM_INT16           CallbackParam)
2532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
2542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
2552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
25609d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent   (void)pGeneralPurpose;
2572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
2592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Off transition has completed in Headphone mode
2602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
2612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if ((pInstance->OutputDevice == LVCS_HEADPHONE) &&
2622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (pInstance->bInOperatingModeTransition)     &&
26309d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent        (pInstance->MSTarget0 == 0x0000)&&  /* this indicates an on->off transition */
2642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (CallbackParam == 0))
2652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Set operating mode to OFF */
2672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInstance->Params.OperatingMode = LVCS_OFF;
2682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Exit transition state */
2702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInstance->bInOperatingModeTransition = LVM_FALSE;
2712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Signal to the bundle */
2732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if((*pInstance->Capabilities.CallBack) != LVM_NULL){
2742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            (*pInstance->Capabilities.CallBack)(pInstance->Capabilities.pBundleInstance,
2752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                                LVM_NULL,
2762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                                (ALGORITHM_CS_ID | LVCS_EVENT_ALGOFF));
2772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if ((pInstance->OutputDevice == LVCS_HEADPHONE)  &&
28209d5ca3766d4bab91cdaad7206716a5747ebad77Eric Laurent        (pInstance->MSTarget0 == 1) &&
2832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (pInstance->bTimerDone == LVM_TRUE)){
2842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Exit transition state */
2862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInstance->bInOperatingModeTransition = LVM_FALSE;
2872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return 1;
2902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
2912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
294