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