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 30 /****************************************************************************************/ 31 /* */ 32 /* Defines */ 33 /* */ 34 /****************************************************************************************/ 35 36 #define SHIFT 13 37 38 /****************************************************************************************/ 39 /* */ 40 /* FUNCTION: LVEQNB_Process */ 41 /* */ 42 /* DESCRIPTION: */ 43 /* Process function for the N-Band Equaliser module. */ 44 /* */ 45 /* PARAMETERS: */ 46 /* hInstance Instance handle */ 47 /* pInData Pointer to the input data */ 48 /* pOutData Pointer to the output data */ 49 /* NumSamples Number of samples in the input buffer */ 50 /* */ 51 /* RETURNS: */ 52 /* LVEQNB_SUCCESS Succeeded */ 53 /* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */ 54 /* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */ 55 /* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */ 56 /* */ 57 /* NOTES: */ 58 /* */ 59 /****************************************************************************************/ 60 61 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance, 62 const LVM_INT16 *pInData, 63 LVM_INT16 *pOutData, 64 LVM_UINT16 NumSamples) 65 { 66 67 LVM_UINT16 i; 68 Biquad_Instance_t *pBiquad; 69 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; 70 LVM_INT32 *pScratch; 71 72 73 /* Check for NULL pointers */ 74 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL)) 75 { 76 return LVEQNB_NULLADDRESS; 77 } 78 79 /* Check if the input and output data buffers are 32-bit aligned */ 80 if ((((LVM_INT32)pInData % 4) != 0) || (((LVM_INT32)pOutData % 4) != 0)) 81 { 82 return LVEQNB_ALIGNMENTERROR; 83 } 84 85 pScratch = (LVM_INT32 *)pInstance->pFastTemporary; 86 87 /* 88 * Check the number of samples is not too large 89 */ 90 if (NumSamples > pInstance->Capabilities.MaxBlockSize) 91 { 92 return(LVEQNB_TOOMANYSAMPLES); 93 } 94 95 if (pInstance->Params.OperatingMode == LVEQNB_ON) 96 { 97 /* 98 * Convert from 16-bit to 32-bit 99 */ 100 Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */ 101 pScratch, /* Destination */ 102 (LVM_INT16)(2*NumSamples), /* Left and Right */ 103 SHIFT); /* Scaling shift */ 104 105 /* 106 * For each section execte the filter unless the gain is 0dB 107 */ 108 if (pInstance->NBands != 0) 109 { 110 for (i=0; i<pInstance->NBands; i++) 111 { 112 /* 113 * Check if band is non-zero dB gain 114 */ 115 if (pInstance->pBandDefinitions[i].Gain != 0) 116 { 117 /* 118 * Get the address of the biquad instance 119 */ 120 pBiquad = &pInstance->pEQNB_FilterState[i]; 121 122 123 /* 124 * Select single or double precision as required 125 */ 126 switch (pInstance->pBiquadType[i]) 127 { 128 case LVEQNB_SinglePrecision: 129 { 130 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad, 131 (LVM_INT32 *)pScratch, 132 (LVM_INT32 *)pScratch, 133 (LVM_INT16)NumSamples); 134 break; 135 } 136 137 case LVEQNB_DoublePrecision: 138 { 139 PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad, 140 (LVM_INT32 *)pScratch, 141 (LVM_INT32 *)pScratch, 142 (LVM_INT16)NumSamples); 143 break; 144 } 145 default: 146 break; 147 } 148 } 149 } 150 } 151 152 153 if(pInstance->bInOperatingModeTransition == LVM_TRUE){ 154 /* 155 * Convert from 32-bit to 16- bit and saturate 156 */ 157 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */ 158 (LVM_INT16 *)pScratch, /* Destination */ 159 (LVM_INT16)(2*NumSamples), /* Left and Right */ 160 SHIFT); /* Scaling shift */ 161 162 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer, 163 (LVM_INT16 *)pScratch, 164 (LVM_INT16 *)pInData, 165 (LVM_INT16 *)pScratch, 166 (LVM_INT16)(2*NumSamples)); 167 168 Copy_16((LVM_INT16*)pScratch, /* Source */ 169 pOutData, /* Destination */ 170 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */ 171 } 172 else{ 173 174 /* 175 * Convert from 32-bit to 16- bit and saturate 176 */ 177 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */ 178 pOutData, /* Destination */ 179 (LVM_INT16 )(2*NumSamples), /* Left and Right */ 180 SHIFT); /* Scaling shift */ 181 } 182 } 183 else 184 { 185 /* 186 * Mode is OFF so copy the data if necessary 187 */ 188 if (pInData != pOutData) 189 { 190 Copy_16(pInData, /* Source */ 191 pOutData, /* Destination */ 192 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */ 193 } 194 } 195 196 197 198 return(LVEQNB_SUCCESS); 199 200 } 201