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 "LVREV_Private.h" 24 #include "VectorArithmetic.h" 25 26 27 /****************************************************************************************/ 28 /* */ 29 /* FUNCTION: LVREV_Process */ 30 /* */ 31 /* DESCRIPTION: */ 32 /* Process function for the LVREV module. */ 33 /* */ 34 /* PARAMETERS: */ 35 /* hInstance Instance handle */ 36 /* pInData Pointer to the input data */ 37 /* pOutData Pointer to the output data */ 38 /* NumSamples Number of samples in the input buffer */ 39 /* */ 40 /* RETURNS: */ 41 /* LVREV_Success Succeeded */ 42 /* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */ 43 /* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */ 44 /* */ 45 /* NOTES: */ 46 /* 1. The input and output buffers must be 32-bit aligned */ 47 /* */ 48 /****************************************************************************************/ 49 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance, 50 const LVM_INT32 *pInData, 51 LVM_INT32 *pOutData, 52 const LVM_UINT16 NumSamples) 53 { 54 LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance; 55 LVM_INT32 *pInput = (LVM_INT32 *)pInData; 56 LVM_INT32 *pOutput = pOutData; 57 LVM_INT32 SamplesToProcess, RemainingSamples; 58 LVM_INT32 format = 1; 59 60 /* 61 * Check for error conditions 62 */ 63 64 /* Check for NULL pointers */ 65 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL)) 66 { 67 return LVREV_NULLADDRESS; 68 } 69 70 /* 71 * Apply the new controls settings if required 72 */ 73 if(pLVREV_Private->bControlPending == LVM_TRUE) 74 { 75 LVREV_ReturnStatus_en errorCode; 76 77 /* 78 * Clear the pending flag and update the control settings 79 */ 80 pLVREV_Private->bControlPending = LVM_FALSE; 81 82 errorCode = LVREV_ApplyNewSettings (pLVREV_Private); 83 84 if(errorCode != LVREV_SUCCESS) 85 { 86 return errorCode; 87 } 88 } 89 90 /* 91 * Trap the case where the number of samples is zero. 92 */ 93 if (NumSamples == 0) 94 { 95 return LVREV_SUCCESS; 96 } 97 98 /* 99 * If OFF copy and reformat the data as necessary 100 */ 101 if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF) 102 { 103 if(pInput != pOutput) 104 { 105 /* 106 * Copy the data to the output buffer, convert to stereo is required 107 */ 108 109 if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){ 110 MonoTo2I_32(pInput, pOutput, NumSamples); 111 } else { 112 Copy_16((LVM_INT16 *)pInput, 113 (LVM_INT16 *)pOutput, 114 (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo 115 } 116 } 117 118 return LVREV_SUCCESS; 119 } 120 121 RemainingSamples = (LVM_INT32)NumSamples; 122 123 if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO) 124 { 125 format = 2; 126 } 127 128 while (RemainingSamples!=0) 129 { 130 /* 131 * Process the data 132 */ 133 134 if(RemainingSamples > pLVREV_Private->MaxBlkLen) 135 { 136 SamplesToProcess = pLVREV_Private->MaxBlkLen; 137 RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess); 138 } 139 else 140 { 141 SamplesToProcess = RemainingSamples; 142 RemainingSamples = 0; 143 } 144 145 ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess); 146 147 pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format)); 148 pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2)); // Always stereo output 149 } 150 151 return LVREV_SUCCESS; 152 } 153 154 155 156 /****************************************************************************************/ 157 /* */ 158 /* FUNCTION: ReverbBlock */ 159 /* */ 160 /* DESCRIPTION: */ 161 /* Process function for the LVREV module. */ 162 /* */ 163 /* PARAMETERS: */ 164 /* hInstance Instance handle */ 165 /* pInData Pointer to the input data */ 166 /* pOutData Pointer to the output data */ 167 /* NumSamples Number of samples in the input buffer */ 168 /* */ 169 /* RETURNS: */ 170 /* LVREV_Success Succeeded */ 171 /* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */ 172 /* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */ 173 /* */ 174 /* NOTES: */ 175 /* 1. The input and output buffers must be 32-bit aligned */ 176 /* */ 177 /****************************************************************************************/ 178 179 void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples) 180 { 181 LVM_INT16 j, size; 182 LVM_INT32 *pDelayLine; 183 LVM_INT32 *pDelayLineInput = pPrivate->pScratch; 184 LVM_INT32 *pScratch = pPrivate->pScratch; 185 LVM_INT32 *pIn; 186 LVM_INT32 *pTemp = pPrivate->pInputSave; 187 LVM_INT32 NumberOfDelayLines; 188 189 /****************************************************************************** 190 * All calculations will go into the buffer pointed to by pTemp, this will * 191 * then be mixed with the original input to create the final output. * 192 * * 193 * When INPLACE processing is selected this must be a temporary buffer and * 194 * hence this is the worst case, so for simplicity this will ALWAYS be so * 195 * * 196 * The input buffer will remain untouched until the output of the mixer if * 197 * INPLACE processing is selected. * 198 * * 199 * The temp buffer will always be NumSamples in size regardless of MONO or * 200 * STEREO input. In the case of stereo input all processing is done in MONO * 201 * and the final output is converted to STEREO after the mixer * 202 ******************************************************************************/ 203 204 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 ) 205 { 206 NumberOfDelayLines = 4; 207 } 208 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 ) 209 { 210 NumberOfDelayLines = 2; 211 } 212 else 213 { 214 NumberOfDelayLines = 1; 215 } 216 217 if(pPrivate->CurrentParams.SourceFormat == LVM_MONO) 218 { 219 pIn = pInput; 220 } 221 else 222 { 223 /* 224 * Stereo to mono conversion 225 */ 226 227 From2iToMono_32( pInput, 228 pTemp, 229 (LVM_INT16)NumSamples); 230 231 pIn = pTemp; 232 } 233 234 Mult3s_32x16(pIn, 235 (LVM_INT16)LVREV_HEADROOM, 236 pTemp, 237 (LVM_INT16)NumSamples); 238 239 /* 240 * High pass filter 241 */ 242 FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs, 243 pTemp, 244 pTemp, 245 (LVM_INT16)NumSamples); 246 /* 247 * Low pass filter 248 */ 249 FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs, 250 pTemp, 251 pTemp, 252 (LVM_INT16)NumSamples); 253 254 /* 255 * Process all delay lines 256 */ 257 258 for(j = 0; j < NumberOfDelayLines; j++) 259 { 260 pDelayLine = pPrivate->pScratchDelayLine[j]; 261 262 /* 263 * All-pass filter with pop and click suppression 264 */ 265 /* Get the smoothed, delayed output. Put it in the output buffer */ 266 MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j], 267 pPrivate->pOffsetA[j], 268 pPrivate->pOffsetB[j], 269 pDelayLine, 270 (LVM_INT16)NumSamples); 271 /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */ 272 Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples], 273 (LVM_INT16 *)pPrivate->pDelay_T[j], 274 (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1)); /* 32-bit data */ 275 /* Apply the smoothed feedback and save to fixed delay input (currently empty) */ 276 MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j], 277 pDelayLine, 278 &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 279 (LVM_INT16)NumSamples); 280 /* Sum into the AP delay line */ 281 Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 282 -0x7fff, /* Invert since the feedback coefficient is negative */ 283 &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples], 284 (LVM_INT16)NumSamples); 285 /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */ 286 MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j], 287 &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples], 288 &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 289 (LVM_INT16)NumSamples); 290 /* Sum into the AP output */ 291 Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 292 0x7fff, 293 pDelayLine, 294 (LVM_INT16)NumSamples); 295 296 /* 297 * Feedback gain 298 */ 299 MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples); 300 301 /* 302 * Low pass filter 303 */ 304 FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j], 305 pDelayLine, 306 pDelayLine, 307 (LVM_INT16)NumSamples); 308 } 309 310 /* 311 * Apply rotation matrix and delay samples 312 */ 313 for(j = 0; j < NumberOfDelayLines; j++) 314 { 315 316 Copy_16( (LVM_INT16*)(pTemp), 317 (LVM_INT16*)(pDelayLineInput), 318 (LVM_INT16)(NumSamples << 1)); 319 320 /* 321 * Rotation matrix mix 322 */ 323 switch(j) 324 { 325 case 3: 326 /* 327 * Add delay line 1 and 2 contribution 328 */ 329 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 330 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 331 332 break; 333 case 2: 334 335 /* 336 * Add delay line 0 and 3 contribution 337 */ 338 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 339 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 340 341 break; 342 case 1: 343 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 344 { 345 /* 346 * Add delay line 0 and 3 contribution 347 */ 348 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 349 Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples); 350 351 } 352 else 353 { 354 /* 355 * Add delay line 0 and 1 contribution 356 */ 357 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 358 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 359 360 } 361 break; 362 case 0: 363 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 364 { 365 /* 366 * Add delay line 1 and 2 contribution 367 */ 368 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 369 Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples); 370 371 } 372 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2) 373 { 374 /* 375 * Add delay line 0 and 1 contribution 376 */ 377 Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples); 378 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 379 380 } 381 else 382 { 383 /* 384 * Add delay line 0 contribution 385 */ 386 387 /* SOURCE DESTINATION*/ 388 Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples); 389 } 390 break; 391 default: 392 break; 393 } 394 395 /* 396 * Delay samples 397 */ 398 Copy_16((LVM_INT16 *)pDelayLineInput, 399 (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 400 (LVM_INT16)(NumSamples << 1)); /* 32-bit data */ 401 402 } 403 404 405 /* 406 * Create stereo output 407 */ 408 switch(pPrivate->InstanceParams.NumDelays) 409 { 410 case LVREV_DELAYLINES_4: 411 Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], 412 pPrivate->pScratchDelayLine[0], 413 (LVM_INT16)NumSamples); 414 Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], 415 pPrivate->pScratchDelayLine[1], 416 (LVM_INT16)NumSamples); 417 418 419 JoinTo2i_32x32(pPrivate->pScratchDelayLine[0], 420 pPrivate->pScratchDelayLine[1], 421 pTemp, 422 (LVM_INT16)NumSamples); 423 424 425 break; 426 case LVREV_DELAYLINES_2: 427 428 Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1], 429 (LVM_INT16*)pScratch, 430 (LVM_INT16)(NumSamples << 1)); 431 432 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], 433 -0x8000, 434 pScratch, 435 (LVM_INT16)NumSamples); 436 437 Add2_Sat_32x32(pPrivate->pScratchDelayLine[1], 438 pPrivate->pScratchDelayLine[0], 439 (LVM_INT16)NumSamples); 440 441 442 JoinTo2i_32x32(pPrivate->pScratchDelayLine[0], 443 pScratch, 444 pTemp, 445 (LVM_INT16)NumSamples); 446 break; 447 case LVREV_DELAYLINES_1: 448 MonoTo2I_32(pPrivate->pScratchDelayLine[0], 449 pTemp, 450 (LVM_INT16)NumSamples); 451 break; 452 default: 453 break; 454 } 455 456 457 /* 458 * Dry/wet mixer 459 */ 460 461 size = (LVM_INT16)(NumSamples << 1); 462 MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer, 463 pTemp, 464 pTemp, 465 pOutput, 466 size); 467 468 /* Apply Gain*/ 469 470 Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT, 471 pOutput, 472 pOutput, 473 size); 474 475 MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer, 476 pOutput, 477 pOutput, 478 size); 479 480 return; 481 } 482 483 484 /* End of file */ 485 486