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