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 #include <audio_utils/BiquadFilter.h>
24
25 #include <string.h> // memset
26 #include "LVDBE.h"
27 #include "LVDBE_Private.h"
28 #include "VectorArithmetic.h"
29 #include "AGC.h"
30 #include "LVDBE_Coeffs.h" /* Filter coefficients */
31 #include <log/log.h>
32
33 /********************************************************************************************/
34 /* */
35 /* FUNCTION: LVDBE_Process */
36 /* */
37 /* DESCRIPTION: */
38 /* Process function for the Bass Enhancement module. */
39 /* */
40 /* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */
41 /* format is not supported, the calling routine must convert the mono stream to */
42 /* mono-in-stereo. */
43 /* ___________ */
44 /* ________ | | ________ */
45 /* | | _____ |------------------------->| | | | */
46 /* | 16-bit | | | | ________ | | | 32-bit | */
47 /* -+-->| to |-->| HPF |--| | | _____ | AGC Mixer |-->| to |--| */
48 /* | | 32-bit | |_____| | | Stereo | | | | | | 16-bit | | */
49 /* | |________| |-->| to |-->| BPF |-->| | |________| 0 */
50 /* | | Mono | |_____| |___________| \--> */
51 /* | |________| */
52 /* | _________ 0 */
53 /* | | | | */
54 /* |----------------------------------------------------| Volume |-----------------| */
55 /* | Control | */
56 /* |_________| */
57 /* */
58 /* PARAMETERS: */
59 /* hInstance Instance handle */
60 /* pInData Pointer to the input data */
61 /* pOutData Pointer to the output data */
62 /* NumSamples Number of samples in the input buffer */
63 /* */
64 /* RETURNS: */
65 /* LVDBE_SUCCESS Succeeded */
66 /* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
67 /* */
68 /* NOTES: */
69 /* 1. The input and output data must be 32-bit format. The input is scaled by a shift */
70 /* when converting from 16-bit format, this scaling allows for internal headroom in the */
71 /* bass enhancement algorithm. */
72 /* 2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with */
73 /* the headroom loss. This headroom loss is compensated in the volume control so the */
74 /* overall end to end gain is odB. */
75 /* */
76 /********************************************************************************************/
LVDBE_Process(LVDBE_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,const LVM_UINT16 NrFrames)77 LVDBE_ReturnStatus_en LVDBE_Process(
78 LVDBE_Handle_t hInstance, const LVM_FLOAT* pInData, LVM_FLOAT* pOutData,
79 const LVM_UINT16 NrFrames) // updated to use samples = frames * channels.
80 {
81 LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
82 const LVM_INT32 NrChannels = pInstance->Params.NrChannels;
83 const LVM_INT32 NrSamples = NrChannels * NrFrames;
84
85 /* Space to store DBE path computation */
86 LVM_FLOAT* const pScratch = (LVM_FLOAT*)pInstance->pScratch;
87
88 /*
89 * Scratch for Mono path starts at offset of
90 * NrSamples float values from pScratch.
91 */
92 LVM_FLOAT* const pMono = pScratch + NrSamples;
93
94 /*
95 * TRICKY: pMono is used and discarded by the DBE path.
96 * so it is available for use for the pScratchVol
97 * path which is computed afterwards.
98 *
99 * Space to store Volume Control path computation.
100 * This is identical to pMono (see TRICKY comment).
101 */
102 LVM_FLOAT* const pScratchVol = pMono;
103
104 /*
105 * Check the number of frames is not too large
106 */
107 if (NrFrames > pInstance->Capabilities.MaxBlockSize) {
108 return LVDBE_TOOMANYSAMPLES;
109 }
110
111 /*
112 * Check if the algorithm is enabled
113 */
114 /* DBE path is processed when DBE is ON or during On/Off transitions */
115 if ((pInstance->Params.OperatingMode == LVDBE_ON) ||
116 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0]) !=
117 LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0]))) {
118 // make copy of input data
119 Copy_Float(pInData, pScratch, (LVM_INT16)NrSamples);
120
121 /*
122 * Apply the high pass filter if selected
123 */
124 if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
125 pInstance->pHPFBiquad->process(pScratch, pScratch, NrFrames);
126 }
127
128 /*
129 * Create the mono stream
130 */
131 FromMcToMono_Float(pScratch, /* Source */
132 pMono, /* Mono destination */
133 (LVM_INT16)NrFrames, /* Number of frames */
134 (LVM_INT16)NrChannels);
135
136 /*
137 * Apply the band pass filter
138 */
139 pInstance->pBPFBiquad->process(pMono, pMono, NrFrames);
140
141 /*
142 * Apply the AGC and mix
143 */
144 AGC_MIX_VOL_Mc1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
145 pScratch, /* Source */
146 pMono, /* Mono band pass source */
147 pScratch, /* Destination */
148 NrFrames, /* Number of frames */
149 NrChannels); /* Number of channels */
150 } else {
151 // clear DBE processed path
152 memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
153 }
154
155 /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
156 if ((pInstance->Params.OperatingMode == LVDBE_OFF) ||
157 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1]) !=
158 LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1]))) {
159 /*
160 * The algorithm is disabled but volume management is required to compensate for
161 * headroom and volume (if enabled)
162 */
163 LVC_MixSoft_Mc_D16C31_SAT(&pInstance->pData->BypassVolume, pInData, pScratchVol,
164 (LVM_INT16)NrFrames, (LVM_INT16)NrChannels);
165 } else {
166 // clear bypass volume path
167 memset(pScratchVol, 0, sizeof(*pScratchVol) * NrSamples);
168 }
169
170 /*
171 * Mix DBE processed path and bypass volume path
172 */
173 LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->pData->BypassMixer, pScratch, pScratchVol, pOutData,
174 (LVM_INT16)NrFrames, (LVM_INT16)NrChannels);
175 return LVDBE_SUCCESS;
176 }
177