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 "LVEQNB.h"
25 #include "LVEQNB_Private.h"
26 #include "VectorArithmetic.h"
27 #include "BIQUAD.h"
28
29 #include <log/log.h>
30
31 /****************************************************************************************/
32 /* */
33 /* Defines */
34 /* */
35 /****************************************************************************************/
36
37 #define SHIFT 13
38
39 /****************************************************************************************/
40 /* */
41 /* FUNCTION: LVEQNB_Process */
42 /* */
43 /* DESCRIPTION: */
44 /* Process function for the N-Band Equaliser module. */
45 /* */
46 /* PARAMETERS: */
47 /* hInstance Instance handle */
48 /* pInData Pointer to the input data */
49 /* pOutData Pointer to the output data */
50 /* NumSamples Number of samples in the input buffer */
51 /* */
52 /* RETURNS: */
53 /* LVEQNB_SUCCESS Succeeded */
54 /* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */
55 /* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */
56 /* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
57 /* */
58 /* NOTES: */
59 /* */
60 /****************************************************************************************/
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,const LVM_UINT16 NrFrames)61 LVEQNB_ReturnStatus_en LVEQNB_Process(
62 LVEQNB_Handle_t hInstance, const LVM_FLOAT* pInData, LVM_FLOAT* pOutData,
63 const LVM_UINT16 NrFrames) { // updated to use samples = frames * channels.
64 LVEQNB_Instance_t* pInstance = (LVEQNB_Instance_t*)hInstance;
65 const LVM_INT32 NrChannels = pInstance->Params.NrChannels;
66 const LVM_INT32 NrSamples = NrChannels * NrFrames;
67
68 /* Check for NULL pointers */
69 if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL)) {
70 return LVEQNB_NULLADDRESS;
71 }
72
73 /* Check if the input and output data buffers are 32-bit aligned */
74 if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0)) {
75 return LVEQNB_ALIGNMENTERROR;
76 }
77
78 LVM_FLOAT* const pScratch = (LVM_FLOAT*)pInstance->pFastTemporary;
79
80 /*
81 * Check the number of frames is not too large
82 */
83 if (NrFrames > pInstance->Capabilities.MaxBlockSize) {
84 return LVEQNB_TOOMANYSAMPLES;
85 }
86
87 if (pInstance->Params.OperatingMode == LVEQNB_ON) {
88 /*
89 * Copy input data in to scratch buffer
90 */
91 Copy_Float(pInData, /* Source */
92 pScratch, /* Destination */
93 (LVM_INT16)NrSamples);
94
95 /*
96 * For each section execte the filter unless the gain is 0dB
97 */
98 if (pInstance->NBands != 0) {
99 for (LVM_UINT16 i = 0; i < pInstance->NBands; i++) {
100 /*
101 * Check if band is non-zero dB gain
102 */
103 if (pInstance->pBandDefinitions[i].Gain != 0) {
104 /*
105 * Select single or double precision as required
106 */
107 switch (pInstance->pBiquadType[i]) {
108 case LVEQNB_SinglePrecision_Float: {
109 LVM_FLOAT* pTemp = pScratch + NrSamples;
110 pInstance->eqBiquad[i].process(pTemp, pScratch, NrFrames);
111 const auto gain = pInstance->gain[i];
112 for (unsigned j = 0; j < NrSamples; ++j) {
113 pScratch[j] += pTemp[j] * gain;
114 }
115 break;
116 }
117 default:
118 break;
119 }
120 }
121 }
122 }
123
124 if (pInstance->bInOperatingModeTransition == LVM_TRUE) {
125 LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->BypassMixer, pScratch, pInData, pScratch,
126 (LVM_INT16)NrFrames, (LVM_INT16)NrChannels);
127 // duplicate with else clause(s)
128 Copy_Float(pScratch, /* Source */
129 pOutData, /* Destination */
130 (LVM_INT16)NrSamples); /* All channel samples */
131 } else {
132 Copy_Float(pScratch, /* Source */
133 pOutData, /* Destination */
134 (LVM_INT16)NrSamples); /* All channel samples */
135 }
136 } else {
137 /*
138 * Mode is OFF so copy the data if necessary
139 */
140 if (pInData != pOutData) {
141 Copy_Float(pInData, /* Source */
142 pOutData, /* Destination */
143 (LVM_INT16)NrSamples); /* All channel samples */
144 }
145 }
146 return LVEQNB_SUCCESS;
147 }
148