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