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
27 /****************************************************************************************/
28 /* */
29 /* FUNCTION: LVDBE_Memory */
30 /* */
31 /* DESCRIPTION: */
32 /* This function is used for memory allocation and free. It can be called in */
33 /* two ways: */
34 /* */
35 /* hInstance = NULL Returns the memory requirements */
36 /* hInstance = Instance handle Returns the memory requirements and */
37 /* allocated base addresses for the instance */
38 /* */
39 /* When this function is called for memory allocation (hInstance=NULL) the memory */
40 /* base address pointers are NULL on return. */
41 /* */
42 /* When the function is called for free (hInstance = Instance Handle) the memory */
43 /* table returns the allocated memory and base addresses used during initialisation. */
44 /* */
45 /* PARAMETERS: */
46 /* hInstance Instance Handle */
47 /* pMemoryTable Pointer to an empty memory definition table */
48 /* pCapabilities Pointer to the instance capabilities */
49 /* */
50 /* RETURNS: */
51 /* LVDBE_SUCCESS Succeeded */
52 /* */
53 /* NOTES: */
54 /* 1. This function may be interrupted by the LVDBE_Process function */
55 /* */
56 /****************************************************************************************/
57
LVDBE_Memory(LVDBE_Handle_t hInstance,LVDBE_MemTab_t * pMemoryTable,LVDBE_Capabilities_t * pCapabilities)58 LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t hInstance,
59 LVDBE_MemTab_t *pMemoryTable,
60 LVDBE_Capabilities_t *pCapabilities)
61 {
62
63 LVM_UINT32 ScratchSize;
64 LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *)hInstance;
65
66
67 /*
68 * Fill in the memory table
69 */
70 if (hInstance == LVM_NULL)
71 {
72 /*
73 * Instance memory
74 */
75 pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size = sizeof(LVDBE_Instance_t);
76 pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment = LVDBE_INSTANCE_ALIGN;
77 pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type = LVDBE_PERSISTENT;
78 pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
79
80 /*
81 * Data memory
82 */
83 #ifdef BUILD_FLOAT
84 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size = sizeof(LVDBE_Data_FLOAT_t);
85 #else
86 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size = sizeof(LVDBE_Data_t);
87 #endif
88 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment = LVDBE_PERSISTENT_DATA_ALIGN;
89 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type = LVDBE_PERSISTENT_DATA;
90 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
91
92 /*
93 * Coef memory
94 */
95 #ifdef BUILD_FLOAT
96 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_FLOAT_t);
97 #else
98 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_t);
99 #endif
100 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment = LVDBE_PERSISTENT_COEF_ALIGN;
101 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type = LVDBE_PERSISTENT_COEF;
102 pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
103
104 /*
105 * Scratch memory
106 */
107 #ifdef BUILD_FLOAT
108 ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_FLOAT) * \
109 pCapabilities->MaxBlockSize);
110 #else /*BUILD_FLOAT*/
111 ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
112 #endif
113 pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size = ScratchSize;
114 pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment = LVDBE_SCRATCH_ALIGN;
115 pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type = LVDBE_SCRATCH;
116 pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
117 }
118 else
119 {
120 /* Read back memory allocation table */
121 *pMemoryTable = pInstance->MemoryTable;
122 }
123
124 return(LVDBE_SUCCESS);
125 }
126
127
128 /****************************************************************************************/
129 /* */
130 /* FUNCTION: LVDBE_Init */
131 /* */
132 /* DESCRIPTION: */
133 /* Create and initialisation function for the Dynamic Bass Enhancement module */
134 /* */
135 /* This function can be used to create an algorithm instance by calling with */
136 /* hInstance set to NULL. In this case the algorithm returns the new instance */
137 /* handle. */
138 /* */
139 /* This function can be used to force a full re-initialisation of the algorithm */
140 /* by calling with hInstance = Instance Handle. In this case the memory table */
141 /* should be correct for the instance, this can be ensured by calling the function */
142 /* DBE_Memory before calling this function. */
143 /* */
144 /* PARAMETERS: */
145 /* hInstance Instance handle */
146 /* pMemoryTable Pointer to the memory definition table */
147 /* pCapabilities Pointer to the instance capabilities */
148 /* */
149 /* RETURNS: */
150 /* LVDBE_SUCCESS Initialisation succeeded */
151 /* LVDBE_ALIGNMENTERROR Instance or scratch memory on incorrect alignment */
152 /* LVDBE_NULLADDRESS Instance or scratch memory has a NULL pointer */
153 /* */
154 /* NOTES: */
155 /* 1. The instance handle is the pointer to the base address of the first memory */
156 /* region. */
157 /* 2. This function must not be interrupted by the LVDBE_Process function */
158 /* */
159 /****************************************************************************************/
160
LVDBE_Init(LVDBE_Handle_t * phInstance,LVDBE_MemTab_t * pMemoryTable,LVDBE_Capabilities_t * pCapabilities)161 LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance,
162 LVDBE_MemTab_t *pMemoryTable,
163 LVDBE_Capabilities_t *pCapabilities)
164 {
165
166 LVDBE_Instance_t *pInstance;
167 #ifdef BUILD_FLOAT
168 LVMixer3_1St_FLOAT_st *pMixer_Instance;
169 LVMixer3_2St_FLOAT_st *pBypassMixer_Instance;
170 LVM_FLOAT MixGain;
171 #else
172 LVMixer3_1St_st *pMixer_Instance;
173 LVMixer3_2St_st *pBypassMixer_Instance;
174 LVM_INT32 MixGain;
175 #endif
176 LVM_INT16 i;
177
178
179 /*
180 * Set the instance handle if not already initialised
181 */
182 if (*phInstance == LVM_NULL)
183 {
184 *phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
185 }
186 pInstance =(LVDBE_Instance_t *)*phInstance;
187
188
189 /*
190 * Check the memory table for NULL pointers and incorrectly aligned data
191 */
192 for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
193 {
194 if (pMemoryTable->Region[i].Size!=0)
195 {
196 if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
197 {
198 return(LVDBE_NULLADDRESS);
199 }
200 if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
201 return(LVDBE_ALIGNMENTERROR);
202 }
203 }
204 }
205
206
207 /*
208 * Save the memory table in the instance structure
209 */
210 pInstance->Capabilities = *pCapabilities;
211
212
213 /*
214 * Save the memory table in the instance structure
215 */
216 pInstance->MemoryTable = *pMemoryTable;
217
218
219 /*
220 * Set the default instance parameters
221 */
222 pInstance->Params.CentreFrequency = LVDBE_CENTRE_55HZ;
223 pInstance->Params.EffectLevel = 0;
224 pInstance->Params.HeadroomdB = 0;
225 pInstance->Params.HPFSelect = LVDBE_HPF_OFF;
226 pInstance->Params.OperatingMode = LVDBE_OFF;
227 pInstance->Params.SampleRate = LVDBE_FS_8000;
228 pInstance->Params.VolumeControl = LVDBE_VOLUME_OFF;
229 pInstance->Params.VolumedB = 0;
230
231
232 /*
233 * Set pointer to data and coef memory
234 */
235 pInstance->pData = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
236 pInstance->pCoef = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
237
238
239 /*
240 * Initialise the filters
241 */
242 LVDBE_SetFilters(pInstance, /* Set the filter taps and coefficients */
243 &pInstance->Params);
244
245
246 /*
247 * Initialise the AGC
248 */
249 LVDBE_SetAGC(pInstance, /* Set the AGC gain */
250 &pInstance->Params);
251 pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;
252 /* Default to the bass boost setting */
253
254 // initialize the mixer with some fixes values since otherwise LVDBE_SetVolume ends up
255 // reading uninitialized data
256 pMixer_Instance = &pInstance->pData->BypassVolume;
257 #ifndef BUILD_FLOAT
258 LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],0x00007FFF,0x00007FFF);
259 #else
260 LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], 1.0, 1.0);
261 #endif
262
263 /*
264 * Initialise the volume
265 */
266 LVDBE_SetVolume(pInstance, /* Set the Volume */
267 &pInstance->Params);
268
269 pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
270 /* Initialise as the target */
271 #ifndef BUILD_FLOAT
272 MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
273 LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
274 #else
275 MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
276 LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], MixGain, MixGain);
277 #endif
278
279 /* Configure the mixer process path */
280 pMixer_Instance->MixerStream[0].CallbackParam = 0;
281 pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
282 pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
283 pMixer_Instance->MixerStream[0].CallbackSet = 0;
284
285 /*
286 * Initialise the clicks minimisation BypassMixer
287 */
288
289 pBypassMixer_Instance = &pInstance->pData->BypassMixer;
290
291 /*
292 * Setup the mixer gain for the processed path
293 */
294 pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
295 pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
296 pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
297 pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
298
299 LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
300 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
301 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
302
303 /*
304 * Setup the mixer gain for the unprocessed path
305 */
306 pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
307 pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
308 pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
309 pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
310 #ifndef BUILD_FLOAT
311 LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
312 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
313 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
314 #else
315 LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1], 1.0, 1.0);
316 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
317 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate, 2);
318 #endif
319
320 return(LVDBE_SUCCESS);
321 }
322