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
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 * pOutData,LVM_UINT16 NumSamples)61 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
62 const LVM_INT16 *pInData,
63 LVM_INT16 *pOutData,
64 LVM_UINT16 NumSamples)
65 {
66
67 LVM_UINT16 i;
68 Biquad_Instance_t *pBiquad;
69 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
70 LVM_INT32 *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_INT32 *)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 * Convert from 16-bit to 32-bit
99 */
100 Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */
101 pScratch, /* Destination */
102 (LVM_INT16)(2*NumSamples), /* Left and Right */
103 SHIFT); /* Scaling shift */
104
105 /*
106 * For each section execte the filter unless the gain is 0dB
107 */
108 if (pInstance->NBands != 0)
109 {
110 for (i=0; i<pInstance->NBands; i++)
111 {
112 /*
113 * Check if band is non-zero dB gain
114 */
115 if (pInstance->pBandDefinitions[i].Gain != 0)
116 {
117 /*
118 * Get the address of the biquad instance
119 */
120 pBiquad = &pInstance->pEQNB_FilterState[i];
121
122
123 /*
124 * Select single or double precision as required
125 */
126 switch (pInstance->pBiquadType[i])
127 {
128 case LVEQNB_SinglePrecision:
129 {
130 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
131 (LVM_INT32 *)pScratch,
132 (LVM_INT32 *)pScratch,
133 (LVM_INT16)NumSamples);
134 break;
135 }
136
137 case LVEQNB_DoublePrecision:
138 {
139 PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
140 (LVM_INT32 *)pScratch,
141 (LVM_INT32 *)pScratch,
142 (LVM_INT16)NumSamples);
143 break;
144 }
145 default:
146 break;
147 }
148 }
149 }
150 }
151
152
153 if(pInstance->bInOperatingModeTransition == LVM_TRUE){
154 /*
155 * Convert from 32-bit to 16- bit and saturate
156 */
157 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
158 (LVM_INT16 *)pScratch, /* Destination */
159 (LVM_INT16)(2*NumSamples), /* Left and Right */
160 SHIFT); /* Scaling shift */
161
162 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
163 (LVM_INT16 *)pScratch,
164 (LVM_INT16 *)pInData,
165 (LVM_INT16 *)pScratch,
166 (LVM_INT16)(2*NumSamples));
167
168 Copy_16((LVM_INT16*)pScratch, /* Source */
169 pOutData, /* Destination */
170 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
171 }
172 else{
173
174 /*
175 * Convert from 32-bit to 16- bit and saturate
176 */
177 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
178 pOutData, /* Destination */
179 (LVM_INT16 )(2*NumSamples), /* Left and Right */
180 SHIFT); /* Scaling shift */
181 }
182 }
183 else
184 {
185 /*
186 * Mode is OFF so copy the data if necessary
187 */
188 if (pInData != pOutData)
189 {
190 Copy_16(pInData, /* Source */
191 pOutData, /* Destination */
192 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
193 }
194 }
195
196
197
198 return(LVEQNB_SUCCESS);
199
200 }
201