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 /****************************************************************************************/
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,const LVM_UINT16 NrFrames)61 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
62                                       const LVM_FLOAT       *pInData,
63                                       LVM_FLOAT             *pOutData,
64                                       const LVM_UINT16      NrFrames)
65 {                                     // updated to use samples = frames * channels.
66     LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
67 
68 #ifdef SUPPORT_MC
69     // Mono passed in as stereo
70     const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
71         ? 2 : pInstance->Params.NrChannels;
72 #else
73     const LVM_INT32 NrChannels = 2; // FCC_2
74 #endif
75     const LVM_INT32 NrSamples = NrChannels * NrFrames;
76 
77      /* Check for NULL pointers */
78     if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
79     {
80         return LVEQNB_NULLADDRESS;
81     }
82 
83     /* Check if the input and output data buffers are 32-bit aligned */
84     if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
85     {
86         return LVEQNB_ALIGNMENTERROR;
87     }
88 
89     LVM_FLOAT * const pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
90 
91     /*
92     * Check the number of frames is not too large
93     */
94     if (NrFrames > pInstance->Capabilities.MaxBlockSize)
95     {
96         return LVEQNB_TOOMANYSAMPLES;
97     }
98 
99     if (pInstance->Params.OperatingMode == LVEQNB_ON)
100     {
101         /*
102          * Copy input data in to scratch buffer
103          */
104         Copy_Float(pInData,     /* Source */
105                    pScratch,    /* Destination */
106                    (LVM_INT16)NrSamples);
107 
108         /*
109          * For each section execte the filter unless the gain is 0dB
110          */
111         if (pInstance->NBands != 0)
112         {
113             for (LVM_UINT16 i = 0; i < pInstance->NBands; i++)
114             {
115                 /*
116                  * Check if band is non-zero dB gain
117                  */
118                 if (pInstance->pBandDefinitions[i].Gain != 0)
119                 {
120                     /*
121                      * Get the address of the biquad instance
122                      */
123                     Biquad_FLOAT_Instance_t *pBiquad = &pInstance->pEQNB_FilterState_Float[i];
124 
125                     /*
126                      * Select single or double precision as required
127                      */
128                     switch (pInstance->pBiquadType[i])
129                     {
130                         case LVEQNB_SinglePrecision_Float:
131                         {
132 #ifdef SUPPORT_MC
133                             PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad,
134                                                           pScratch,
135                                                           pScratch,
136                                                           (LVM_INT16)NrFrames,
137                                                           (LVM_INT16)NrChannels);
138 #else
139                             PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
140                                                           pScratch,
141                                                           pScratch,
142                                                           (LVM_INT16)NrFrames);
143 #endif
144                             break;
145                         }
146                         default:
147                             break;
148                     }
149                 }
150             }
151         }
152 
153         if(pInstance->bInOperatingModeTransition == LVM_TRUE){
154 #ifdef SUPPORT_MC
155             LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->BypassMixer,
156                                        pScratch,
157                                        pInData,
158                                        pScratch,
159                                        (LVM_INT16)NrFrames,
160                                        (LVM_INT16)NrChannels);
161 #else
162             LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
163                                        pScratch,
164                                        pInData,
165                                        pScratch,
166                                        (LVM_INT16)NrSamples);
167 #endif
168             // duplicate with else clause(s)
169             Copy_Float(pScratch,                         /* Source */
170                        pOutData,                         /* Destination */
171                        (LVM_INT16)NrSamples);            /* All channel samples */
172         }
173         else{
174             Copy_Float(pScratch,              /* Source */
175                        pOutData,              /* Destination */
176                        (LVM_INT16)NrSamples); /* All channel samples */
177         }
178     }
179     else
180     {
181         /*
182          * Mode is OFF so copy the data if necessary
183          */
184         if (pInData != pOutData)
185         {
186             Copy_Float(pInData,                          /* Source */
187                        pOutData,                         /* Destination */
188                        (LVM_INT16)NrSamples);            /* All channel samples */
189         }
190     }
191     return LVEQNB_SUCCESS;
192 
193 }
194