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#ifdef BUILD_FLOAT 61LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance, 62 const LVM_FLOAT *pInData, 63 LVM_FLOAT *pOutData, 64 LVM_UINT16 NumSamples) 65{ 66 67 LVM_UINT16 i; 68 Biquad_FLOAT_Instance_t *pBiquad; 69 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; 70 LVM_FLOAT *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 ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0)) 81 { 82 return LVEQNB_ALIGNMENTERROR; 83 } 84 85 pScratch = (LVM_FLOAT *)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 * Copy input data in to scratch buffer 99 */ 100 101 Copy_Float((LVM_FLOAT *)pInData, /* Source */ 102 pScratch, /* Destination */ 103 (LVM_INT16)(2 * NumSamples)); /* Left and Right */ 104 /* 105 * For each section execte the filter unless the gain is 0dB 106 */ 107 if (pInstance->NBands != 0) 108 { 109 for (i = 0; i < pInstance->NBands; i++) 110 { 111 /* 112 * Check if band is non-zero dB gain 113 */ 114 if (pInstance->pBandDefinitions[i].Gain != 0) 115 { 116 /* 117 * Get the address of the biquad instance 118 */ 119 pBiquad = &pInstance->pEQNB_FilterState_Float[i]; 120 121 122 /* 123 * Select single or double precision as required 124 */ 125 switch (pInstance->pBiquadType[i]) 126 { 127 case LVEQNB_SinglePrecision_Float: 128 { 129 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad, 130 (LVM_FLOAT *)pScratch, 131 (LVM_FLOAT *)pScratch, 132 (LVM_INT16)NumSamples); 133 break; 134 } 135 default: 136 break; 137 } 138 } 139 } 140 } 141 142 143 if(pInstance->bInOperatingModeTransition == LVM_TRUE){ 144 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer, 145 (LVM_FLOAT *)pScratch, 146 (LVM_FLOAT *)pInData, 147 (LVM_FLOAT *)pScratch, 148 (LVM_INT16)(2 * NumSamples)); 149 Copy_Float((LVM_FLOAT*)pScratch, /* Source */ 150 pOutData, /* Destination */ 151 (LVM_INT16)(2 * NumSamples)); /* Left and Right samples */ 152 } 153 else{ 154 Copy_Float(pScratch, /* Source */ 155 pOutData, /* Destination */ 156 (LVM_INT16 )(2 * NumSamples)); /* Left and Right */ 157 } 158 } 159 else 160 { 161 /* 162 * Mode is OFF so copy the data if necessary 163 */ 164 if (pInData != pOutData) 165 { 166 Copy_Float(pInData, /* Source */ 167 pOutData, /* Destination */ 168 (LVM_INT16)(2 * NumSamples)); /* Left and Right samples */ 169 } 170 } 171 return(LVEQNB_SUCCESS); 172 173} 174#else 175LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance, 176 const LVM_INT16 *pInData, 177 LVM_INT16 *pOutData, 178 LVM_UINT16 NumSamples) 179{ 180 181 LVM_UINT16 i; 182 Biquad_Instance_t *pBiquad; 183 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; 184 LVM_INT32 *pScratch; 185 186 187 /* Check for NULL pointers */ 188 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL)) 189 { 190 return LVEQNB_NULLADDRESS; 191 } 192 193 /* Check if the input and output data buffers are 32-bit aligned */ 194 if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0)) 195 { 196 return LVEQNB_ALIGNMENTERROR; 197 } 198 199 pScratch = (LVM_INT32 *)pInstance->pFastTemporary; 200 201 /* 202 * Check the number of samples is not too large 203 */ 204 if (NumSamples > pInstance->Capabilities.MaxBlockSize) 205 { 206 return(LVEQNB_TOOMANYSAMPLES); 207 } 208 209 if (pInstance->Params.OperatingMode == LVEQNB_ON) 210 { 211 /* 212 * Convert from 16-bit to 32-bit 213 */ 214 Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */ 215 pScratch, /* Destination */ 216 (LVM_INT16)(2*NumSamples), /* Left and Right */ 217 SHIFT); /* Scaling shift */ 218 219 /* 220 * For each section execte the filter unless the gain is 0dB 221 */ 222 if (pInstance->NBands != 0) 223 { 224 for (i=0; i<pInstance->NBands; i++) 225 { 226 /* 227 * Check if band is non-zero dB gain 228 */ 229 if (pInstance->pBandDefinitions[i].Gain != 0) 230 { 231 /* 232 * Get the address of the biquad instance 233 */ 234 pBiquad = &pInstance->pEQNB_FilterState[i]; 235 236 237 /* 238 * Select single or double precision as required 239 */ 240 switch (pInstance->pBiquadType[i]) 241 { 242 case LVEQNB_SinglePrecision: 243 { 244 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad, 245 (LVM_INT32 *)pScratch, 246 (LVM_INT32 *)pScratch, 247 (LVM_INT16)NumSamples); 248 break; 249 } 250 251 case LVEQNB_DoublePrecision: 252 { 253 PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad, 254 (LVM_INT32 *)pScratch, 255 (LVM_INT32 *)pScratch, 256 (LVM_INT16)NumSamples); 257 break; 258 } 259 default: 260 break; 261 } 262 } 263 } 264 } 265 266 267 if(pInstance->bInOperatingModeTransition == LVM_TRUE){ 268 /* 269 * Convert from 32-bit to 16- bit and saturate 270 */ 271 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */ 272 (LVM_INT16 *)pScratch, /* Destination */ 273 (LVM_INT16)(2*NumSamples), /* Left and Right */ 274 SHIFT); /* Scaling shift */ 275 276 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer, 277 (LVM_INT16 *)pScratch, 278 (LVM_INT16 *)pInData, 279 (LVM_INT16 *)pScratch, 280 (LVM_INT16)(2*NumSamples)); 281 282 Copy_16((LVM_INT16*)pScratch, /* Source */ 283 pOutData, /* Destination */ 284 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */ 285 } 286 else{ 287 288 /* 289 * Convert from 32-bit to 16- bit and saturate 290 */ 291 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */ 292 pOutData, /* Destination */ 293 (LVM_INT16 )(2*NumSamples), /* Left and Right */ 294 SHIFT); /* Scaling shift */ 295 } 296 } 297 else 298 { 299 /* 300 * Mode is OFF so copy the data if necessary 301 */ 302 if (pInData != pOutData) 303 { 304 Copy_16(pInData, /* Source */ 305 pOutData, /* Destination */ 306 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */ 307 } 308 } 309 310 311 312 return(LVEQNB_SUCCESS); 313 314} 315#endif