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 SHIFT       13
37
38/****************************************************************************************/
39/*                                                                                      */
40/* FUNCTION:                LVEQNB_Process                                              */
41/*                                                                                      */
42/* DESCRIPTION:                                                                         */
43/*  Process function for the N-Band Equaliser module.                                   */
44/*                                                                                      */
45/* PARAMETERS:                                                                          */
46/*  hInstance               Instance handle                                             */
47/*  pInData                 Pointer to the input data                                   */
48/*  pOutData                Pointer to the output data                                  */
49/*  NumSamples              Number of samples in the input buffer                       */
50/*                                                                                      */
51/* RETURNS:                                                                             */
52/*  LVEQNB_SUCCESS          Succeeded                                                   */
53/*  LVEQNB_NULLADDRESS      When hInstance, pInData or pOutData are NULL                */
54/*  LVEQNB_ALIGNMENTERROR   When pInData or pOutData are not 32-bit aligned             */
55/*  LVEQNB_TOOMANYSAMPLES   NumSamples was larger than the maximum block size           */
56/*                                                                                      */
57/* NOTES:                                                                               */
58/*                                                                                      */
59/****************************************************************************************/
60#ifdef BUILD_FLOAT
61LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
62                                      const LVM_FLOAT       *pInData,
63                                      LVM_FLOAT             *pOutData,
64                                      LVM_UINT16            NumSamples)
65{
66
67    LVM_UINT16          i;
68    Biquad_FLOAT_Instance_t   *pBiquad;
69    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
70    LVM_FLOAT           *pScratch;
71
72
73     /* Check for NULL pointers */
74    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
75    {
76        return LVEQNB_NULLADDRESS;
77    }
78
79    /* Check if the input and output data buffers are 32-bit aligned */
80    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
81    {
82        return LVEQNB_ALIGNMENTERROR;
83    }
84
85    pScratch  = (LVM_FLOAT *)pInstance->pFastTemporary;
86
87    /*
88    * Check the number of samples is not too large
89    */
90    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
91    {
92        return(LVEQNB_TOOMANYSAMPLES);
93    }
94
95    if (pInstance->Params.OperatingMode == LVEQNB_ON)
96    {
97        /*
98         * Copy input data in to scratch buffer
99         */
100
101        Copy_Float((LVM_FLOAT *)pInData,      /* Source */
102                   pScratch,                  /* Destination */
103                   (LVM_INT16)(2 * NumSamples)); /* Left and Right */
104        /*
105         * For each section execte the filter unless the gain is 0dB
106         */
107        if (pInstance->NBands != 0)
108        {
109            for (i = 0; i < pInstance->NBands; i++)
110            {
111                /*
112                 * Check if band is non-zero dB gain
113                 */
114                if (pInstance->pBandDefinitions[i].Gain != 0)
115                {
116                    /*
117                     * Get the address of the biquad instance
118                     */
119                    pBiquad = &pInstance->pEQNB_FilterState_Float[i];
120
121
122                    /*
123                     * Select single or double precision as required
124                     */
125                    switch (pInstance->pBiquadType[i])
126                    {
127                        case LVEQNB_SinglePrecision_Float:
128                        {
129                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
130                                                          (LVM_FLOAT *)pScratch,
131                                                          (LVM_FLOAT *)pScratch,
132                                                          (LVM_INT16)NumSamples);
133                            break;
134                        }
135                        default:
136                            break;
137                    }
138                }
139            }
140        }
141
142
143        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
144            LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
145                                       (LVM_FLOAT *)pScratch,
146                                       (LVM_FLOAT *)pInData,
147                                       (LVM_FLOAT *)pScratch,
148                                       (LVM_INT16)(2 * NumSamples));
149            Copy_Float((LVM_FLOAT*)pScratch,                           /* Source */
150                       pOutData,                                       /* Destination */
151                       (LVM_INT16)(2 * NumSamples));                     /* Left and Right samples */
152        }
153        else{
154            Copy_Float(pScratch,              /* Source */
155                       pOutData,              /* Destination */
156                       (LVM_INT16 )(2 * NumSamples)); /* Left and Right */
157        }
158    }
159    else
160    {
161        /*
162         * Mode is OFF so copy the data if necessary
163         */
164        if (pInData != pOutData)
165        {
166            Copy_Float(pInData,                                    /* Source */
167                       pOutData,                                   /* Destination */
168                       (LVM_INT16)(2 * NumSamples));                 /* Left and Right samples */
169        }
170    }
171    return(LVEQNB_SUCCESS);
172
173}
174#else
175LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
176                                      const LVM_INT16       *pInData,
177                                      LVM_INT16             *pOutData,
178                                      LVM_UINT16            NumSamples)
179{
180
181    LVM_UINT16          i;
182    Biquad_Instance_t   *pBiquad;
183    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
184    LVM_INT32           *pScratch;
185
186
187     /* Check for NULL pointers */
188    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
189    {
190        return LVEQNB_NULLADDRESS;
191    }
192
193    /* Check if the input and output data buffers are 32-bit aligned */
194    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
195    {
196        return LVEQNB_ALIGNMENTERROR;
197    }
198
199    pScratch  = (LVM_INT32 *)pInstance->pFastTemporary;
200
201    /*
202    * Check the number of samples is not too large
203    */
204    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
205    {
206        return(LVEQNB_TOOMANYSAMPLES);
207    }
208
209    if (pInstance->Params.OperatingMode == LVEQNB_ON)
210    {
211        /*
212         * Convert from 16-bit to 32-bit
213         */
214        Int16LShiftToInt32_16x32((LVM_INT16 *)pInData,      /* Source */
215                                 pScratch,                  /* Destination */
216                                 (LVM_INT16)(2*NumSamples), /* Left and Right */
217                                 SHIFT);                    /* Scaling shift */
218
219        /*
220         * For each section execte the filter unless the gain is 0dB
221         */
222        if (pInstance->NBands != 0)
223        {
224            for (i=0; i<pInstance->NBands; i++)
225            {
226                /*
227                 * Check if band is non-zero dB gain
228                 */
229                if (pInstance->pBandDefinitions[i].Gain != 0)
230                {
231                    /*
232                     * Get the address of the biquad instance
233                     */
234                    pBiquad = &pInstance->pEQNB_FilterState[i];
235
236
237                    /*
238                     * Select single or double precision as required
239                     */
240                    switch (pInstance->pBiquadType[i])
241                    {
242                        case LVEQNB_SinglePrecision:
243                        {
244                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
245                                                          (LVM_INT32 *)pScratch,
246                                                          (LVM_INT32 *)pScratch,
247                                                          (LVM_INT16)NumSamples);
248                            break;
249                        }
250
251                        case LVEQNB_DoublePrecision:
252                        {
253                            PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
254                                                          (LVM_INT32 *)pScratch,
255                                                          (LVM_INT32 *)pScratch,
256                                                          (LVM_INT16)NumSamples);
257                            break;
258                        }
259                        default:
260                            break;
261                    }
262                }
263            }
264        }
265
266
267        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
268                /*
269                 * Convert from 32-bit to 16- bit and saturate
270                 */
271                Int32RShiftToInt16_Sat_32x16(pScratch,                      /* Source */
272                                             (LVM_INT16 *)pScratch,         /* Destination */
273                                             (LVM_INT16)(2*NumSamples),     /* Left and Right */
274                                             SHIFT);                        /* Scaling shift */
275
276                LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
277                                                (LVM_INT16 *)pScratch,
278                                                (LVM_INT16 *)pInData,
279                                                (LVM_INT16 *)pScratch,
280                                                (LVM_INT16)(2*NumSamples));
281
282                Copy_16((LVM_INT16*)pScratch,                           /* Source */
283                        pOutData,                                       /* Destination */
284                        (LVM_INT16)(2*NumSamples));                     /* Left and Right samples */
285        }
286        else{
287
288            /*
289             * Convert from 32-bit to 16- bit and saturate
290             */
291            Int32RShiftToInt16_Sat_32x16(pScratch,              /* Source */
292                                         pOutData,              /* Destination */
293                                         (LVM_INT16 )(2*NumSamples), /* Left and Right */
294                                         SHIFT);                /* Scaling shift */
295        }
296    }
297    else
298    {
299        /*
300         * Mode is OFF so copy the data if necessary
301         */
302        if (pInData != pOutData)
303        {
304            Copy_16(pInData,                                    /* Source */
305                    pOutData,                                   /* Destination */
306                    (LVM_INT16)(2*NumSamples));                 /* Left and Right samples */
307        }
308    }
309
310
311
312    return(LVEQNB_SUCCESS);
313
314}
315#endif