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 "LVEQNB.h"
25 #include "LVEQNB_Private.h"
26 #include "VectorArithmetic.h"
27 #include "BIQUAD.h"
28 
29 /****************************************************************************************/
30 /*                                                                                      */
31 /*  Defines                                                                             */
32 /*                                                                                      */
33 /****************************************************************************************/
34 
35 #define     LOW_FREQ            298             /* 32768/110 for low test frequency */
36 #define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
37 
38 /****************************************************************************************/
39 /*                                                                                      */
40 /* FUNCTION:                 LVEQNB_GetParameters                                       */
41 /*                                                                                      */
42 /* DESCRIPTION:                                                                         */
43 /*  Request the N-Band equaliser parameters. The current parameter set is returned via  */
44 /*  the parameter pointer.                                                              */
45 /*                                                                                      */
46 /* PARAMETERS:                                                                          */
47 /*  hInstance                Instance handle                                            */
48 /*  pParams                  Pointer to an empty parameter structure                    */
49 /*                                                                                      */
50 /* RETURNS:                                                                             */
51 /*  LVEQNB_SUCCESS          Succeeds                                                    */
52 /*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
53 /*                                                                                      */
54 /* NOTES:                                                                               */
55 /*  1.  This function may be interrupted by the LVEQNB_Process function                 */
56 /*                                                                                      */
57 /****************************************************************************************/
58 
LVEQNB_GetParameters(LVEQNB_Handle_t hInstance,LVEQNB_Params_t * pParams)59 LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
60                                             LVEQNB_Params_t     *pParams)
61 {
62 
63     LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
64 
65    /*
66      * Check for error conditions
67      */
68     if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
69     {
70         return LVEQNB_NULLADDRESS;
71     }
72 
73     *pParams = pInstance->Params;
74 
75     return(LVEQNB_SUCCESS);
76 }
77 
78 /************************************************************************************/
79 /*                                                                                  */
80 /* FUNCTION:                 LVEQNB_GetCapabilities                                 */
81 /*                                                                                  */
82 /* DESCRIPTION:                                                                     */
83 /*  Get the N-Band equaliser capabilities. The current capabilities are returned    */
84 /*  via the pointer.                                                                */
85 /*                                                                                  */
86 /* PARAMETERS:                                                                      */
87 /*  hInstance                Instance handle                                        */
88 /*  pCapabilities            Pointer to an empty capability structure               */
89 /*                                                                                  */
90 /* RETURNS:                                                                         */
91 /*  LVEQNB_Success           Succeeds                                               */
92 /*  LVEQNB_NULLADDRESS       hInstance or pCapabilities is NULL                     */
93 /*                                                                                  */
94 /* NOTES:                                                                           */
95 /*  1.  This function may be interrupted by the LVEQNB_Process function             */
96 /*                                                                                  */
97 /************************************************************************************/
98 
LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance,LVEQNB_Capabilities_t * pCapabilities)99 LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
100                                               LVEQNB_Capabilities_t     *pCapabilities)
101 {
102 
103     LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
104 
105     if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
106     {
107         return LVEQNB_NULLADDRESS;
108     }
109 
110     *pCapabilities = pInstance->Capabilities;
111 
112     return(LVEQNB_SUCCESS);
113 }
114 
115 /************************************************************************************/
116 /*                                                                                  */
117 /* FUNCTION:            LVEQNB_SetFilters                                           */
118 /*                                                                                  */
119 /* DESCRIPTION:                                                                     */
120 /*  Sets the filter type based on the definition.                                   */
121 /*                                                                                  */
122 /* PARAMETERS:                                                                      */
123 /*  pInstance           Pointer to the instance                                     */
124 /*  pParams             Initialisation parameters                                   */
125 /*                                                                                  */
126 /* RETURNS:                                                                         */
127 /*  void                Nothing                                                     */
128 /*                                                                                  */
129 /* NOTES:                                                                           */
130 /*  1. To select the biquad type the follow rules are applied:                      */
131 /*          Double precision    if (fc <= fs/110)                                   */
132 /*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
133 /*          Single precision    otherwise                                           */
134 /*                                                                                  */
135 /************************************************************************************/
136 
LVEQNB_SetFilters(LVEQNB_Instance_t * pInstance,LVEQNB_Params_t * pParams)137 void    LVEQNB_SetFilters(LVEQNB_Instance_t     *pInstance,
138                           LVEQNB_Params_t       *pParams)
139 {
140     extern const LVM_UINT32   LVEQNB_SampleRateTab[];           /* Sample rate table */
141 
142     LVM_UINT16          i;                                      /* Filter band index */
143     LVM_UINT32          fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate];  /* Sample rate */
144     LVM_UINT32          fc;                                     /* Filter centre frequency */
145     LVM_INT16           QFactor;                                /* Filter Q factor */
146 
147     pInstance->NBands = pParams->NBands;
148 
149     for (i=0; i<pParams->NBands; i++)
150     {
151         /*
152          * Get the filter settings
153          */
154         fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency;     /* Get the band centre frequency */
155         QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor;   /* Get the band Q factor */
156 
157         pInstance->pBiquadType[i] = LVEQNB_SinglePrecision_Float; /* Default to single precision */
158 
159         /*
160          * Check for out of range frequencies
161          */
162         if (fc > (fs >> 1))
163         {
164             pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
165         }
166 
167         /*
168          * Copy the filter definition to persistant memory
169          */
170         pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
171 
172     }
173 }
174 
175 /************************************************************************************/
176 /*                                                                                  */
177 /* FUNCTION:            LVEQNB_SetCoefficients                                      */
178 /*                                                                                  */
179 /* DESCRIPTION:                                                                     */
180 /*  Sets the filter coefficients. This uses the type to select single or double     */
181 /*  precision coefficients.                                                         */
182 /*                                                                                  */
183 /* PARAMETERS:                                                                      */
184 /*  pInstance           Pointer to the instance                                     */
185 /*  pParams             Initialisation parameters                                   */
186 /*                                                                                  */
187 /************************************************************************************/
188 
LVEQNB_SetCoefficients(LVEQNB_Instance_t * pInstance)189 void    LVEQNB_SetCoefficients(LVEQNB_Instance_t     *pInstance)
190 {
191 
192     LVM_UINT16              i;                          /* Filter band index */
193     LVEQNB_BiquadType_en    BiquadType;                 /* Filter biquad type */
194 
195     /*
196      * Set the coefficients for each band by the init function
197      */
198     for (i=0; i<pInstance->Params.NBands; i++)
199     {
200 
201         /*
202          * Check band type for correct initialisation method and recalculate the coefficients
203          */
204         BiquadType = pInstance->pBiquadType[i];
205         switch  (BiquadType)
206         {
207             case    LVEQNB_SinglePrecision_Float:
208             {
209                 PK_FLOAT_Coefs_t      Coefficients;
210                 /*
211                  * Calculate the single precision coefficients
212                  */
213                 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
214                                        &pInstance->pBandDefinitions[i],
215                                        &Coefficients);
216                 /*
217                  * Set the coefficients
218                  */
219                 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
220                                                    &pInstance->pEQNB_Taps_Float[i],
221                                                    &Coefficients);
222                 break;
223             }
224             default:
225                 break;
226         }
227     }
228 
229 }
230 
231 /************************************************************************************/
232 /*                                                                                  */
233 /* FUNCTION:            LVEQNB_ClearFilterHistory                                   */
234 /*                                                                                  */
235 /* DESCRIPTION:                                                                     */
236 /*  Clears the filter data history                                                  */
237 /*                                                                                  */
238 /* PARAMETERS:                                                                      */
239 /*  pInstance           Pointer to the instance                                     */
240 /*                                                                                  */
241 /************************************************************************************/
LVEQNB_ClearFilterHistory(LVEQNB_Instance_t * pInstance)242 void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
243 {
244     LVM_FLOAT       *pTapAddress;
245     LVM_INT16       NumTaps;
246 
247     pTapAddress = (LVM_FLOAT *)pInstance->pEQNB_Taps_Float;
248     NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * \
249                                     sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) / sizeof(LVM_FLOAT));
250 
251     if (NumTaps != 0)
252     {
253         LoadConst_Float(0,                                 /* Clear the history, value 0 */
254                         pTapAddress,                       /* Destination */
255                         NumTaps);                          /* Number of words */
256     }
257 }
258 /****************************************************************************************/
259 /*                                                                                      */
260 /* FUNCTION:                LVEQNB_Control                                              */
261 /*                                                                                      */
262 /* DESCRIPTION:                                                                         */
263 /*  Sets or changes the LifeVibes module parameters.                                    */
264 /*                                                                                      */
265 /* PARAMETERS:                                                                          */
266 /*  hInstance               Instance handle                                             */
267 /*  pParams                 Pointer to a parameter structure                            */
268 /*                                                                                      */
269 /* RETURNS:                                                                             */
270 /*  LVEQNB_Success          Always succeeds                                             */
271 /*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
272 /*  LVEQNB_NULLADDRESS      NULL address for the equaliser filter definitions and the   */
273 /*                          number of bands is non-zero                                 */
274 /*                                                                                      */
275 /* NOTES:                                                                               */
276 /*  1.  This function may be interrupted by the LVEQNB_Process function                 */
277 /*                                                                                      */
278 /****************************************************************************************/
279 
LVEQNB_Control(LVEQNB_Handle_t hInstance,LVEQNB_Params_t * pParams)280 LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t        hInstance,
281                                       LVEQNB_Params_t        *pParams)
282 {
283 
284     LVEQNB_Instance_t    *pInstance = (LVEQNB_Instance_t  *)hInstance;
285     LVM_INT16            bChange    = LVM_FALSE;
286     LVM_INT16            i = 0;
287     LVEQNB_Mode_en       OperatingModeSave ;
288 
289     /*
290      * Check for error conditions
291      */
292     if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
293     {
294         return LVEQNB_NULLADDRESS;
295     }
296 
297     if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
298     {
299         return LVEQNB_NULLADDRESS;
300     }
301 
302     OperatingModeSave = pInstance->Params.OperatingMode;
303 
304     /* Set the alpha factor of the mixer */
305     if (pParams->SampleRate != pInstance->Params.SampleRate)
306     {
307         LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
308         LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
309     }
310 
311     if( (pInstance->Params.NBands            !=  pParams->NBands          ) ||
312         (pInstance->Params.OperatingMode     !=  pParams->OperatingMode   ) ||
313         (pInstance->Params.pBandDefinition   !=  pParams->pBandDefinition ) ||
314         (pInstance->Params.SampleRate        !=  pParams->SampleRate      ) ||
315         (pInstance->Params.SourceFormat      !=  pParams->SourceFormat    ))
316     {
317 
318         bChange = LVM_TRUE;
319     }
320     else
321     {
322         for(i = 0; i < pParams->NBands; i++)
323         {
324 
325             if((pInstance->pBandDefinitions[i].Frequency  != pParams->pBandDefinition[i].Frequency )||
326                 (pInstance->pBandDefinitions[i].Gain       != pParams->pBandDefinition[i].Gain      )||
327                 (pInstance->pBandDefinitions[i].QFactor    != pParams->pBandDefinition[i].QFactor   ))
328             {
329 
330                 bChange = LVM_TRUE;
331             }
332         }
333     }
334 
335     // During operating mode transition, there is a race condition where the mode
336     // is still LVEQNB_ON, but the effect is considered disabled in the upper layers.
337     // modeChange handles this special race condition.
338     const int /* bool */ modeChange = pParams->OperatingMode != OperatingModeSave
339             || (OperatingModeSave == LVEQNB_ON
340                     && pInstance->bInOperatingModeTransition
341                     && LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
342 
343     if (bChange || modeChange) {
344 
345         /*
346          * If the sample rate has changed clear the history
347          */
348         if (pInstance->Params.SampleRate != pParams->SampleRate)
349         {
350             LVEQNB_ClearFilterHistory(pInstance);           /* Clear the history */
351         }
352 
353         /*
354          * Update the instance parameters
355          */
356         pInstance->Params = *pParams;
357 
358         /*
359          * Reset the filters except if the algo is switched off
360          */
361         if(pParams->OperatingMode != LVEQNB_BYPASS){
362             /*
363              * Reset the filters as all parameters could have changed
364              */
365             LVEQNB_SetFilters(pInstance,                        /* Instance pointer */
366                               pParams);                         /* New parameters */
367 
368             /*
369              * Update the filters
370              */
371             LVEQNB_SetCoefficients(pInstance);                  /* Instance pointer */
372         }
373 
374         if (modeChange) {
375             if(pParams->OperatingMode == LVEQNB_ON)
376             {
377                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 1.0f);
378                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 0.0f);
379                 pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
380                 pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
381             }
382             else
383             {
384                 /* Stay on the ON operating mode until the transition is done */
385                 // This may introduce a state race condition if the effect is enabled again
386                 // while in transition.  This is fixed in the modeChange logic.
387                 pInstance->Params.OperatingMode = LVEQNB_ON;
388                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 0.0f);
389                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 1.0f);
390                 pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
391                 pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
392             }
393             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
394             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
395             pInstance->bInOperatingModeTransition = LVM_TRUE;
396         }
397 
398     }
399     return(LVEQNB_SUCCESS);
400 }
401 
402 /****************************************************************************************/
403 /*                                                                                      */
404 /* FUNCTION:                LVEQNB_BypassMixerCallBack                                  */
405 /*                                                                                      */
406 /* DESCRIPTION:                                                                         */
407 /*  CallBack function of the mixer                                                      */
408 /*  transition                                                                          */
409 /*                                                                                      */
410 /****************************************************************************************/
LVEQNB_BypassMixerCallBack(void * hInstance,void * pGeneralPurpose,LVM_INT16 CallbackParam)411 LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
412                                       void *pGeneralPurpose,
413                                       LVM_INT16 CallbackParam)
414 {
415     LVEQNB_Instance_t      *pInstance =(LVEQNB_Instance_t  *)hInstance;
416     LVM_Callback            CallBack  = pInstance->Capabilities.CallBack;
417 
418     (void) pGeneralPurpose;
419 
420      /*
421       * Send an ALGOFF event if the ON->OFF switch transition is finished
422       */
423     if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0) &&
424        (CallbackParam == 0)){
425         pInstance->Params.OperatingMode = LVEQNB_BYPASS;
426         if (CallBack != LVM_NULL){
427             CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
428         }
429     }
430 
431     /*
432      *  Exit transition state
433      */
434     pInstance->bInOperatingModeTransition = LVM_FALSE;
435 
436     return 1;
437 }
438