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