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