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 
     24 #include "AGC.h"
     25 #include "ScalarArithmetic.h"
     26 
     27 
     28 /****************************************************************************************/
     29 /*                                                                                      */
     30 /*    Defines                                                                           */
     31 /*                                                                                      */
     32 /****************************************************************************************/
     33 
     34 #define VOL_TC_SHIFT                                        21          /* As a power of 2 */
     35 #define DECAY_SHIFT                                        10           /* As a power of 2 */
     36 
     37 
     38 /****************************************************************************************/
     39 /*                                                                                      */
     40 /* FUNCTION:                  AGC_MIX_VOL_2St1Mon_D32_WRA                               */
     41 /*                                                                                      */
     42 /* DESCRIPTION:                                                                         */
     43 /*    Apply AGC and mix signals                                                         */
     44 /*                                                                                      */
     45 /*                                                                                      */
     46 /*  StSrc   ------------------|                                                         */
     47 /*                            |                                                         */
     48 /*              ______       _|_        ________                                        */
     49 /*             |      |     |   |      |        |                                       */
     50 /*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
     51 /*             | Gain |     |___|      | Gain   |                              |        */
     52 /*             |______|                |________|                              |        */
     53 /*                /|\                               __________     ________    |        */
     54 /*                 |                               |          |   |        |   |        */
     55 /*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
     56 /*                                                 | Update   |   | Detect |            */
     57 /*                                                 |__________|   |________|            */
     58 /*                                                                                      */
     59 /*                                                                                      */
     60 /* PARAMETERS:                                                                          */
     61 /*  pInstance               Instance pointer                                            */
     62 /*  pStereoIn               Stereo source                                               */
     63 /*  pMonoIn                 Mono band pass source                                       */
     64 /*  pStereoOut              Stereo destination                                          */
     65 /*                                                                                      */
     66 /* RETURNS:                                                                             */
     67 /*  Void                                                                                */
     68 /*                                                                                      */
     69 /* NOTES:                                                                               */
     70 /*                                                                                      */
     71 /****************************************************************************************/
     72 
     73 void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
     74                                  const LVM_INT32            *pStSrc,        /* Stereo source */
     75                                  const LVM_INT32            *pMonoSrc,      /* Mono source */
     76                                  LVM_INT32                  *pDst,          /* Stereo destination */
     77                                  LVM_UINT16                 NumSamples)     /* Number of samples */
     78 {
     79 
     80     /*
     81      * General variables
     82      */
     83     LVM_UINT16      i;                                          /* Sample index */
     84     LVM_INT32       Left;                                       /* Left sample */
     85     LVM_INT32       Right;                                      /* Right sample */
     86     LVM_INT32       Mono;                                       /* Mono sample */
     87     LVM_INT32       AbsPeak;                                    /* Absolute peak signal */
     88     LVM_INT32       HighWord;                                   /* High word in intermediate calculations */
     89     LVM_INT32       LowWord;                                    /* Low word in intermediate calculations */
     90     LVM_INT16       AGC_Mult;                                   /* Short AGC gain */
     91     LVM_INT16       Vol_Mult;                                   /* Short volume */
     92 
     93 
     94     /*
     95      * Instance control variables
     96      */
     97     LVM_INT32      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
     98     LVM_INT32      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
     99     LVM_INT16      AGC_GainShift = pInstance->AGC_GainShift;    /* Get the AGC shift */
    100     LVM_INT16      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
    101     LVM_INT16      AGC_Decay     = pInstance->AGC_Decay;        /* Decay scaler */
    102     LVM_INT32      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
    103     LVM_INT32      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
    104     LVM_INT32      Vol_Target    = pInstance->Target;           /* Target volume setting */
    105     LVM_INT16      Vol_Shift     = pInstance->VolumeShift;      /* Volume shift scaling */
    106     LVM_INT16      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
    107 
    108 
    109     /*
    110      * Process on a sample by sample basis
    111      */
    112     for (i=0;i<NumSamples;i++)                                  /* For each sample */
    113     {
    114 
    115         /*
    116          * Get the short scalers
    117          */
    118         AGC_Mult    = (LVM_INT16)(AGC_Gain >> 16);              /* Get the short AGC gain */
    119         Vol_Mult    = (LVM_INT16)(Vol_Current >> 16);           /* Get the short volume gain */
    120 
    121 
    122         /*
    123          * Get the input samples
    124          */
    125         Left  = *pStSrc++;                                      /* Get the left sample */
    126         Right = *pStSrc++;                                      /* Get the right sample */
    127         Mono  = *pMonoSrc++;                                    /* Get the mono sample */
    128 
    129 
    130         /*
    131          * Apply the AGC gain to the mono input and mix with the stereo signal
    132          */
    133         HighWord = (AGC_Mult * (Mono >> 16));                   /* signed long (Mono) by unsigned short (AGC_Mult) multiply */
    134         LowWord = (AGC_Mult * (Mono & 0xffff));
    135         Mono = (HighWord + (LowWord >> 16)) << (AGC_GainShift);
    136         Left  += Mono;                                          /* Mix in the mono signal */
    137         Right += Mono;
    138 
    139 
    140         /*
    141          * Apply the volume and write to the output stream
    142          */
    143         HighWord = (Vol_Mult * (Left >> 16));                   /* signed long (Left) by unsigned short (Vol_Mult) multiply */
    144         LowWord = (Vol_Mult * (Left & 0xffff));
    145         Left = (HighWord + (LowWord >> 16)) << (Vol_Shift);
    146         HighWord = (Vol_Mult * (Right >> 16));                  /* signed long (Right) by unsigned short (Vol_Mult) multiply */
    147         LowWord = (Vol_Mult * (Right & 0xffff));
    148         Right = (HighWord + (LowWord >> 16)) << (Vol_Shift);
    149         *pDst++ = Left;                                         /* Save the results */
    150         *pDst++ = Right;
    151 
    152 
    153         /*
    154          * Update the AGC gain
    155          */
    156         AbsPeak = (Abs_32(Left)>Abs_32(Right)) ? Abs_32(Left) : Abs_32(Right);  /* Get the absolute peak */
    157         if (AbsPeak > AGC_Target)
    158         {
    159             /*
    160              * The signal is too large so decrease the gain
    161              */
    162             HighWord = (AGC_Attack * (AGC_Gain >> 16));         /* signed long (AGC_Gain) by unsigned short (AGC_Attack) multiply */
    163             LowWord = (AGC_Attack * (AGC_Gain & 0xffff));
    164             AGC_Gain = (HighWord + (LowWord >> 16)) << 1;
    165         }
    166         else
    167         {
    168             /*
    169              * The signal is too small so increase the gain
    170              */
    171             if (AGC_Gain > AGC_MaxGain)
    172             {
    173                 AGC_Gain -= (AGC_Decay << DECAY_SHIFT);
    174             }
    175             else
    176             {
    177                 AGC_Gain += (AGC_Decay << DECAY_SHIFT);
    178             }
    179         }
    180 
    181         /*
    182          * Update the gain
    183          */
    184         Vol_Current += Vol_TC * ((Vol_Target - Vol_Current) >> VOL_TC_SHIFT);
    185     }
    186 
    187 
    188     /*
    189      * Update the parameters
    190      */
    191     pInstance->Volume = Vol_Current;                            /* Actual volume setting */
    192     pInstance->AGC_Gain = AGC_Gain;
    193 
    194     return;
    195 }
    196 
    197