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 /*    Defines                                                                           */
30 /*                                                                                      */
31 /****************************************************************************************/
32 
33 #define VOL_TC_SHIFT                                        21          /* As a power of 2 */
34 #define DECAY_SHIFT                                        10           /* As a power of 2 */
35 #define VOL_TC_FLOAT                                      2.0f          /* As a power of 2 */
36 #define DECAY_FAC_FLOAT                                  64.0f          /* As a power of 2 */
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 /****************************************************************************************/
AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t * pInstance,const LVM_FLOAT * pStSrc,const LVM_FLOAT * pMonoSrc,LVM_FLOAT * pDst,LVM_UINT16 NumSamples)72 void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,     /* Instance pointer */
73                                  const LVM_FLOAT            *pStSrc,        /* Stereo source */
74                                  const LVM_FLOAT            *pMonoSrc,      /* Mono source */
75                                  LVM_FLOAT                  *pDst,          /* Stereo destination */
76                                  LVM_UINT16                 NumSamples)     /* Number of samples */
77 {
78 
79     /*
80      * General variables
81      */
82     LVM_UINT16      i;                                          /* Sample index */
83     LVM_FLOAT       Left;                                       /* Left sample */
84     LVM_FLOAT       Right;                                      /* Right sample */
85     LVM_FLOAT       Mono;                                       /* Mono sample */
86     LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
87     LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
88     LVM_FLOAT       Vol_Mult;                                   /* Short volume */
89 
90     /*
91      * Instance control variables
92      */
93     LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
94     LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
95     LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
96     LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));/* Decay scaler */
97     LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
98     LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
99     LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
100     LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
101 
102     /*
103      * Process on a sample by sample basis
104      */
105     for (i = 0; i < NumSamples; i++)                                  /* For each sample */
106     {
107 
108         /*
109          * Get the short scalers
110          */
111         AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the short AGC gain */
112         Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the short volume gain */
113 
114         /*
115          * Get the input samples
116          */
117         Left  = *pStSrc++;                                      /* Get the left sample */
118         Right = *pStSrc++;                                      /* Get the right sample */
119         Mono  = *pMonoSrc++;                                    /* Get the mono sample */
120 
121         /*
122          * Apply the AGC gain to the mono input and mix with the stereo signal
123          */
124         Left  += (Mono * AGC_Mult);                               /* Mix in the mono signal */
125         Right += (Mono * AGC_Mult);
126 
127         /*
128          * Apply the volume and write to the output stream
129          */
130         Left  = Left  * Vol_Mult;
131         Right = Right * Vol_Mult;
132         *pDst++ = Left;                                         /* Save the results */
133         *pDst++ = Right;
134 
135         /*
136          * Update the AGC gain
137          */
138         AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
139         if (AbsPeak > AGC_Target)
140         {
141             /*
142              * The signal is too large so decrease the gain
143              */
144             AGC_Gain = AGC_Gain * AGC_Attack;
145         }
146         else
147         {
148             /*
149              * The signal is too small so increase the gain
150              */
151             if (AGC_Gain > AGC_MaxGain)
152             {
153                 AGC_Gain -= (AGC_Decay);
154             }
155             else
156             {
157                 AGC_Gain += (AGC_Decay);
158             }
159         }
160 
161         /*
162          * Update the gain
163          */
164         Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
165     }
166 
167     /*
168      * Update the parameters
169      */
170     pInstance->Volume = Vol_Current;                            /* Actual volume setting */
171     pInstance->AGC_Gain = AGC_Gain;
172 
173     return;
174 }
175 #ifdef SUPPORT_MC
176 /****************************************************************************************/
177 /*                                                                                      */
178 /* FUNCTION:                  AGC_MIX_VOL_Mc1Mon_D32_WRA                                */
179 /*                                                                                      */
180 /* DESCRIPTION:                                                                         */
181 /*    Apply AGC and mix signals                                                         */
182 /*                                                                                      */
183 /*                                                                                      */
184 /*  McSrc   ------------------|                                                         */
185 /*                            |                                                         */
186 /*              ______       _|_        ________                                        */
187 /*             |      |     |   |      |        |                                       */
188 /*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
189 /*             | Gain |     |___|      | Gain   |                              |        */
190 /*             |______|                |________|                              |        */
191 /*                /|\                               __________     ________    |        */
192 /*                 |                               |          |   |        |   |        */
193 /*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
194 /*                                                 | Update   |   | Detect |            */
195 /*                                                 |__________|   |________|            */
196 /*                                                                                      */
197 /*                                                                                      */
198 /* PARAMETERS:                                                                          */
199 /*  pInstance               Instance pointer                                            */
200 /*  pMcSrc                  Multichannel source                                         */
201 /*  pMonoSrc                Mono band pass source                                       */
202 /*  pDst                    Multichannel destination                                    */
203 /*  NrFrames                Number of frames                                            */
204 /*  NrChannels              Number of channels                                          */
205 /*                                                                                      */
206 /* RETURNS:                                                                             */
207 /*  Void                                                                                */
208 /*                                                                                      */
209 /* NOTES:                                                                               */
210 /*                                                                                      */
211 /****************************************************************************************/
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)212 void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,
213                                  const LVM_FLOAT            *pMcSrc,
214                                  const LVM_FLOAT            *pMonoSrc,
215                                  LVM_FLOAT                  *pDst,
216                                  LVM_UINT16                 NrFrames,
217                                  LVM_UINT16                 NrChannels)
218 {
219 
220     /*
221      * General variables
222      */
223     LVM_UINT16      i, jj;                                      /* Sample index */
224     LVM_FLOAT       SampleVal;                                  /* Sample value */
225     LVM_FLOAT       Mono;                                       /* Mono sample */
226     LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
227     LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
228     LVM_FLOAT       Vol_Mult;                                   /* Short volume */
229 
230     /*
231      * Instance control variables
232      */
233     LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
234     LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
235     LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
236     /* Decay scaler */
237     LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));
238     LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
239     LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
240     LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
241     LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
242 
243     /*
244      * Process on a sample by sample basis
245      */
246     for (i = 0; i < NrFrames; i++)                                  /* For each frame */
247     {
248 
249         /*
250          * Get the scalers
251          */
252         AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the AGC gain */
253         Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the volume gain */
254 
255         AbsPeak = 0.0f;
256         /*
257          * Get the input samples
258          */
259         for (jj = 0; jj < NrChannels; jj++)
260         {
261             SampleVal  = *pMcSrc++;                       /* Get the sample value of jj Channel*/
262             Mono       = *pMonoSrc;                       /* Get the mono sample */
263 
264             /*
265              * Apply the AGC gain to the mono input and mix with the input signal
266              */
267             SampleVal  += (Mono * AGC_Mult);                        /* Mix in the mono signal */
268 
269             /*
270              * Apply the volume and write to the output stream
271              */
272             SampleVal  = SampleVal  * Vol_Mult;
273 
274             *pDst++ = SampleVal;                                         /* Save the results */
275 
276             /*
277              * Update the AGC gain
278              */
279             AbsPeak = Abs_Float(SampleVal) > AbsPeak ? Abs_Float(SampleVal) : AbsPeak;
280         }
281         if (AbsPeak > AGC_Target)
282         {
283             /*
284              * The signal is too large so decrease the gain
285              */
286             AGC_Gain = AGC_Gain * AGC_Attack;
287         }
288         else
289         {
290             /*
291              * The signal is too small so increase the gain
292              */
293             if (AGC_Gain > AGC_MaxGain)
294             {
295                 AGC_Gain -= (AGC_Decay);
296             }
297             else
298             {
299                 AGC_Gain += (AGC_Decay);
300             }
301         }
302         pMonoSrc++;
303         /*
304          * Update the gain
305          */
306         Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
307     }
308 
309     /*
310      * Update the parameters
311      */
312     pInstance->Volume = Vol_Current;                            /* Actual volume setting */
313     pInstance->AGC_Gain = AGC_Gain;
314 
315     return;
316 }
317 #endif /*SUPPORT_MC*/
318