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 "Filter.h"
     25 
     26 /****************************************************************************************/
     27 /*                                                                                      */
     28 /* FUNCTION:                LVREV_ApplyNewSettings                                      */
     29 /*                                                                                      */
     30 /* DESCRIPTION:                                                                         */
     31 /*  Applies the new control parameters                                                  */
     32 /*                                                                                      */
     33 /* PARAMETERS:                                                                          */
     34 /*  pPrivate                Pointer to the instance private parameters                  */
     35 /*                                                                                      */
     36 /* RETURNS:                                                                             */
     37 /*  LVREV_Success           Succeeded                                                   */
     38 /*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
     39 /*                                                                                      */
     40 /* NOTES:                                                                               */
     41 /*                                                                                      */
     42 /****************************************************************************************/
     43 
     44 LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
     45 {
     46 
     47     LVM_Mode_en  OperatingMode;
     48     LVM_INT32    NumberOfDelayLines;
     49 
     50 
     51     /* Check for NULL pointer */
     52     if(pPrivate == LVM_NULL)
     53     {
     54         return LVREV_NULLADDRESS;
     55     }
     56 
     57     OperatingMode = pPrivate->NewParams.OperatingMode;
     58 
     59     if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
     60     {
     61         NumberOfDelayLines = 4;
     62     }
     63     else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
     64     {
     65         NumberOfDelayLines = 2;
     66     }
     67     else
     68     {
     69         NumberOfDelayLines = 1;
     70     }
     71 
     72     /*
     73      * Update the high pass filter coefficients
     74      */
     75     if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
     76        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
     77        (pPrivate->bFirstControl        == LVM_TRUE))
     78     {
     79         LVM_INT32       Omega;
     80         FO_C32_Coefs_t  Coeffs;
     81 
     82         Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
     83         LVM_FO_HPF(Omega, &Coeffs);
     84         FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps, &Coeffs);
     85         LoadConst_32(0,
     86             (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
     87             sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
     88     }
     89 
     90 
     91     /*
     92      * Update the low pass filter coefficients
     93      */
     94     if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
     95        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
     96        (pPrivate->bFirstControl        == LVM_TRUE))
     97     {
     98         LVM_INT32       Omega;
     99         FO_C32_Coefs_t  Coeffs;
    100 
    101 
    102         Coeffs.A0 = 0x7FFFFFFF;
    103         Coeffs.A1 = 0;
    104         Coeffs.B1 = 0;
    105         if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
    106         {
    107             Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
    108 
    109             /*
    110              * Do not apply filter if w =2*pi*fc/fs >= 2.9
    111              */
    112             if(Omega<=LVREV_2_9_INQ29)
    113             {
    114                 LVM_FO_LPF(Omega, &Coeffs);
    115             }
    116         }
    117         FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps, &Coeffs);
    118         LoadConst_32(0,
    119             (void *)&pPrivate->pFastData->LPTaps,        /* Destination Cast to void: no dereferencing in function*/
    120             sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
    121     }
    122 
    123 
    124     /*
    125      * Calculate the room size parameter
    126      */
    127     if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
    128     {
    129         /* Room size range is 10ms to 200ms
    130          * 0%   -- 10ms
    131          * 50%  -- 65ms
    132          * 100% -- 120ms
    133          */
    134         pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5)/10);
    135     }
    136 
    137 
    138     /*
    139      * Update the T delay number of samples and the all pass delay number of samples
    140      */
    141     if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
    142         (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
    143         (pPrivate->bFirstControl        == LVM_TRUE))
    144     {
    145 
    146         LVM_UINT32  Temp;
    147         LVM_INT32   APDelaySize;
    148         LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
    149         LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
    150         LVM_INT16   i;
    151         LVM_INT16   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
    152         LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
    153         LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
    154 
    155 
    156         /*
    157          * For each delay line
    158          */
    159         for (i=0; i<NumberOfDelayLines; i++)
    160         {
    161             if (i != 0)
    162             {
    163                 LVM_INT32 Temp1;  /* to avoid QAC warning on type conversion */
    164                 LVM_INT32 Temp2;  /* to avoid QAC warning on type conversion */
    165 
    166                 Temp2=(LVM_INT32)DelayLengthSamples;
    167                 MUL32x16INTO32(Temp2, ScaleTable[i], Temp1, 15)
    168                 Temp=(LVM_UINT32)Temp1;
    169             }
    170             else
    171             {
    172                Temp = DelayLengthSamples;
    173             }
    174             APDelaySize = Temp  / 1500;
    175 
    176 
    177             /*
    178              * Set the fixed delay
    179              */
    180             Temp                  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
    181             pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
    182 
    183 
    184             /*
    185              * Set the tap selection
    186              */
    187             if (pPrivate->AB_Selection)
    188             {
    189                 /* Smooth from tap A to tap B */
    190                 pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
    191                 pPrivate->B_DelaySize[i]          = APDelaySize;
    192                 pPrivate->Mixer_APTaps[i].Target1 = 0;
    193                 pPrivate->Mixer_APTaps[i].Target2 = 0x7fffffff;
    194             }
    195             else
    196             {
    197                 /* Smooth from tap B to tap A */
    198                 pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
    199                 pPrivate->A_DelaySize[i]          = APDelaySize;
    200                 pPrivate->Mixer_APTaps[i].Target2 = 0;
    201                 pPrivate->Mixer_APTaps[i].Target1 = 0x7fffffff;
    202             }
    203 
    204             /*
    205              * Set the maximum block size to the smallest delay size
    206              */
    207             pPrivate->MaxBlkLen   = Temp;
    208             if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
    209             {
    210                 pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
    211             }
    212             if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
    213             {
    214                 pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
    215             }
    216         }
    217         if (pPrivate->AB_Selection)
    218         {
    219             pPrivate->AB_Selection = 0;
    220         }
    221         else
    222         {
    223             pPrivate->AB_Selection = 1;
    224         }
    225 
    226 
    227         /*
    228          * Limit the maximum block length
    229          */
    230         pPrivate->MaxBlkLen=pPrivate->MaxBlkLen-2;                                  /* Just as a precausion, but no problem if we remove this line      */
    231         if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
    232         {
    233             pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
    234         }
    235     }
    236 
    237 
    238     /*
    239      * Update the low pass filter coefficient
    240      */
    241     if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
    242         (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
    243         (pPrivate->bFirstControl        == LVM_TRUE))
    244     {
    245 
    246         LVM_INT32       Temp;
    247         LVM_INT32       Omega;
    248         FO_C32_Coefs_t  Coeffs;
    249         LVM_INT16       i;
    250         LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
    251         LVM_INT32       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4, LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
    252 
    253 
    254         /*
    255          * For each filter
    256          */
    257         for (i=0; i<NumberOfDelayLines; i++)
    258         {
    259             if (i != 0)
    260             {
    261                 MUL32x16INTO32(ScaleTable[i], Damping, Temp, 15)
    262             }
    263             else
    264             {
    265                 Temp = Damping;
    266             }
    267             if(Temp <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
    268             {
    269                 Omega = LVM_GetOmega((LVM_UINT16)Temp, pPrivate->NewParams.SampleRate);
    270                 LVM_FO_LPF(Omega, &Coeffs);
    271             }
    272             else
    273             {
    274                 Coeffs.A0 = 0x7FF00000;
    275                 Coeffs.A1 = 0;
    276                 Coeffs.B1 = 0;
    277             }
    278             FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i], &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
    279         }
    280     }
    281 
    282 
    283     /*
    284      * Update All-pass filter mixer time constants
    285      */
    286     if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
    287         (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
    288         (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
    289     {
    290         LVM_INT16   i;
    291         LVM_INT32   Alpha    = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
    292         LVM_INT32   AlphaTap = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
    293 
    294         for (i=0; i<4; i++)
    295         {
    296             pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
    297             pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
    298             pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
    299             pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
    300         }
    301     }
    302 
    303 
    304     /*
    305      * Update the feed back gain
    306      */
    307     if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
    308         (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
    309         (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
    310         (pPrivate->bFirstControl        == LVM_TRUE))
    311     {
    312 
    313         LVM_INT32               G[4];                       /* Feedback gain (Q7.24) */
    314 
    315         if(pPrivate->NewParams.T60 == 0)
    316         {
    317             G[3] = 0;
    318             G[2] = 0;
    319             G[1] = 0;
    320             G[0] = 0;
    321         }
    322         else
    323         {
    324             LVM_INT32   Temp1;
    325             LVM_INT32   Temp2;
    326             LVM_INT16   i;
    327             LVM_INT16   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
    328 
    329 
    330             /*
    331              * For each delay line
    332              */
    333             for (i=0; i<NumberOfDelayLines; i++)
    334             {
    335                 Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
    336                 if(Temp1 >= (4 << 15))
    337                 {
    338                     G[i] = 0;
    339                 }
    340                 else if((Temp1 >= (2 << 15)))
    341                 {
    342                     Temp2 = LVM_Power10(-(Temp1 << 14));
    343                     Temp1 = LVM_Power10(-(Temp1 << 14));
    344                     MUL32x32INTO32(Temp1,Temp2,Temp1,24)
    345                 }
    346                 else
    347                 {
    348                     Temp1 = LVM_Power10(-(Temp1 << 15));
    349                 }
    350                 if (NumberOfDelayLines == 1)
    351                 {
    352                     G[i] = Temp1;
    353                 }
    354                 else
    355                 {
    356                     LVM_INT32   TempG;
    357                     MUL32x16INTO32(Temp1,ONE_OVER_SQRT_TWO,TempG,15)
    358                     G[i]=TempG;
    359                 }
    360             }
    361         }
    362 
    363         /* Set up the feedback mixers for four delay lines */
    364         pPrivate->FeedbackMixer[0].Target=G[0]<<7;
    365         pPrivate->FeedbackMixer[1].Target=G[1]<<7;
    366         pPrivate->FeedbackMixer[2].Target=G[2]<<7;
    367         pPrivate->FeedbackMixer[3].Target=G[3]<<7;
    368     }
    369 
    370 
    371     /*
    372      * Calculate the gain correction
    373      */
    374     if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
    375        (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
    376        (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
    377     {
    378         LVM_INT32 Index=0;
    379         LVM_INT32 i=0;
    380         LVM_INT32 Gain=0;
    381         LVM_INT32 RoomSize=0;
    382         LVM_INT32 T60;
    383         LVM_INT32 Coefs[5];
    384 
    385         if(pPrivate->NewParams.RoomSize==0)
    386         {
    387             RoomSize=1;
    388         }
    389         else
    390         {
    391             RoomSize=(LVM_INT32)pPrivate->NewParams.RoomSize;
    392         }
    393 
    394         if(pPrivate->NewParams.T60<100)
    395         {
    396             T60 = 100 * LVREV_T60_SCALE;
    397         }
    398         else
    399         {
    400             T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
    401         }
    402 
    403         /* Find the nearest room size in table */
    404         for(i=0;i<24;i++)
    405         {
    406             if(RoomSize<= LVREV_GainPolyTable[i][0])
    407             {
    408                 Index=i;
    409                 break;
    410             }
    411         }
    412 
    413 
    414         if(RoomSize==LVREV_GainPolyTable[Index][0])
    415         {
    416             /* Take table values if the room size is in table */
    417             for(i=1;i<5;i++)
    418             {
    419                 Coefs[i-1]=LVREV_GainPolyTable[Index][i];
    420             }
    421             Coefs[4]=0;
    422             Gain=LVM_Polynomial(3,Coefs,T60);       /* Q.24 result */
    423         }
    424         else
    425         {
    426             /* Interpolate the gain between nearest room sizes */
    427 
    428             LVM_INT32 Gain1,Gain2;
    429             LVM_INT32 Tot_Dist,Dist;
    430 
    431             Tot_Dist=LVREV_GainPolyTable[Index][0]-LVREV_GainPolyTable[Index-1][0];
    432             Dist=RoomSize-LVREV_GainPolyTable[Index-1][0];
    433 
    434 
    435             /* Get gain for first */
    436             for(i=1;i<5;i++)
    437             {
    438                 Coefs[i-1]=LVREV_GainPolyTable[Index-1][i];
    439             }
    440             Coefs[4]=0;
    441 
    442             Gain1=LVM_Polynomial(3,Coefs,T60);      /* Q.24 result */
    443 
    444             /* Get gain for second */
    445             for(i=1;i<5;i++)
    446             {
    447                 Coefs[i-1]=LVREV_GainPolyTable[Index][i];
    448             }
    449             Coefs[4]=0;
    450 
    451             Gain2=LVM_Polynomial(3,Coefs,T60);      /* Q.24 result */
    452 
    453             /* Linear Interpolate the gain */
    454             Gain = Gain1+ (((Gain2-Gain1)*Dist)/(Tot_Dist));
    455         }
    456 
    457 
    458         /*
    459          * Get the inverse of gain: Q.15
    460          * Gain is mostly above one except few cases, take only gains above 1
    461          */
    462         if(Gain < 16777216L)
    463         {
    464             pPrivate->Gain= 32767;
    465         }
    466         else
    467         {
    468             pPrivate->Gain=(LVM_INT16)(LVM_MAXINT_32/(Gain>>8));
    469         }
    470 
    471 
    472         Index=((32767*100)/(100+pPrivate->NewParams.Level));
    473         pPrivate->Gain=(LVM_INT16)((pPrivate->Gain*Index)>>15);
    474         pPrivate->GainMixer.Target = pPrivate->Gain*Index;
    475     }
    476 
    477 
    478     /*
    479      * Update the all pass comb filter coefficient
    480      */
    481     if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
    482         (pPrivate->bFirstControl     == LVM_TRUE))
    483     {
    484         LVM_INT16   i;
    485         LVM_INT32   b = pPrivate->NewParams.Density * LVREV_B_8_on_1000;
    486 
    487         for (i=0;i<4; i++)
    488         {
    489             pPrivate->Mixer_SGFeedback[i].Target    = b;
    490             pPrivate->Mixer_SGFeedforward[i].Target = b;
    491         }
    492     }
    493 
    494 
    495     /*
    496      * Update the bypass mixer time constant
    497      */
    498     if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
    499        (pPrivate->bFirstControl          == LVM_TRUE))
    500     {
    501         LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
    502         LVM_INT32    Alpha;
    503 
    504         Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
    505         pPrivate->FeedbackMixer[0].Alpha=Alpha;
    506         pPrivate->FeedbackMixer[1].Alpha=Alpha;
    507         pPrivate->FeedbackMixer[2].Alpha=Alpha;
    508         pPrivate->FeedbackMixer[3].Alpha=Alpha;
    509 
    510         NumChannels = 2;                                    /* Always stereo output */
    511         pPrivate->BypassMixer.Alpha1 = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
    512         pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
    513         pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
    514     }
    515 
    516 
    517     /*
    518      * Update the bypass mixer targets
    519      */
    520     if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
    521         (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
    522     {
    523         pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
    524         pPrivate->BypassMixer.Target1 = 0x00000000;
    525         if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
    526         {
    527             pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
    528         }
    529         if (pPrivate->NewParams.Level != 0)
    530         {
    531             pPrivate->bDisableReverb = LVM_FALSE;
    532         }
    533     }
    534 
    535     if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
    536     {
    537         if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
    538         {
    539             pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
    540             pPrivate->BypassMixer.Target1 = 0x00000000;
    541 
    542             pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
    543             OperatingMode                      = LVM_MODE_ON;
    544             if (pPrivate->NewParams.Level == 0)
    545             {
    546                 pPrivate->bDisableReverb = LVM_TRUE;
    547             }
    548             else
    549             {
    550                 pPrivate->bDisableReverb = LVM_FALSE;
    551             }
    552         }
    553         else if (pPrivate->bFirstControl == LVM_FALSE)
    554         {
    555             pPrivate->BypassMixer.Target2 = 0x00000000;
    556             pPrivate->BypassMixer.Target1 = 0x00000000;
    557             pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
    558             pPrivate->GainMixer.Target    = 0x03FFFFFF;
    559             OperatingMode = LVM_MODE_ON;
    560         }
    561         else
    562         {
    563             OperatingMode = LVM_MODE_OFF;
    564         }
    565     }
    566 
    567 
    568     /*
    569      * If it is the first call to ApplyNew settings force the current to the target to begin immediate playback of the effect
    570      */
    571     if(pPrivate->bFirstControl == LVM_TRUE)
    572     {
    573         pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
    574         pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
    575     }
    576 
    577 
    578     /*
    579      * Copy the new parameters
    580      */
    581     pPrivate->CurrentParams = pPrivate->NewParams;
    582     pPrivate->CurrentParams.OperatingMode = OperatingMode;
    583 
    584 
    585     /*
    586      * Update flag
    587      */
    588     if(pPrivate->bFirstControl == LVM_TRUE)
    589     {
    590         pPrivate->bFirstControl = LVM_FALSE;
    591     }
    592 
    593 
    594     return LVREV_SUCCESS;
    595 }
    596 
    597 
    598 /****************************************************************************************/
    599 /*                                                                                      */
    600 /* FUNCTION:                BypassMixer_Callback                                        */
    601 /*                                                                                      */
    602 /* DESCRIPTION:                                                                         */
    603 /*  Controls the On to Off operating mode transition                                    */
    604 /*                                                                                      */
    605 /* PARAMETERS:                                                                          */
    606 /*  pPrivate                Pointer to the instance private parameters                  */
    607 /*                                                                                      */
    608 /* RETURNS:                                                                             */
    609 /*  LVREV_Success           Succeeded                                                   */
    610 /*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
    611 /*                                                                                      */
    612 /* NOTES:                                                                               */
    613 /*                                                                                      */
    614 /****************************************************************************************/
    615 LVM_INT32 BypassMixer_Callback (void *pCallbackData,
    616                                 void *pGeneralPurpose,
    617                                 LVM_INT16 GeneralPurpose )
    618 {
    619 
    620     LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)pCallbackData;
    621 
    622 
    623     /*
    624      * Avoid build warnings
    625      */
    626     (void)pGeneralPurpose;
    627     (void)GeneralPurpose;
    628 
    629 
    630     /*
    631      * Turn off
    632      */
    633     pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_OFF;
    634     pLVREV_Private->bDisableReverb              = LVM_TRUE;
    635     LVREV_ClearAudioBuffers((LVREV_Handle_t)pCallbackData);
    636 
    637 
    638     return 0;
    639 }
    640 
    641 /* End of file */
    642 
    643