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 <string.h> // memset
25 #include "LVDBE.h"
26 #include "LVDBE_Private.h"
27 #include "VectorArithmetic.h"
28 #include "AGC.h"
29 #include "LVDBE_Coeffs.h" /* Filter coefficients */
30 #include <log/log.h>
31
32 /********************************************************************************************/
33 /* */
34 /* FUNCTION: LVDBE_Process */
35 /* */
36 /* DESCRIPTION: */
37 /* Process function for the Bass Enhancement module. */
38 /* */
39 /* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */
40 /* format is not supported, the calling routine must convert the mono stream to */
41 /* mono-in-stereo. */
42 /* ___________ */
43 /* ________ | | ________ */
44 /* | | _____ |------------------------->| | | | */
45 /* | 16-bit | | | | ________ | | | 32-bit | */
46 /* -+-->| to |-->| HPF |--| | | _____ | AGC Mixer |-->| to |--| */
47 /* | | 32-bit | |_____| | | Stereo | | | | | | 16-bit | | */
48 /* | |________| |-->| to |-->| BPF |-->| | |________| 0 */
49 /* | | Mono | |_____| |___________| \--> */
50 /* | |________| */
51 /* | _________ 0 */
52 /* | | | | */
53 /* |----------------------------------------------------| Volume |-----------------| */
54 /* | Control | */
55 /* |_________| */
56 /* */
57 /* PARAMETERS: */
58 /* hInstance Instance handle */
59 /* pInData Pointer to the input data */
60 /* pOutData Pointer to the output data */
61 /* NumSamples Number of samples in the input buffer */
62 /* */
63 /* RETURNS: */
64 /* LVDBE_SUCCESS Succeeded */
65 /* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
66 /* */
67 /* NOTES: */
68 /* 1. The input and output data must be 32-bit format. The input is scaled by a shift */
69 /* when converting from 16-bit format, this scaling allows for internal headroom in the */
70 /* bass enhancement algorithm. */
71 /* 2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with */
72 /* the headroom loss. This headroom loss is compensated in the volume control so the */
73 /* overall end to end gain is odB. */
74 /* */
75 /********************************************************************************************/
LVDBE_Process(LVDBE_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,const LVM_UINT16 NrFrames)76 LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
77 const LVM_FLOAT *pInData,
78 LVM_FLOAT *pOutData,
79 const LVM_UINT16 NrFrames) // updated to use samples = frames * channels.
80 {
81 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
82
83 /*Extract number of Channels info*/
84 #ifdef SUPPORT_MC
85 // Mono passed in as stereo
86 const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
87 ? 2 : pInstance->Params.NrChannels;
88 #else
89 const LVM_INT32 NrChannels = 2; // FCC_2
90 #endif
91 const LVM_INT32 NrSamples = NrChannels * NrFrames;
92
93 /* Space to store DBE path computation */
94 LVM_FLOAT * const pScratch =
95 (LVM_FLOAT *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
96
97 /*
98 * Scratch for Mono path starts at offset of
99 * NrSamples float values from pScratch.
100 */
101 LVM_FLOAT * const pMono = pScratch + NrSamples;
102
103 /*
104 * TRICKY: pMono is used and discarded by the DBE path.
105 * so it is available for use for the pScratchVol
106 * path which is computed afterwards.
107 *
108 * Space to store Volume Control path computation.
109 * This is identical to pMono (see TRICKY comment).
110 */
111 LVM_FLOAT * const pScratchVol = pMono;
112
113 /*
114 * Check the number of frames is not too large
115 */
116 if (NrFrames > pInstance->Capabilities.MaxBlockSize)
117 {
118 return LVDBE_TOOMANYSAMPLES;
119 }
120
121 /*
122 * Check if the algorithm is enabled
123 */
124 /* DBE path is processed when DBE is ON or during On/Off transitions */
125 if ((pInstance->Params.OperatingMode == LVDBE_ON)||
126 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
127 !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
128 {
129 // make copy of input data
130 Copy_Float(pInData,
131 pScratch,
132 (LVM_INT16)NrSamples);
133
134 /*
135 * Apply the high pass filter if selected
136 */
137 if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
138 {
139 #ifdef SUPPORT_MC
140 BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
141 pScratch, /* Source */
142 pScratch, /* Destination */
143 (LVM_INT16)NrFrames,
144 (LVM_INT16)NrChannels);
145 #else
146 BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */
147 pScratch, /* Source */
148 pScratch, /* Destination */
149 (LVM_INT16)NrFrames);
150 #endif
151 }
152
153 /*
154 * Create the mono stream
155 */
156 #ifdef SUPPORT_MC
157 FromMcToMono_Float(pScratch, /* Source */
158 pMono, /* Mono destination */
159 (LVM_INT16)NrFrames, /* Number of frames */
160 (LVM_INT16)NrChannels);
161 #else
162 From2iToMono_Float(pScratch, /* Stereo source */
163 pMono, /* Mono destination */
164 (LVM_INT16)NrFrames);
165 #endif
166
167 /*
168 * Apply the band pass filter
169 */
170 BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
171 pMono, /* Source */
172 pMono, /* Destination */
173 (LVM_INT16)NrFrames);
174
175 /*
176 * Apply the AGC and mix
177 */
178 #ifdef SUPPORT_MC
179 AGC_MIX_VOL_Mc1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
180 pScratch, /* Source */
181 pMono, /* Mono band pass source */
182 pScratch, /* Destination */
183 NrFrames, /* Number of frames */
184 NrChannels); /* Number of channels */
185 #else
186 AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
187 pScratch, /* Stereo source */
188 pMono, /* Mono band pass source */
189 pScratch, /* Stereo destination */
190 NrFrames);
191 #endif
192
193 for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
194 //TODO: replace with existing clamping function
195 if (pScratch[ii] < -1.0) {
196 pScratch[ii] = -1.0;
197 } else if (pScratch[ii] > 1.0) {
198 pScratch[ii] = 1.0;
199 }
200 }
201 } else {
202 // clear DBE processed path
203 memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
204 }
205
206 /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
207 if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
208 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
209 !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
210 {
211
212 /*
213 * The algorithm is disabled but volume management is required to compensate for
214 * headroom and volume (if enabled)
215 */
216 #ifdef SUPPORT_MC
217 LVC_MixSoft_Mc_D16C31_SAT(&pInstance->pData->BypassVolume,
218 pInData,
219 pScratchVol,
220 (LVM_INT16)NrFrames,
221 (LVM_INT16)NrChannels);
222 #else
223 LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
224 pInData,
225 pScratchVol,
226 (LVM_INT16)NrSamples); /* Left and right, really # samples */
227 #endif
228 } else {
229 // clear bypass volume path
230 memset(pScratchVol, 0, sizeof(*pScratchVol) * NrSamples);
231 }
232
233 /*
234 * Mix DBE processed path and bypass volume path
235 */
236 #ifdef SUPPORT_MC
237 LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->pData->BypassMixer,
238 pScratch,
239 pScratchVol,
240 pOutData,
241 (LVM_INT16)NrFrames,
242 (LVM_INT16)NrChannels);
243 #else
244 LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
245 pScratch,
246 pScratchVol,
247 pOutData,
248 (LVM_INT16)NrSamples);
249 #endif
250 return LVDBE_SUCCESS;
251 }
252