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 /* */
21 /* Includes */
22 /* */
23 /****************************************************************************************/
24
25 #include "LVEQNB.h"
26 #include "LVEQNB_Private.h"
27 #include "InstAlloc.h"
28 #include <string.h> /* For memset */
29
30 /****************************************************************************************/
31 /* */
32 /* FUNCTION: LVEQNB_Memory */
33 /* */
34 /* DESCRIPTION: */
35 /* This function is used for memory allocation and free. It can be called in */
36 /* two ways: */
37 /* */
38 /* hInstance = NULL Returns the memory requirements */
39 /* hInstance = Instance handle Returns the memory requirements and */
40 /* allocated base addresses for the instance */
41 /* */
42 /* When this function is called for memory allocation (hInstance=NULL) the memory */
43 /* base address pointers are NULL on return. */
44 /* */
45 /* When the function is called for free (hInstance = Instance Handle) the memory */
46 /* table returns the allocated memory and base addresses used during initialisation. */
47 /* */
48 /* PARAMETERS: */
49 /* hInstance Instance Handle */
50 /* pMemoryTable Pointer to an empty memory definition table */
51 /* pCapabilities Pointer to the instance capabilities */
52 /* */
53 /* RETURNS: */
54 /* LVEQNB_SUCCESS Succeeded */
55 /* LVEQNB_NULLADDRESS When any of pMemoryTable and pCapabilities is NULL address */
56 /* */
57 /* NOTES: */
58 /* 1. This function may be interrupted by the LVEQNB_Process function */
59 /* */
60 /****************************************************************************************/
61
LVEQNB_Memory(LVEQNB_Handle_t hInstance,LVEQNB_MemTab_t * pMemoryTable,LVEQNB_Capabilities_t * pCapabilities)62 LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t hInstance,
63 LVEQNB_MemTab_t *pMemoryTable,
64 LVEQNB_Capabilities_t *pCapabilities)
65 {
66
67 INST_ALLOC AllocMem;
68 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
69
70
71 if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL))
72 {
73 return LVEQNB_NULLADDRESS;
74 }
75
76
77 /*
78 * Fill in the memory table
79 */
80 if (hInstance == LVM_NULL)
81 {
82 /*
83 * Instance memory
84 */
85 InstAlloc_Init(&AllocMem,
86 LVM_NULL);
87 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
88 sizeof(LVEQNB_Instance_t));
89 pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size = InstAlloc_GetTotal(&AllocMem);
90 pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment = LVEQNB_INSTANCE_ALIGN;
91 pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type = LVEQNB_PERSISTENT;
92 pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
93
94
95 /*
96 * Persistant data memory
97 */
98 InstAlloc_Init(&AllocMem,
99 LVM_NULL);
100 #ifdef BUILD_FLOAT
101 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
102 sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
103 InstAlloc_AddMember(&AllocMem, /* High pass filter */
104 sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
105 /* Equaliser Biquad Taps */
106 InstAlloc_AddMember(&AllocMem,
107 (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t)));
108 /* Filter definitions */
109 InstAlloc_AddMember(&AllocMem,
110 (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));
111 /* Biquad types */
112 InstAlloc_AddMember(&AllocMem,
113 (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));
114 #else
115 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
116 sizeof(Biquad_2I_Order2_Taps_t));
117 InstAlloc_AddMember(&AllocMem, /* High pass filter */
118 sizeof(Biquad_2I_Order2_Taps_t));
119 InstAlloc_AddMember(&AllocMem,
120 (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */
121 InstAlloc_AddMember(&AllocMem,
122 (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t))); /* Filter definitions */
123 InstAlloc_AddMember(&AllocMem,
124 (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en))); /* Biquad types */
125 #endif
126 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size = InstAlloc_GetTotal(&AllocMem);
127 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment = LVEQNB_DATA_ALIGN;
128 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type = LVEQNB_PERSISTENT_DATA;
129 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
130
131 /*
132 * Persistant coefficient memory
133 */
134 InstAlloc_Init(&AllocMem,
135 LVM_NULL);
136 #ifdef BUILD_FLOAT
137 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
138 sizeof(Biquad_FLOAT_Instance_t));
139 InstAlloc_AddMember(&AllocMem, /* High pass filter */
140 sizeof(Biquad_FLOAT_Instance_t));
141 /* Equaliser Biquad Instance */
142 InstAlloc_AddMember(&AllocMem,
143 pCapabilities->MaxBands * sizeof(Biquad_FLOAT_Instance_t));
144 #else
145 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
146 sizeof(Biquad_Instance_t));
147 InstAlloc_AddMember(&AllocMem, /* High pass filter */
148 sizeof(Biquad_Instance_t));
149 InstAlloc_AddMember(&AllocMem,
150 pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
151 #endif
152 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size = InstAlloc_GetTotal(&AllocMem);
153 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment = LVEQNB_COEF_ALIGN;
154 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type = LVEQNB_PERSISTENT_COEF;
155 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
156
157 /*
158 * Scratch memory
159 */
160 InstAlloc_Init(&AllocMem,
161 LVM_NULL);
162 #ifdef BUILD_FLOAT
163 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
164 LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * \
165 pCapabilities->MaxBlockSize);
166 #else
167 InstAlloc_AddMember(&AllocMem, /* Low pass filter */
168 LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
169 #endif
170 pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size = InstAlloc_GetTotal(&AllocMem);
171 pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment = LVEQNB_SCRATCH_ALIGN;
172 pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type = LVEQNB_SCRATCH;
173 pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
174 }
175 else
176 {
177 /* Read back memory allocation table */
178 *pMemoryTable = pInstance->MemoryTable;
179 }
180
181 return(LVEQNB_SUCCESS);
182 }
183
184
185 /****************************************************************************************/
186 /* */
187 /* FUNCTION: LVEQNB_Init */
188 /* */
189 /* DESCRIPTION: */
190 /* Create and initialisation function for the N-Band equaliser module */
191 /* */
192 /* This function can be used to create an algorithm instance by calling with */
193 /* hInstance set to NULL. In this case the algorithm returns the new instance */
194 /* handle. */
195 /* */
196 /* This function can be used to force a full re-initialisation of the algorithm */
197 /* by calling with hInstance = Instance Handle. In this case the memory table */
198 /* should be correct for the instance, this can be ensured by calling the function */
199 /* DBE_Memory before calling this function. */
200 /* */
201 /* PARAMETERS: */
202 /* hInstance Instance handle */
203 /* pMemoryTable Pointer to the memory definition table */
204 /* pCapabilities Pointer to the instance capabilities */
205 /* */
206 /* RETURNS: */
207 /* LVEQNB_SUCCESS Initialisation succeeded */
208 /* LVEQNB_NULLADDRESS When pCapabilities or pMemoryTableis or phInstance are NULL */
209 /* LVEQNB_NULLADDRESS One or more of the memory regions has a NULL base address */
210 /* pointer for a memory region with a non-zero size. */
211 /* */
212 /* NOTES: */
213 /* 1. The instance handle is the pointer to the base address of the first memory */
214 /* region. */
215 /* 2. This function must not be interrupted by the LVEQNB_Process function */
216 /* */
217 /****************************************************************************************/
218
LVEQNB_Init(LVEQNB_Handle_t * phInstance,LVEQNB_MemTab_t * pMemoryTable,LVEQNB_Capabilities_t * pCapabilities)219 LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t *phInstance,
220 LVEQNB_MemTab_t *pMemoryTable,
221 LVEQNB_Capabilities_t *pCapabilities)
222 {
223
224 LVEQNB_Instance_t *pInstance;
225 LVM_UINT32 MemSize;
226 INST_ALLOC AllocMem;
227 LVM_INT32 i;
228
229 /*
230 * Check for NULL pointers
231 */
232 if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL))
233 {
234 return LVEQNB_NULLADDRESS;
235 }
236
237 /*
238 * Check the memory table for NULL pointers
239 */
240 for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++)
241 {
242 if (pMemoryTable->Region[i].Size!=0)
243 {
244 if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
245 {
246 return(LVEQNB_NULLADDRESS);
247 }
248 }
249 }
250
251 /*
252 * Set the instance handle if not already initialised
253 */
254
255 InstAlloc_Init(&AllocMem, pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress);
256
257 if (*phInstance == LVM_NULL)
258 {
259 *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t));
260 }
261 pInstance =(LVEQNB_Instance_t *)*phInstance;
262
263
264
265 /*
266 * Save the memory table in the instance structure
267 */
268 pInstance->Capabilities = *pCapabilities;
269
270
271 /*
272 * Save the memory table in the instance structure and
273 * set the structure pointers
274 */
275 pInstance->MemoryTable = *pMemoryTable;
276
277 /*
278 * Allocate coefficient memory
279 */
280 InstAlloc_Init(&AllocMem,
281 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
282
283 #ifdef BUILD_FLOAT
284 /* Equaliser Biquad Instance */
285 pInstance->pEQNB_FilterState_Float = InstAlloc_AddMember(&AllocMem,
286 pCapabilities->MaxBands * \
287 sizeof(Biquad_FLOAT_Instance_t));
288 #else
289 pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
290 pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
291 #endif
292
293
294
295 /*
296 * Allocate data memory
297 */
298 InstAlloc_Init(&AllocMem,
299 pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
300
301 #ifdef BUILD_FLOAT
302 MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
303 pInstance->pEQNB_Taps_Float = (Biquad_2I_Order2_FLOAT_Taps_t *)InstAlloc_AddMember(&AllocMem,
304 MemSize);
305 #else
306 MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
307 pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
308 MemSize);
309 #endif
310 MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
311 pInstance->pBandDefinitions = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
312 MemSize);
313 // clear all the bands, setting their gain to 0, otherwise when applying new params,
314 // it will compare against uninitialized values
315 memset(pInstance->pBandDefinitions, 0, MemSize);
316 MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en));
317 pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem,
318 MemSize);
319
320
321 /*
322 * Internally map, structure and allign scratch memory
323 */
324 InstAlloc_Init(&AllocMem,
325 pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
326
327 #ifdef BUILD_FLOAT
328 pInstance->pFastTemporary = (LVM_FLOAT *)InstAlloc_AddMember(&AllocMem,
329 sizeof(LVM_FLOAT));
330 #else
331 pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
332 sizeof(LVM_INT16));
333 #endif
334
335 /*
336 * Update the instance parameters
337 */
338 pInstance->Params.NBands = 0;
339 pInstance->Params.OperatingMode = LVEQNB_BYPASS;
340 pInstance->Params.pBandDefinition = LVM_NULL;
341 pInstance->Params.SampleRate = LVEQNB_FS_8000;
342 pInstance->Params.SourceFormat = LVEQNB_STEREO;
343
344 /*
345 * Initialise the filters
346 */
347 LVEQNB_SetFilters(pInstance, /* Set the filter types */
348 &pInstance->Params);
349
350 LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */
351
352 LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */
353
354 /*
355 * Initialise the bypass variables
356 */
357 pInstance->BypassMixer.MixerStream[0].CallbackSet = 0;
358 pInstance->BypassMixer.MixerStream[0].CallbackParam = 0;
359 pInstance->BypassMixer.MixerStream[0].pCallbackHandle = (void*)pInstance;
360 pInstance->BypassMixer.MixerStream[0].pCallBack = LVEQNB_BypassMixerCallBack;
361
362 LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
363 LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
364
365
366 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
367 pInstance->BypassMixer.MixerStream[1].CallbackParam = 0;
368 pInstance->BypassMixer.MixerStream[1].pCallbackHandle = LVM_NULL;
369 pInstance->BypassMixer.MixerStream[1].pCallBack = LVM_NULL;
370 #ifdef BUILD_FLOAT
371 LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1], 0, 1.0f);
372 LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1], 0, LVM_FS_8000, 2);
373 #else
374 LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
375 LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
376 #endif
377
378 pInstance->bInOperatingModeTransition = LVM_FALSE;
379
380 return(LVEQNB_SUCCESS);
381 }
382
383