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#include "VectorArithmetic.h"
27#include "AGC.h"
28#include "LVDBE_Coeffs.h"               /* Filter coefficients */
29
30/********************************************************************************************/
31/*                                                                                          */
32/* FUNCTION:                 LVDBE_Process                                                  */
33/*                                                                                          */
34/* DESCRIPTION:                                                                             */
35/*  Process function for the Bass Enhancement module.                                       */
36/*                                                                                          */
37/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono            */
38/*  format is not supported, the calling routine must convert the mono stream to            */
39/*  mono-in-stereo.                                                                         */
40/*                                                        ___________                       */
41/*       ________                                        |           |    ________          */
42/*      |        |    _____   |------------------------->|           |   |        |         */
43/*      | 16-bit |   |     |  |    ________              |           |   | 32-bit |         */
44/* -+-->|   to   |-->| HPF |--|   |        |    _____    | AGC Mixer |-->|   to   |--|      */
45/*  |   | 32-bit |   |_____|  |   | Stereo |   |     |   |           |   | 16-bit |  |      */
46/*  |   |________|            |-->|   to   |-->| BPF |-->|           |   |________|  0      */
47/*  |                             |  Mono  |   |_____|   |___________|                \-->  */
48/*  |                             |________|                                                */
49/*  |                                                     _________                  0      */
50/*  |                                                    |         |                 |      */
51/*  |----------------------------------------------------| Volume  |-----------------|      */
52/*                                                       | Control |                        */
53/*                                                       |_________|                        */
54/*                                                                                          */
55/* PARAMETERS:                                                                              */
56/*  hInstance                 Instance handle                                               */
57/*  pInData                  Pointer to the input data                                      */
58/*  pOutData                 Pointer to the output data                                     */
59/*  NumSamples                 Number of samples in the input buffer                        */
60/*                                                                                          */
61/* RETURNS:                                                                                 */
62/*  LVDBE_SUCCESS            Succeeded                                                      */
63/*    LVDBE_TOOMANYSAMPLES    NumSamples was larger than the maximum block size             */
64/*                                                                                          */
65/* NOTES:                                                                                   */
66/*  1. The input and output data must be 32-bit format. The input is scaled by a shift      */
67/*     when converting from 16-bit format, this scaling allows for internal headroom in the */
68/*     bass enhancement algorithm.                                                          */
69/*  2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with   */
70/*     the headroom loss. This headroom loss is compensated in the volume control so the    */
71/*     overall end to end gain is odB.                                                      */
72/*                                                                                          */
73/********************************************************************************************/
74#ifndef BUILD_FLOAT
75LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
76    const LVM_INT16 *pInData, LVM_INT16 *pOutData, LVM_UINT16 NumSamples) {
77
78  LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *) hInstance;
79  LVM_INT32 *pScratch =
80      (LVM_INT32 *) pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
81  LVM_INT32 *pMono;
82  LVM_INT16 *pInput = (LVM_INT16 *) pInData;
83
84  /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
85  LVM_INT16 *pScratchVol = (LVM_INT16 *) (&pScratch[NumSamples]);
86
87  /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
88  pMono = &pScratch[2 * NumSamples];
89
90  /*
91   * Check the number of samples is not too large
92   */
93  if (NumSamples > pInstance->Capabilities.MaxBlockSize) {
94    return (LVDBE_TOOMANYSAMPLES);
95  }
96
97  /*
98   * Check if the algorithm is enabled
99   */
100  /* DBE path is processed when DBE is ON or during On/Off transitions */
101  if ((pInstance->Params.OperatingMode == LVDBE_ON)
102      || (LVC_Mixer_GetCurrent(
103          &pInstance->pData->BypassMixer.MixerStream[0])
104          != LVC_Mixer_GetTarget(
105              &pInstance->pData->BypassMixer.MixerStream[0]))) {
106
107    /*
108     * Convert 16-bit samples to 32-bit and scale
109     * (For a 16-bit implementation apply headroom loss here)
110     */
111    Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data    */
112    pScratch, /* Dest. 32-bit data     */
113    (LVM_INT16) (2 * NumSamples), /* Left and right        */
114    LVDBE_SCALESHIFT); /* Shift scale           */
115
116    /*
117     * Apply the high pass filter if selected
118     */
119    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
120      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
121      (LVM_INT32 *) pScratch, /* Source               */
122      (LVM_INT32 *) pScratch, /* Destination          */
123      (LVM_INT16) NumSamples); /* Number of samples    */
124    }
125
126    /*
127     * Create the mono stream
128     */
129    From2iToMono_32(pScratch, /* Stereo source         */
130    pMono, /* Mono destination      */
131    (LVM_INT16) NumSamples); /* Number of samples     */
132
133    /*
134     * Apply the band pass filter
135     */
136    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
137    (LVM_INT32 *) pMono, /* Source                */
138    (LVM_INT32 *) pMono, /* Destination           */
139    (LVM_INT16) NumSamples); /* Number of samples     */
140
141    /*
142     * Apply the AGC and mix
143     */
144    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
145    pScratch, /* Stereo source         */
146    pMono, /* Mono band pass source */
147    pScratch, /* Stereo destination    */
148    NumSamples); /* Number of samples     */
149
150    /*
151     * Convert 32-bit samples to 16-bit and saturate
152     * (Not required for 16-bit implemenations)
153     */
154    Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data    */
155    (LVM_INT16 *) pScratch, /* Dest. 16-bit data     */
156    (LVM_INT16) (2 * NumSamples), /* Left and right        */
157    LVDBE_SCALESHIFT); /* Shift scale           */
158
159  }
160
161  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
162  if ((pInstance->Params.OperatingMode == LVDBE_OFF)
163      || (LVC_Mixer_GetCurrent(
164          &pInstance->pData->BypassMixer.MixerStream[1])
165          != LVC_Mixer_GetTarget(
166              &pInstance->pData->BypassMixer.MixerStream[1]))) {
167
168    /*
169     * The algorithm is disabled but volume management is required to compensate for
170     * headroom and volume (if enabled)
171     */
172    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, pInData,
173        pScratchVol, (LVM_INT16) (2 * NumSamples)); /* Left and right          */
174
175  }
176
177  /*
178   * Mix DBE processed path and bypass volume path
179   */
180  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
181      (LVM_INT16 *) pScratch, pScratchVol, pOutData,
182      (LVM_INT16) (2 * NumSamples));
183
184  return (LVDBE_SUCCESS);
185}
186#else /*BUILD_FLOAT*/
187LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
188    const LVM_FLOAT *pInData,
189    LVM_FLOAT *pOutData,
190    LVM_UINT16 NumSamples)
191{
192
193  LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
194  LVM_FLOAT *pScratch_in = (LVM_FLOAT *)pInstance->MemoryTable.Region
195  [LVDBE_MEMREGION_SCRATCH].pBaseAddress;
196  LVM_FLOAT *pScratch = pScratch_in + 2 * NumSamples;
197  LVM_FLOAT *pMono;
198  LVM_INT32 ii = 0;
199
200  /* Scratch for Volume Control starts at offset of 4*NumSamples float values from pScratch */
201  LVM_FLOAT           *pScratchVol = (LVM_FLOAT *)(&pScratch_in[4 * NumSamples]);
202//  LVM_INT16 *pScratchVol_int = (LVM_INT16 *)(pScratchVol);
203
204  /* Scratch for Mono path starts at offset of 6*NumSamples 32-bit values from pScratch */
205  pMono = &pScratch_in[4 * NumSamples];
206
207  /*
208   * Check the number of samples is not too large
209   */
210  if (NumSamples > pInstance->Capabilities.MaxBlockSize)
211  {
212    return(LVDBE_TOOMANYSAMPLES);
213  }
214
215  /*
216   * Convert 16-bit samples to Float
217   */
218  Copy_Float(pInData, /* Source 16-bit data    */
219      pScratch_in, /* Dest. 32-bit data     */
220      (LVM_INT16)(2 * NumSamples)); /* Left and right        */
221
222  for (ii = 0; ii < 2 * NumSamples; ii++) {
223    pScratch[ii] = pScratch_in[ii];
224  }
225  /*
226   * Check if the algorithm is enabled
227   */
228  /* DBE path is processed when DBE is ON or during On/Off transitions */
229  if ((pInstance->Params.OperatingMode == LVDBE_ON)||
230      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
231          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
232  {
233
234    /*
235     * Apply the high pass filter if selected
236     */
237    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
238    {
239      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
240          (LVM_FLOAT *)pScratch, /* Source               */
241          (LVM_FLOAT *)pScratch, /* Destination          */
242          (LVM_INT16)NumSamples); /* Number of samples    */
243    }
244
245    /*
246     * Create the mono stream
247     */
248    From2iToMono_Float((LVM_FLOAT *)pScratch, /* Stereo source         */
249        pMono, /* Mono destination      */
250        (LVM_INT16)NumSamples); /* Number of samples     */
251
252    /*
253     * Apply the band pass filter
254     */
255    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
256        (LVM_FLOAT *)pMono, /* Source                */
257        (LVM_FLOAT *)pMono, /* Destination           */
258        (LVM_INT16)NumSamples); /* Number of samples     */
259
260    /*
261     * Apply the AGC and mix
262     */
263    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
264        pScratch, /* Stereo source         */
265        pMono, /* Mono band pass source */
266        pScratch, /* Stereo destination    */
267        NumSamples); /* Number of samples     */
268
269    for (ii = 0; ii < 2 * NumSamples; ii++) {
270      //TODO: replace with existing clamping function
271      if(pScratch[ii] < -1.0) {
272        pScratch[ii] = -1.0;
273      } else if(pScratch[ii] > 1.0) {
274        pScratch[ii] = 1.0;
275      }
276    }
277  }
278
279  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
280  if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
281      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
282          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
283  {
284
285    /*
286     * The algorithm is disabled but volume management is required to compensate for
287     * headroom and volume (if enabled)
288     */
289    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
290        pScratch_in,
291        pScratchVol,
292        (LVM_INT16)(2 * NumSamples)); /* Left and right */
293  }
294
295  /*
296   * Mix DBE processed path and bypass volume path
297   */
298  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
299      pScratch,
300      pScratchVol,
301      pOutData,
302      (LVM_INT16)(2 * NumSamples));
303
304  return(LVDBE_SUCCESS);
305}
306#endif
307