• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "AGC.h"
24 #include "ScalarArithmetic.h"
25 
26 /****************************************************************************************/
27 /*                                                                                      */
28 /*    Defines                                                                           */
29 /*                                                                                      */
30 /****************************************************************************************/
31 
32 #define VOL_TC_SHIFT 21       /* As a power of 2 */
33 #define DECAY_SHIFT 10        /* As a power of 2 */
34 #define VOL_TC_FLOAT 2.0f     /* As a power of 2 */
35 #define DECAY_FAC_FLOAT 64.0f /* As a power of 2 */
36 
37 /****************************************************************************************/
38 /*                                                                                      */
39 /* FUNCTION:                  AGC_MIX_VOL_Mc1Mon_D32_WRA                                */
40 /*                                                                                      */
41 /* DESCRIPTION:                                                                         */
42 /*    Apply AGC and mix signals                                                         */
43 /*                                                                                      */
44 /*                                                                                      */
45 /*  McSrc   ------------------|                                                         */
46 /*                            |                                                         */
47 /*              ______       _|_        ________                                        */
48 /*             |      |     |   |      |        |                                       */
49 /*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
50 /*             | Gain |     |___|      | Gain   |                              |        */
51 /*             |______|                |________|                              |        */
52 /*                /|\                               __________     ________    |        */
53 /*                 |                               |          |   |        |   |        */
54 /*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
55 /*                                                 | Update   |   | Detect |            */
56 /*                                                 |__________|   |________|            */
57 /*                                                                                      */
58 /*                                                                                      */
59 /* PARAMETERS:                                                                          */
60 /*  pInstance               Instance pointer                                            */
61 /*  pMcSrc                  Multichannel source                                         */
62 /*  pMonoSrc                Mono band pass source                                       */
63 /*  pDst                    Multichannel destination                                    */
64 /*  NrFrames                Number of frames                                            */
65 /*  NrChannels              Number of channels                                          */
66 /*                                                                                      */
67 /* RETURNS:                                                                             */
68 /*  Void                                                                                */
69 /*                                                                                      */
70 /* NOTES:                                                                               */
71 /*                                                                                      */
72 /****************************************************************************************/
AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t * pInstance,const LVM_FLOAT * pMcSrc,const LVM_FLOAT * pMonoSrc,LVM_FLOAT * pDst,LVM_UINT16 NrFrames,LVM_UINT16 NrChannels)73 void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, const LVM_FLOAT* pMcSrc,
74                                 const LVM_FLOAT* pMonoSrc, LVM_FLOAT* pDst, LVM_UINT16 NrFrames,
75                                 LVM_UINT16 NrChannels) {
76     /*
77      * General variables
78      */
79     LVM_UINT16 i, jj;    /* Sample index */
80     LVM_FLOAT SampleVal; /* Sample value */
81     LVM_FLOAT Mono;      /* Mono sample */
82     LVM_FLOAT AbsPeak;   /* Absolute peak signal */
83     LVM_FLOAT AGC_Mult;  /* Short AGC gain */
84     LVM_FLOAT Vol_Mult;  /* Short volume */
85 
86     /*
87      * Instance control variables
88      */
89     LVM_FLOAT AGC_Gain = pInstance->AGC_Gain;       /* Get the current AGC gain */
90     LVM_FLOAT AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */
91     LVM_FLOAT AGC_Attack = pInstance->AGC_Attack;   /* Attack scaler */
92     /* Decay scaler */
93     LVM_FLOAT AGC_Decay = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));
94     LVM_FLOAT AGC_Target = pInstance->AGC_Target; /* Get the target level */
95     LVM_FLOAT Vol_Current = pInstance->Volume;    /* Actual volume setting */
96     LVM_FLOAT Vol_Target = pInstance->Target;     /* Target volume setting */
97     LVM_FLOAT Vol_TC = pInstance->VolumeTC;       /* Time constant */
98 
99     /*
100      * Process on a sample by sample basis
101      */
102     for (i = 0; i < NrFrames; i++) /* For each frame */
103     {
104         /*
105          * Get the scalers
106          */
107         AGC_Mult = (LVM_FLOAT)(AGC_Gain);    /* Get the AGC gain */
108         Vol_Mult = (LVM_FLOAT)(Vol_Current); /* Get the volume gain */
109 
110         AbsPeak = 0.0f;
111         /*
112          * Get the input samples
113          */
114         for (jj = 0; jj < NrChannels; jj++) {
115             SampleVal = *pMcSrc++; /* Get the sample value of jj Channel*/
116             Mono = *pMonoSrc;      /* Get the mono sample */
117 
118             /*
119              * Apply the AGC gain to the mono input and mix with the input signal
120              */
121             SampleVal += (Mono * AGC_Mult); /* Mix in the mono signal */
122 
123             /*
124              * Apply the volume and write to the output stream
125              */
126             SampleVal = SampleVal * Vol_Mult;
127 
128             *pDst++ = LVM_Clamp(SampleVal); /* Save the results */
129 
130             /*
131              * Update the AGC gain
132              */
133             AbsPeak = Abs_Float(SampleVal) > AbsPeak ? Abs_Float(SampleVal) : AbsPeak;
134         }
135         if (AbsPeak > AGC_Target) {
136             /*
137              * The signal is too large so decrease the gain
138              */
139             AGC_Gain = AGC_Gain * AGC_Attack;
140         } else {
141             /*
142              * The signal is too small so increase the gain
143              */
144             if (AGC_Gain > AGC_MaxGain) {
145                 AGC_Gain -= (AGC_Decay);
146             } else {
147                 AGC_Gain += (AGC_Decay);
148             }
149         }
150         pMonoSrc++;
151         /*
152          * Update the gain
153          */
154         Vol_Current += (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
155     }
156 
157     /*
158      * Update the parameters
159      */
160     pInstance->Volume = Vol_Current; /* Actual volume setting */
161     pInstance->AGC_Gain = AGC_Gain;
162 
163     return;
164 }
165