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 #ifdef BUILD_FLOAT 50 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance, 51 const LVM_FLOAT *pInData, 52 LVM_FLOAT *pOutData, 53 const LVM_UINT16 NumSamples) 54 #else 55 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance, 56 const LVM_INT32 *pInData, 57 LVM_INT32 *pOutData, 58 const LVM_UINT16 NumSamples) 59 #endif 60 { 61 LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance; 62 #ifdef BUILD_FLOAT 63 LVM_FLOAT *pInput = (LVM_FLOAT *)pInData; 64 LVM_FLOAT *pOutput = pOutData; 65 #else 66 LVM_INT32 *pInput = (LVM_INT32 *)pInData; 67 LVM_INT32 *pOutput = pOutData; 68 #endif 69 LVM_INT32 SamplesToProcess, RemainingSamples; 70 LVM_INT32 format = 1; 71 72 /* 73 * Check for error conditions 74 */ 75 76 /* Check for NULL pointers */ 77 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL)) 78 { 79 return LVREV_NULLADDRESS; 80 } 81 82 /* 83 * Apply the new controls settings if required 84 */ 85 if(pLVREV_Private->bControlPending == LVM_TRUE) 86 { 87 LVREV_ReturnStatus_en errorCode; 88 89 /* 90 * Clear the pending flag and update the control settings 91 */ 92 pLVREV_Private->bControlPending = LVM_FALSE; 93 94 errorCode = LVREV_ApplyNewSettings (pLVREV_Private); 95 96 if(errorCode != LVREV_SUCCESS) 97 { 98 return errorCode; 99 } 100 } 101 102 /* 103 * Trap the case where the number of samples is zero. 104 */ 105 if (NumSamples == 0) 106 { 107 return LVREV_SUCCESS; 108 } 109 110 /* 111 * If OFF copy and reformat the data as necessary 112 */ 113 if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF) 114 { 115 if(pInput != pOutput) 116 { 117 /* 118 * Copy the data to the output buffer, convert to stereo is required 119 */ 120 #ifndef BUILD_FLOAT 121 if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){ 122 MonoTo2I_32(pInput, pOutput, NumSamples); 123 } else { 124 Copy_16((LVM_INT16 *)pInput, 125 (LVM_INT16 *)pOutput, 126 (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo 127 } 128 #else 129 if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){ 130 MonoTo2I_Float(pInput, pOutput, NumSamples); 131 } else { 132 Copy_Float(pInput, 133 pOutput, 134 (LVM_INT16)(NumSamples << 1)); // 32 bit data, stereo 135 } 136 #endif 137 } 138 139 return LVREV_SUCCESS; 140 } 141 142 RemainingSamples = (LVM_INT32)NumSamples; 143 144 if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO) 145 { 146 format = 2; 147 } 148 149 while (RemainingSamples!=0) 150 { 151 /* 152 * Process the data 153 */ 154 155 if(RemainingSamples > pLVREV_Private->MaxBlkLen) 156 { 157 SamplesToProcess = pLVREV_Private->MaxBlkLen; 158 RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess); 159 } 160 else 161 { 162 SamplesToProcess = RemainingSamples; 163 RemainingSamples = 0; 164 } 165 166 ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess); 167 #ifdef BUILD_FLOAT 168 pInput = (LVM_FLOAT *)(pInput + (SamplesToProcess * format)); 169 pOutput = (LVM_FLOAT *)(pOutput + (SamplesToProcess * 2)); // Always stereo output 170 #else 171 pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format)); 172 pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2)); 173 #endif 174 } 175 176 return LVREV_SUCCESS; 177 } 178 179 180 181 /****************************************************************************************/ 182 /* */ 183 /* FUNCTION: ReverbBlock */ 184 /* */ 185 /* DESCRIPTION: */ 186 /* Process function for the LVREV module. */ 187 /* */ 188 /* PARAMETERS: */ 189 /* hInstance Instance handle */ 190 /* pInData Pointer to the input data */ 191 /* pOutData Pointer to the output data */ 192 /* NumSamples Number of samples in the input buffer */ 193 /* */ 194 /* RETURNS: */ 195 /* LVREV_Success Succeeded */ 196 /* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */ 197 /* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */ 198 /* */ 199 /* NOTES: */ 200 /* 1. The input and output buffers must be 32-bit aligned */ 201 /* */ 202 /****************************************************************************************/ 203 #ifndef BUILD_FLOAT 204 void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples) 205 { 206 LVM_INT16 j, size; 207 LVM_INT32 *pDelayLine; 208 LVM_INT32 *pDelayLineInput = pPrivate->pScratch; 209 LVM_INT32 *pScratch = pPrivate->pScratch; 210 LVM_INT32 *pIn; 211 LVM_INT32 *pTemp = pPrivate->pInputSave; 212 LVM_INT32 NumberOfDelayLines; 213 214 /****************************************************************************** 215 * All calculations will go into the buffer pointed to by pTemp, this will * 216 * then be mixed with the original input to create the final output. * 217 * * 218 * When INPLACE processing is selected this must be a temporary buffer and * 219 * hence this is the worst case, so for simplicity this will ALWAYS be so * 220 * * 221 * The input buffer will remain untouched until the output of the mixer if * 222 * INPLACE processing is selected. * 223 * * 224 * The temp buffer will always be NumSamples in size regardless of MONO or * 225 * STEREO input. In the case of stereo input all processing is done in MONO * 226 * and the final output is converted to STEREO after the mixer * 227 ******************************************************************************/ 228 229 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 ) 230 { 231 NumberOfDelayLines = 4; 232 } 233 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 ) 234 { 235 NumberOfDelayLines = 2; 236 } 237 else 238 { 239 NumberOfDelayLines = 1; 240 } 241 242 if(pPrivate->CurrentParams.SourceFormat == LVM_MONO) 243 { 244 pIn = pInput; 245 } 246 else 247 { 248 /* 249 * Stereo to mono conversion 250 */ 251 252 From2iToMono_32( pInput, 253 pTemp, 254 (LVM_INT16)NumSamples); 255 256 pIn = pTemp; 257 } 258 259 Mult3s_32x16(pIn, 260 (LVM_INT16)LVREV_HEADROOM, 261 pTemp, 262 (LVM_INT16)NumSamples); 263 264 /* 265 * High pass filter 266 */ 267 FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs, 268 pTemp, 269 pTemp, 270 (LVM_INT16)NumSamples); 271 /* 272 * Low pass filter 273 */ 274 FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs, 275 pTemp, 276 pTemp, 277 (LVM_INT16)NumSamples); 278 279 /* 280 * Process all delay lines 281 */ 282 283 for(j = 0; j < NumberOfDelayLines; j++) 284 { 285 pDelayLine = pPrivate->pScratchDelayLine[j]; 286 287 /* 288 * All-pass filter with pop and click suppression 289 */ 290 /* Get the smoothed, delayed output. Put it in the output buffer */ 291 MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j], 292 pPrivate->pOffsetA[j], 293 pPrivate->pOffsetB[j], 294 pDelayLine, 295 (LVM_INT16)NumSamples); 296 /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */ 297 Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples], 298 (LVM_INT16 *)pPrivate->pDelay_T[j], 299 (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1)); /* 32-bit data */ 300 /* Apply the smoothed feedback and save to fixed delay input (currently empty) */ 301 MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j], 302 pDelayLine, 303 &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 304 (LVM_INT16)NumSamples); 305 /* Sum into the AP delay line */ 306 Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 307 -0x7fff, /* Invert since the feedback coefficient is negative */ 308 &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples], 309 (LVM_INT16)NumSamples); 310 /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */ 311 MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j], 312 &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples], 313 &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 314 (LVM_INT16)NumSamples); 315 /* Sum into the AP output */ 316 Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 317 0x7fff, 318 pDelayLine, 319 (LVM_INT16)NumSamples); 320 321 /* 322 * Feedback gain 323 */ 324 MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples); 325 326 /* 327 * Low pass filter 328 */ 329 FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j], 330 pDelayLine, 331 pDelayLine, 332 (LVM_INT16)NumSamples); 333 } 334 335 /* 336 * Apply rotation matrix and delay samples 337 */ 338 for(j = 0; j < NumberOfDelayLines; j++) 339 { 340 341 Copy_16( (LVM_INT16*)(pTemp), 342 (LVM_INT16*)(pDelayLineInput), 343 (LVM_INT16)(NumSamples << 1)); 344 345 /* 346 * Rotation matrix mix 347 */ 348 switch(j) 349 { 350 case 3: 351 /* 352 * Add delay line 1 and 2 contribution 353 */ 354 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 355 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 356 357 break; 358 case 2: 359 360 /* 361 * Add delay line 0 and 3 contribution 362 */ 363 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 364 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 365 366 break; 367 case 1: 368 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 369 { 370 /* 371 * Add delay line 0 and 3 contribution 372 */ 373 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 374 Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples); 375 376 } 377 else 378 { 379 /* 380 * Add delay line 0 and 1 contribution 381 */ 382 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 383 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 384 385 } 386 break; 387 case 0: 388 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 389 { 390 /* 391 * Add delay line 1 and 2 contribution 392 */ 393 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 394 Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples); 395 396 } 397 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2) 398 { 399 /* 400 * Add delay line 0 and 1 contribution 401 */ 402 Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples); 403 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples); 404 405 } 406 else 407 { 408 /* 409 * Add delay line 0 contribution 410 */ 411 412 /* SOURCE DESTINATION*/ 413 Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples); 414 } 415 break; 416 default: 417 break; 418 } 419 420 /* 421 * Delay samples 422 */ 423 Copy_16((LVM_INT16 *)pDelayLineInput, 424 (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples], 425 (LVM_INT16)(NumSamples << 1)); /* 32-bit data */ 426 427 } 428 429 430 /* 431 * Create stereo output 432 */ 433 switch(pPrivate->InstanceParams.NumDelays) 434 { 435 case LVREV_DELAYLINES_4: 436 Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], 437 pPrivate->pScratchDelayLine[0], 438 (LVM_INT16)NumSamples); 439 Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], 440 pPrivate->pScratchDelayLine[1], 441 (LVM_INT16)NumSamples); 442 443 444 JoinTo2i_32x32(pPrivate->pScratchDelayLine[0], 445 pPrivate->pScratchDelayLine[1], 446 pTemp, 447 (LVM_INT16)NumSamples); 448 449 450 break; 451 case LVREV_DELAYLINES_2: 452 453 Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1], 454 (LVM_INT16*)pScratch, 455 (LVM_INT16)(NumSamples << 1)); 456 457 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], 458 -0x8000, 459 pScratch, 460 (LVM_INT16)NumSamples); 461 462 Add2_Sat_32x32(pPrivate->pScratchDelayLine[1], 463 pPrivate->pScratchDelayLine[0], 464 (LVM_INT16)NumSamples); 465 466 467 JoinTo2i_32x32(pPrivate->pScratchDelayLine[0], 468 pScratch, 469 pTemp, 470 (LVM_INT16)NumSamples); 471 break; 472 case LVREV_DELAYLINES_1: 473 MonoTo2I_32(pPrivate->pScratchDelayLine[0], 474 pTemp, 475 (LVM_INT16)NumSamples); 476 break; 477 default: 478 break; 479 } 480 481 482 /* 483 * Dry/wet mixer 484 */ 485 486 size = (LVM_INT16)(NumSamples << 1); 487 MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer, 488 pTemp, 489 pTemp, 490 pOutput, 491 size); 492 493 /* Apply Gain*/ 494 495 Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT, 496 pOutput, 497 pOutput, 498 size); 499 500 MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer, 501 pOutput, 502 pOutput, 503 size); 504 505 return; 506 } 507 #else 508 void ReverbBlock(LVM_FLOAT *pInput, LVM_FLOAT *pOutput, 509 LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples) 510 { 511 LVM_INT16 j, size; 512 LVM_FLOAT *pDelayLine; 513 LVM_FLOAT *pDelayLineInput = pPrivate->pScratch; 514 LVM_FLOAT *pScratch = pPrivate->pScratch; 515 LVM_FLOAT *pIn; 516 LVM_FLOAT *pTemp = pPrivate->pInputSave; 517 LVM_INT32 NumberOfDelayLines; 518 519 /****************************************************************************** 520 * All calculations will go into the buffer pointed to by pTemp, this will * 521 * then be mixed with the original input to create the final output. * 522 * * 523 * When INPLACE processing is selected this must be a temporary buffer and * 524 * hence this is the worst case, so for simplicity this will ALWAYS be so * 525 * * 526 * The input buffer will remain untouched until the output of the mixer if * 527 * INPLACE processing is selected. * 528 * * 529 * The temp buffer will always be NumSamples in size regardless of MONO or * 530 * STEREO input. In the case of stereo input all processing is done in MONO * 531 * and the final output is converted to STEREO after the mixer * 532 ******************************************************************************/ 533 534 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 535 { 536 NumberOfDelayLines = 4; 537 } 538 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2) 539 { 540 NumberOfDelayLines = 2; 541 } 542 else 543 { 544 NumberOfDelayLines = 1; 545 } 546 547 if(pPrivate->CurrentParams.SourceFormat == LVM_MONO) 548 { 549 pIn = pInput; 550 } 551 else 552 { 553 /* 554 * Stereo to mono conversion 555 */ 556 557 From2iToMono_Float(pInput, 558 pTemp, 559 (LVM_INT16)NumSamples); 560 pIn = pTemp; 561 } 562 563 Mult3s_Float(pIn, 564 (LVM_FLOAT)LVREV_HEADROOM, 565 pTemp, 566 (LVM_INT16)NumSamples); 567 568 /* 569 * High pass filter 570 */ 571 FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs, 572 pTemp, 573 pTemp, 574 (LVM_INT16)NumSamples); 575 /* 576 * Low pass filter 577 */ 578 FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs, 579 pTemp, 580 pTemp, 581 (LVM_INT16)NumSamples); 582 583 /* 584 * Process all delay lines 585 */ 586 587 for(j = 0; j < NumberOfDelayLines; j++) 588 { 589 pDelayLine = pPrivate->pScratchDelayLine[j]; 590 591 /* 592 * All-pass filter with pop and click suppression 593 */ 594 /* Get the smoothed, delayed output. Put it in the output buffer */ 595 MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j], 596 pPrivate->pOffsetA[j], 597 pPrivate->pOffsetB[j], 598 pDelayLine, 599 (LVM_INT16)NumSamples); 600 /* Re-align the all pass filter delay buffer and copying the fixed delay data \ 601 to the AP delay in the process */ 602 Copy_Float(&pPrivate->pDelay_T[j][NumSamples], 603 pPrivate->pDelay_T[j], 604 (LVM_INT16)(pPrivate->T[j] - NumSamples)); /* 32-bit data */ 605 /* Apply the smoothed feedback and save to fixed delay input (currently empty) */ 606 MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j], 607 pDelayLine, 608 &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples], 609 (LVM_INT16)NumSamples); 610 /* Sum into the AP delay line */ 611 Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples], 612 -1.0f, /* Invert since the feedback coefficient is negative */ 613 &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples], 614 (LVM_INT16)NumSamples); 615 /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */ 616 MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j], 617 &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples], 618 &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples], 619 (LVM_INT16)NumSamples); 620 /* Sum into the AP output */ 621 Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples], 622 1.0f, 623 pDelayLine, 624 (LVM_INT16)NumSamples); 625 626 /* 627 * Feedback gain 628 */ 629 MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples); 630 631 /* 632 * Low pass filter 633 */ 634 FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j], 635 pDelayLine, 636 pDelayLine, 637 (LVM_INT16)NumSamples); 638 } 639 640 /* 641 * Apply rotation matrix and delay samples 642 */ 643 for(j = 0; j < NumberOfDelayLines; j++) 644 { 645 646 Copy_Float(pTemp, 647 pDelayLineInput, 648 (LVM_INT16)(NumSamples)); 649 /* 650 * Rotation matrix mix 651 */ 652 switch(j) 653 { 654 case 3: 655 /* 656 * Add delay line 1 and 2 contribution 657 */ 658 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f, 659 pDelayLineInput, (LVM_INT16)NumSamples); 660 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[2], -1.0f, 661 pDelayLineInput, (LVM_INT16)NumSamples); 662 663 break; 664 case 2: 665 666 /* 667 * Add delay line 0 and 3 contribution 668 */ 669 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f, 670 pDelayLineInput, (LVM_INT16)NumSamples); 671 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[3], -1.0f, 672 pDelayLineInput, (LVM_INT16)NumSamples); 673 674 break; 675 case 1: 676 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 677 { 678 /* 679 * Add delay line 0 and 3 contribution 680 */ 681 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f, 682 pDelayLineInput, (LVM_INT16)NumSamples); 683 Add2_Sat_Float(pPrivate->pScratchDelayLine[3], pDelayLineInput, 684 (LVM_INT16)NumSamples); 685 686 } 687 else 688 { 689 /* 690 * Add delay line 0 and 1 contribution 691 */ 692 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f, 693 pDelayLineInput, (LVM_INT16)NumSamples); 694 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f, 695 pDelayLineInput, (LVM_INT16)NumSamples); 696 697 } 698 break; 699 case 0: 700 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4) 701 { 702 /* 703 * Add delay line 1 and 2 contribution 704 */ 705 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f, 706 pDelayLineInput, (LVM_INT16)NumSamples); 707 Add2_Sat_Float(pPrivate->pScratchDelayLine[2], pDelayLineInput, 708 (LVM_INT16)NumSamples); 709 710 } 711 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2) 712 { 713 /* 714 * Add delay line 0 and 1 contribution 715 */ 716 Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput, 717 (LVM_INT16)NumSamples); 718 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f, 719 pDelayLineInput, (LVM_INT16)NumSamples); 720 721 } 722 else 723 { 724 /* 725 * Add delay line 0 contribution 726 */ 727 728 /* SOURCE DESTINATION*/ 729 Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput, 730 (LVM_INT16)NumSamples); 731 } 732 break; 733 default: 734 break; 735 } 736 737 /* 738 * Delay samples 739 */ 740 Copy_Float(pDelayLineInput, 741 &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples], 742 (LVM_INT16)(NumSamples)); /* 32-bit data */ 743 } 744 745 746 /* 747 * Create stereo output 748 */ 749 switch(pPrivate->InstanceParams.NumDelays) 750 { 751 case LVREV_DELAYLINES_4: 752 Add2_Sat_Float(pPrivate->pScratchDelayLine[3], 753 pPrivate->pScratchDelayLine[0], 754 (LVM_INT16)NumSamples); 755 Add2_Sat_Float(pPrivate->pScratchDelayLine[2], 756 pPrivate->pScratchDelayLine[1], 757 (LVM_INT16)NumSamples); 758 759 760 JoinTo2i_Float(pPrivate->pScratchDelayLine[0], 761 pPrivate->pScratchDelayLine[1], 762 pTemp, 763 (LVM_INT16)NumSamples); 764 765 766 break; 767 case LVREV_DELAYLINES_2: 768 769 Copy_Float(pPrivate->pScratchDelayLine[1], 770 pScratch, 771 (LVM_INT16)(NumSamples)); 772 773 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], 774 -1.0f, 775 pScratch, 776 (LVM_INT16)NumSamples); 777 778 Add2_Sat_Float(pPrivate->pScratchDelayLine[1], 779 pPrivate->pScratchDelayLine[0], 780 (LVM_INT16)NumSamples); 781 782 783 JoinTo2i_Float(pPrivate->pScratchDelayLine[0], 784 pScratch, 785 pTemp, 786 (LVM_INT16)NumSamples); 787 break; 788 case LVREV_DELAYLINES_1: 789 MonoTo2I_Float(pPrivate->pScratchDelayLine[0], 790 pTemp, 791 (LVM_INT16)NumSamples); 792 break; 793 default: 794 break; 795 } 796 797 798 /* 799 * Dry/wet mixer 800 */ 801 802 size = (LVM_INT16)(NumSamples << 1); 803 MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer, 804 pTemp, 805 pTemp, 806 pOutput, 807 size); 808 809 /* Apply Gain*/ 810 811 Shift_Sat_Float(LVREV_OUTPUTGAIN_SHIFT, 812 pOutput, 813 pOutput, 814 size); 815 816 MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer, 817 pOutput, 818 pOutput, 819 size); 820 821 return; 822 } 823 #endif 824 /* End of file */ 825 826