Home | History | Annotate | Download | only in src
      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