1/*
2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/************************************************************************************/
19/*                                                                                  */
20/*  Includes                                                                        */
21/*                                                                                  */
22/************************************************************************************/
23
24#include "LVCS.h"
25#include "LVCS_Private.h"
26#include "LVCS_Tables.h"
27
28/************************************************************************************/
29/*                                                                                  */
30/* FUNCTION:                 LVCS_GetParameters                                     */
31/*                                                                                  */
32/* DESCRIPTION:                                                                     */
33/*  Request the Concert Sound parameters. The current parameter set is returned     */
34/*  via the parameter pointer.                                                      */
35/*                                                                                  */
36/* PARAMETERS:                                                                      */
37/*  hInstance                Instance handle                                        */
38/*  pParams                  Pointer to an empty parameter structure                */
39/*                                                                                  */
40/* RETURNS:                                                                         */
41/*  LVCS_Success             Always succeeds                                        */
42/*                                                                                  */
43/* NOTES:                                                                           */
44/*  1.  This function may be interrupted by the LVCS_Process function               */
45/*                                                                                  */
46/************************************************************************************/
47
48LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t   hInstance,
49                                        LVCS_Params_t   *pParams)
50{
51
52    LVCS_Instance_t     *pInstance =(LVCS_Instance_t  *)hInstance;
53
54    *pParams = pInstance->Params;
55
56    return(LVCS_SUCCESS);
57}
58
59
60/************************************************************************************/
61/*                                                                                  */
62/* FUNCTION:                LVCS_Control                                            */
63/*                                                                                  */
64/* DESCRIPTION:                                                                     */
65/*  Sets or changes the Concert Sound parameters.                                   */
66/*                                                                                  */
67/* PARAMETERS:                                                                      */
68/*  hInstance               Instance handle                                         */
69/*  pParams                 Pointer to a parameter structure                        */
70/*                                                                                  */
71/* RETURNS:                                                                         */
72/*  LVCS_Success            Succeeded                                               */
73/*                                                                                  */
74/* NOTES:                                                                           */
75/*  1.  This function must not be interrupted by the LVCS_Process function          */
76/*                                                                                  */
77/************************************************************************************/
78
79LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t      hInstance,
80                                  LVCS_Params_t      *pParams)
81{
82    LVM_INT16                   Offset;
83    LVCS_Instance_t             *pInstance =(LVCS_Instance_t  *)hInstance;
84    LVCS_ReturnStatus_en        err;
85    LVCS_Modes_en               OperatingModeSave = pInstance->Params.OperatingMode;
86
87    if (pParams->SampleRate != pInstance->Params.SampleRate)
88    {
89        pInstance->TimerParams.SamplingRate = LVCS_SampleRateTable[pParams->SampleRate];
90    }
91
92    /*
93     * If the reverb level has changed
94     */
95    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
96    {
97        err=LVCS_ReverbGeneratorInit(hInstance,pParams);
98    }
99
100    /*
101     * If the sample rate or speaker has changed then perform a full re-initialisation
102     */
103    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
104       (pInstance->Params.SpeakerType != pParams->SpeakerType))
105    {
106        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
107
108        /*
109         * Output device
110         */
111        pInstance->OutputDevice = LVCS_HEADPHONE;
112
113        /*
114         * Get the volume correction parameters
115         */
116        /* Use internal coefficient table */
117        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
118        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
119
120        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
121
122        pInstance->CompressGain = pInstance->VolCorrect.CompMin;
123
124        LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
125
126
127        {
128            LVM_UINT32          Gain;
129            const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
130            Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * LVM_MAXINT_16);
131            Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
132            Gain=Gain>>15;
133            /*
134             * Apply the gain correction and shift, note the result is in Q3.13 format
135             */
136            Gain = (Gain * pInstance->VolCorrect.GainMin) >>12;
137
138            LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,Gain);
139            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
140                    LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
141            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
142                    LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
143
144        }
145
146
147        err=LVCS_SEnhancerInit(hInstance,
148                           pParams);
149
150        err=LVCS_ReverbGeneratorInit(hInstance,
151                                 pParams);
152
153        err=LVCS_EqualiserInit(hInstance,
154                           pParams);
155
156        err=LVCS_BypassMixInit(hInstance,
157                           pParams);
158
159    }
160
161
162    /*
163     * Check if the effect level or source format has changed
164     */
165    else if ((pInstance->Params.EffectLevel != pParams->EffectLevel) ||
166            (pInstance->Params.SourceFormat != pParams->SourceFormat))
167    {
168        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
169
170        /*
171         * Get the volume correction parameters
172         */
173        /* Use internal coefficient table */
174        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
175        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
176
177        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
178
179        /* Update the effect level and alpha-mixer gains */
180        err=LVCS_BypassMixInit(hInstance,
181                           pParams);
182
183        if(err != LVCS_SUCCESS)
184        {
185            return err;
186        }
187    }
188    else
189    {
190        pInstance->Params = *pParams;
191    }
192
193    /*
194     * Update the instance parameters
195     */
196    pInstance->Params = *pParams;
197
198    /* Stay on the current operating mode until the transition is done */
199    if((pParams->OperatingMode != OperatingModeSave) ||
200       (pInstance->bInOperatingModeTransition == LVM_TRUE)){
201
202        /* Set the reverb delay timeout */
203        if(pInstance->bInOperatingModeTransition != LVM_TRUE){
204            pInstance->bTimerDone = LVM_FALSE;
205            pInstance->TimerParams.TimeInMs =
206            (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)
207            /pInstance->TimerParams.SamplingRate) + 1);
208            LVM_Timer_Init ( &pInstance->TimerInstance,
209                             &pInstance->TimerParams);
210        }
211
212        /* Update the effect level and alpha-mixer gains */
213        err=LVCS_BypassMixInit(hInstance,
214                           pParams);
215
216        /* Change transition bypass mixer settings if needed depending on transition type */
217        if(pParams->OperatingMode != LVCS_OFF){
218            pInstance->MSTarget0=LVM_MAXINT_16;
219            pInstance->MSTarget1=0;
220        }
221        else
222        {
223            pInstance->Params.OperatingMode = OperatingModeSave;
224            pInstance->MSTarget1=LVM_MAXINT_16;
225            pInstance->MSTarget0=0;
226        }
227
228
229        /* Set transition flag */
230        pInstance->bInOperatingModeTransition = LVM_TRUE;
231    }
232
233    return(LVCS_SUCCESS);
234}
235
236/****************************************************************************************/
237/*                                                                                      */
238/* FUNCTION:                LVCS_TimerCallBack                                          */
239/*                                                                                      */
240/* DESCRIPTION:                                                                         */
241/*  CallBack function of the Timer.                                                     */
242/*                                                                                      */
243/****************************************************************************************/
244void LVCS_TimerCallBack (void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam)
245{
246    LVCS_Instance_t     *pInstance  = (LVCS_Instance_t  *)hInstance;
247
248    /* Avoid warnings because pCallBackParams and CallbackParam are not used*/
249    if((pCallBackParams != LVM_NULL) || (CallbackParam != 0)){
250        pCallBackParams = hInstance;
251        CallbackParam = 0;
252        return;
253    }
254
255    pInstance->bTimerDone = LVM_TRUE;
256
257
258    return;
259}
260
261