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