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