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