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
60LVEQNB_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
101LVEQNB_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
140void    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
214void    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
292void    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
332LVEQNB_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/****************************************************************************************/
461LVM_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