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 "LVDBE.h"
25 #include "LVDBE_Private.h"
26 #include "VectorArithmetic.h"
27 #include "AGC.h"
28 #include "LVDBE_Coeffs.h" /* Filter coefficients */
29
30 /********************************************************************************************/
31 /* */
32 /* FUNCTION: LVDBE_Process */
33 /* */
34 /* DESCRIPTION: */
35 /* Process function for the Bass Enhancement module. */
36 /* */
37 /* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */
38 /* format is not supported, the calling routine must convert the mono stream to */
39 /* mono-in-stereo. */
40 /* ___________ */
41 /* ________ | | ________ */
42 /* | | _____ |------------------------->| | | | */
43 /* | 16-bit | | | | ________ | | | 32-bit | */
44 /* -+-->| to |-->| HPF |--| | | _____ | AGC Mixer |-->| to |--| */
45 /* | | 32-bit | |_____| | | Stereo | | | | | | 16-bit | | */
46 /* | |________| |-->| to |-->| BPF |-->| | |________| 0 */
47 /* | | Mono | |_____| |___________| \--> */
48 /* | |________| */
49 /* | _________ 0 */
50 /* | | | | */
51 /* |----------------------------------------------------| Volume |-----------------| */
52 /* | Control | */
53 /* |_________| */
54 /* */
55 /* PARAMETERS: */
56 /* hInstance Instance handle */
57 /* pInData Pointer to the input data */
58 /* pOutData Pointer to the output data */
59 /* NumSamples Number of samples in the input buffer */
60 /* */
61 /* RETURNS: */
62 /* LVDBE_SUCCESS Succeeded */
63 /* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
64 /* */
65 /* NOTES: */
66 /* 1. The input and output data must be 32-bit format. The input is scaled by a shift */
67 /* when converting from 16-bit format, this scaling allows for internal headroom in the */
68 /* bass enhancement algorithm. */
69 /* 2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with */
70 /* the headroom loss. This headroom loss is compensated in the volume control so the */
71 /* overall end to end gain is odB. */
72 /* */
73 /********************************************************************************************/
74 #ifndef BUILD_FLOAT
LVDBE_Process(LVDBE_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 * pOutData,LVM_UINT16 NumSamples)75 LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
76 const LVM_INT16 *pInData, LVM_INT16 *pOutData, LVM_UINT16 NumSamples) {
77
78 LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *) hInstance;
79 LVM_INT32 *pScratch =
80 (LVM_INT32 *) pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
81 LVM_INT32 *pMono;
82 LVM_INT16 *pInput = (LVM_INT16 *) pInData;
83
84 /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
85 LVM_INT16 *pScratchVol = (LVM_INT16 *) (&pScratch[NumSamples]);
86
87 /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
88 pMono = &pScratch[2 * NumSamples];
89
90 /*
91 * Check the number of samples is not too large
92 */
93 if (NumSamples > pInstance->Capabilities.MaxBlockSize) {
94 return (LVDBE_TOOMANYSAMPLES);
95 }
96
97 /*
98 * Check if the algorithm is enabled
99 */
100 /* DBE path is processed when DBE is ON or during On/Off transitions */
101 if ((pInstance->Params.OperatingMode == LVDBE_ON)
102 || (LVC_Mixer_GetCurrent(
103 &pInstance->pData->BypassMixer.MixerStream[0])
104 != LVC_Mixer_GetTarget(
105 &pInstance->pData->BypassMixer.MixerStream[0]))) {
106
107 /*
108 * Convert 16-bit samples to 32-bit and scale
109 * (For a 16-bit implementation apply headroom loss here)
110 */
111 Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data */
112 pScratch, /* Dest. 32-bit data */
113 (LVM_INT16) (2 * NumSamples), /* Left and right */
114 LVDBE_SCALESHIFT); /* Shift scale */
115
116 /*
117 * Apply the high pass filter if selected
118 */
119 if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
120 BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */
121 (LVM_INT32 *) pScratch, /* Source */
122 (LVM_INT32 *) pScratch, /* Destination */
123 (LVM_INT16) NumSamples); /* Number of samples */
124 }
125
126 /*
127 * Create the mono stream
128 */
129 From2iToMono_32(pScratch, /* Stereo source */
130 pMono, /* Mono destination */
131 (LVM_INT16) NumSamples); /* Number of samples */
132
133 /*
134 * Apply the band pass filter
135 */
136 BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
137 (LVM_INT32 *) pMono, /* Source */
138 (LVM_INT32 *) pMono, /* Destination */
139 (LVM_INT16) NumSamples); /* Number of samples */
140
141 /*
142 * Apply the AGC and mix
143 */
144 AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
145 pScratch, /* Stereo source */
146 pMono, /* Mono band pass source */
147 pScratch, /* Stereo destination */
148 NumSamples); /* Number of samples */
149
150 /*
151 * Convert 32-bit samples to 16-bit and saturate
152 * (Not required for 16-bit implemenations)
153 */
154 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */
155 (LVM_INT16 *) pScratch, /* Dest. 16-bit data */
156 (LVM_INT16) (2 * NumSamples), /* Left and right */
157 LVDBE_SCALESHIFT); /* Shift scale */
158
159 }
160
161 /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
162 if ((pInstance->Params.OperatingMode == LVDBE_OFF)
163 || (LVC_Mixer_GetCurrent(
164 &pInstance->pData->BypassMixer.MixerStream[1])
165 != LVC_Mixer_GetTarget(
166 &pInstance->pData->BypassMixer.MixerStream[1]))) {
167
168 /*
169 * The algorithm is disabled but volume management is required to compensate for
170 * headroom and volume (if enabled)
171 */
172 LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, pInData,
173 pScratchVol, (LVM_INT16) (2 * NumSamples)); /* Left and right */
174
175 }
176
177 /*
178 * Mix DBE processed path and bypass volume path
179 */
180 LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
181 (LVM_INT16 *) pScratch, pScratchVol, pOutData,
182 (LVM_INT16) (2 * NumSamples));
183
184 return (LVDBE_SUCCESS);
185 }
186 #else /*BUILD_FLOAT*/
LVDBE_Process(LVDBE_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,LVM_UINT16 NumSamples)187 LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
188 const LVM_FLOAT *pInData,
189 LVM_FLOAT *pOutData,
190 LVM_UINT16 NumSamples)
191 {
192
193 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
194 LVM_FLOAT *pScratch_in = (LVM_FLOAT *)pInstance->MemoryTable.Region
195 [LVDBE_MEMREGION_SCRATCH].pBaseAddress;
196 LVM_FLOAT *pScratch = pScratch_in + 2 * NumSamples;
197 LVM_FLOAT *pMono;
198 LVM_INT32 ii = 0;
199
200 /* Scratch for Volume Control starts at offset of 4*NumSamples float values from pScratch */
201 LVM_FLOAT *pScratchVol = (LVM_FLOAT *)(&pScratch_in[4 * NumSamples]);
202 // LVM_INT16 *pScratchVol_int = (LVM_INT16 *)(pScratchVol);
203
204 /* Scratch for Mono path starts at offset of 6*NumSamples 32-bit values from pScratch */
205 pMono = &pScratch_in[4 * NumSamples];
206
207 /*
208 * Check the number of samples is not too large
209 */
210 if (NumSamples > pInstance->Capabilities.MaxBlockSize)
211 {
212 return(LVDBE_TOOMANYSAMPLES);
213 }
214
215 /*
216 * Convert 16-bit samples to Float
217 */
218 Copy_Float(pInData, /* Source 16-bit data */
219 pScratch_in, /* Dest. 32-bit data */
220 (LVM_INT16)(2 * NumSamples)); /* Left and right */
221
222 for (ii = 0; ii < 2 * NumSamples; ii++) {
223 pScratch[ii] = pScratch_in[ii];
224 }
225 /*
226 * Check if the algorithm is enabled
227 */
228 /* DBE path is processed when DBE is ON or during On/Off transitions */
229 if ((pInstance->Params.OperatingMode == LVDBE_ON)||
230 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
231 !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
232 {
233
234 /*
235 * Apply the high pass filter if selected
236 */
237 if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
238 {
239 BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */
240 (LVM_FLOAT *)pScratch, /* Source */
241 (LVM_FLOAT *)pScratch, /* Destination */
242 (LVM_INT16)NumSamples); /* Number of samples */
243 }
244
245 /*
246 * Create the mono stream
247 */
248 From2iToMono_Float((LVM_FLOAT *)pScratch, /* Stereo source */
249 pMono, /* Mono destination */
250 (LVM_INT16)NumSamples); /* Number of samples */
251
252 /*
253 * Apply the band pass filter
254 */
255 BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
256 (LVM_FLOAT *)pMono, /* Source */
257 (LVM_FLOAT *)pMono, /* Destination */
258 (LVM_INT16)NumSamples); /* Number of samples */
259
260 /*
261 * Apply the AGC and mix
262 */
263 AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
264 pScratch, /* Stereo source */
265 pMono, /* Mono band pass source */
266 pScratch, /* Stereo destination */
267 NumSamples); /* Number of samples */
268
269 for (ii = 0; ii < 2 * NumSamples; ii++) {
270 //TODO: replace with existing clamping function
271 if(pScratch[ii] < -1.0) {
272 pScratch[ii] = -1.0;
273 } else if(pScratch[ii] > 1.0) {
274 pScratch[ii] = 1.0;
275 }
276 }
277 }
278
279 /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
280 if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
281 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
282 !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
283 {
284
285 /*
286 * The algorithm is disabled but volume management is required to compensate for
287 * headroom and volume (if enabled)
288 */
289 LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
290 pScratch_in,
291 pScratchVol,
292 (LVM_INT16)(2 * NumSamples)); /* Left and right */
293 }
294
295 /*
296 * Mix DBE processed path and bypass volume path
297 */
298 LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
299 pScratch,
300 pScratchVol,
301 pOutData,
302 (LVM_INT16)(2 * NumSamples));
303
304 return(LVDBE_SUCCESS);
305 }
306 #endif
307