12c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* 22c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2004-2010 NXP Software 32c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2010 The Android Open Source Project 42c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 52c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 62c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * you may not use this file except in compliance with the License. 72c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * You may obtain a copy of the License at 82c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 92c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * http://www.apache.org/licenses/LICENSE-2.0 102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Unless required by applicable law or agreed to in writing, software 122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * See the License for the specific language governing permissions and 152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * limitations under the License. 162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Includes */ 212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "AGC.h" 252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "ScalarArithmetic.h" 262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Defines */ 312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#define VOL_TC_SHIFT 21 /* As a power of 2 */ 352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#define DECAY_SHIFT 10 /* As a power of 2 */ 36d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#ifdef BUILD_FLOAT 37d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#define VOL_TC_FLOAT 2.0f /* As a power of 2 */ 38d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#define DECAY_FAC_FLOAT 64.0f /* As a power of 2 */ 39d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#endif 402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION: AGC_MIX_VOL_2St1Mon_D32_WRA */ 442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION: */ 462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Apply AGC and mix signals */ 472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* StSrc ------------------| */ 502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | */ 512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* ______ _|_ ________ */ 522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | | | | | | */ 532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* MonoSrc -->| AGC |---->| + |----->| Volume |------------------------------+---> */ 542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | Gain | |___| | Gain | | */ 552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* |______| |________| | */ 562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* /|\ __________ ________ | */ 572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | | | | | | */ 582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* |-------------------------------| AGC Gain |<--| Peak |<--| */ 592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | Update | | Detect | */ 602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* |__________| |________| */ 612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS: */ 642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* pInstance Instance pointer */ 652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* pStereoIn Stereo source */ 662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* pMonoIn Mono band pass source */ 672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* pStereoOut Stereo destination */ 682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS: */ 702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Void */ 712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES: */ 732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 75d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#ifndef BUILD_FLOAT 762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurentvoid AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t *pInstance, /* Instance pointer */ 772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent const LVM_INT32 *pStSrc, /* Stereo source */ 782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent const LVM_INT32 *pMonoSrc, /* Mono source */ 792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 *pDst, /* Stereo destination */ 802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_UINT16 NumSamples) /* Number of samples */ 812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{ 822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * General variables 852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_UINT16 i; /* Sample index */ 872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 Left; /* Left sample */ 882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 Right; /* Right sample */ 892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 Mono; /* Mono sample */ 902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 AbsPeak; /* Absolute peak signal */ 912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 HighWord; /* High word in intermediate calculations */ 922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 LowWord; /* Low word in intermediate calculations */ 932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 AGC_Mult; /* Short AGC gain */ 942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 Vol_Mult; /* Short volume */ 952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Instance control variables 992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */ 1012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */ 1022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 AGC_GainShift = pInstance->AGC_GainShift; /* Get the AGC shift */ 1032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */ 1042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 AGC_Decay = pInstance->AGC_Decay; /* Decay scaler */ 1052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 AGC_Target = pInstance->AGC_Target; /* Get the target level */ 1062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 Vol_Current = pInstance->Volume; /* Actual volume setting */ 1072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 Vol_Target = pInstance->Target; /* Target volume setting */ 1082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 Vol_Shift = pInstance->VolumeShift; /* Volume shift scaling */ 1092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 Vol_TC = pInstance->VolumeTC; /* Time constant */ 1102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Process on a sample by sample basis 1142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent for (i=0;i<NumSamples;i++) /* For each sample */ 1162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Get the short scalers 1202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent AGC_Mult = (LVM_INT16)(AGC_Gain >> 16); /* Get the short AGC gain */ 1222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Vol_Mult = (LVM_INT16)(Vol_Current >> 16); /* Get the short volume gain */ 1232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Get the input samples 1272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Left = *pStSrc++; /* Get the left sample */ 1292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Right = *pStSrc++; /* Get the right sample */ 1302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Mono = *pMonoSrc++; /* Get the mono sample */ 1312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Apply the AGC gain to the mono input and mix with the stereo signal 1352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent HighWord = (AGC_Mult * (Mono >> 16)); /* signed long (Mono) by unsigned short (AGC_Mult) multiply */ 1372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LowWord = (AGC_Mult * (Mono & 0xffff)); 1382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Mono = (HighWord + (LowWord >> 16)) << (AGC_GainShift); 1392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Left += Mono; /* Mix in the mono signal */ 1402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Right += Mono; 1412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Apply the volume and write to the output stream 1452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent HighWord = (Vol_Mult * (Left >> 16)); /* signed long (Left) by unsigned short (Vol_Mult) multiply */ 1472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LowWord = (Vol_Mult * (Left & 0xffff)); 1482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Left = (HighWord + (LowWord >> 16)) << (Vol_Shift); 1492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent HighWord = (Vol_Mult * (Right >> 16)); /* signed long (Right) by unsigned short (Vol_Mult) multiply */ 1502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LowWord = (Vol_Mult * (Right & 0xffff)); 1512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Right = (HighWord + (LowWord >> 16)) << (Vol_Shift); 1522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *pDst++ = Left; /* Save the results */ 1532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *pDst++ = Right; 1542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Update the AGC gain 1582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent AbsPeak = (Abs_32(Left)>Abs_32(Right)) ? Abs_32(Left) : Abs_32(Right); /* Get the absolute peak */ 1602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (AbsPeak > AGC_Target) 1612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * The signal is too large so decrease the gain 1642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent HighWord = (AGC_Attack * (AGC_Gain >> 16)); /* signed long (AGC_Gain) by unsigned short (AGC_Attack) multiply */ 1662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LowWord = (AGC_Attack * (AGC_Gain & 0xffff)); 1672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent AGC_Gain = (HighWord + (LowWord >> 16)) << 1; 1682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent else 1702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * The signal is too small so increase the gain 1732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (AGC_Gain > AGC_MaxGain) 1752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent AGC_Gain -= (AGC_Decay << DECAY_SHIFT); 1772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent else 1792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent AGC_Gain += (AGC_Decay << DECAY_SHIFT); 1812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Update the gain 1862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent Vol_Current += Vol_TC * ((Vol_Target - Vol_Current) >> VOL_TC_SHIFT); 1882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Update the parameters 1932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent pInstance->Volume = Vol_Current; /* Actual volume setting */ 1952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent pInstance->AGC_Gain = AGC_Gain; 1962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent return; 1982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent} 199d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#else 200d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katurivoid AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t *pInstance, /* Instance pointer */ 201d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri const LVM_FLOAT *pStSrc, /* Stereo source */ 202d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri const LVM_FLOAT *pMonoSrc, /* Mono source */ 203d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT *pDst, /* Stereo destination */ 204d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_UINT16 NumSamples) /* Number of samples */ 205d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri{ 206d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 207d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 208d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * General variables 209d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 210d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_UINT16 i; /* Sample index */ 211d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Left; /* Left sample */ 212d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Right; /* Right sample */ 213d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Mono; /* Mono sample */ 214d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AbsPeak; /* Absolute peak signal */ 215d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AGC_Mult; /* Short AGC gain */ 216d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Vol_Mult; /* Short volume */ 217d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 218d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 219d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 220d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Instance control variables 221d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 222d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */ 223d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */ 224d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */ 225d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AGC_Decay = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));/* Decay scaler */ 226d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT AGC_Target = pInstance->AGC_Target; /* Get the target level */ 227d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Vol_Current = pInstance->Volume; /* Actual volume setting */ 228d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Vol_Target = pInstance->Target; /* Target volume setting */ 229d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri LVM_FLOAT Vol_TC = pInstance->VolumeTC; /* Time constant */ 230d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 231d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 232d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 233d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Process on a sample by sample basis 234d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 235d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri for (i = 0; i < NumSamples; i++) /* For each sample */ 236d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri { 2372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 238d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 239d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Get the short scalers 240d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 241d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri AGC_Mult = (LVM_FLOAT)(AGC_Gain); /* Get the short AGC gain */ 242d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Vol_Mult = (LVM_FLOAT)(Vol_Current); /* Get the short volume gain */ 243d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 244d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 245d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 246d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Get the input samples 247d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 248d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Left = *pStSrc++; /* Get the left sample */ 249d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Right = *pStSrc++; /* Get the right sample */ 250d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Mono = *pMonoSrc++; /* Get the mono sample */ 251d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 252d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 253d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 254d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Apply the AGC gain to the mono input and mix with the stereo signal 255d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 256d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Left += (Mono * AGC_Mult); /* Mix in the mono signal */ 257d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Right += (Mono * AGC_Mult); 258d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 259d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 260d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Apply the volume and write to the output stream 261d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 262d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Left = Left * Vol_Mult; 263d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Right = Right * Vol_Mult; 264d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri *pDst++ = Left; /* Save the results */ 265d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri *pDst++ = Right; 266d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 267d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 268d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Update the AGC gain 269d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 270d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right); 271d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri if (AbsPeak > AGC_Target) 272d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri { 273d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 274d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * The signal is too large so decrease the gain 275d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 276d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri AGC_Gain = AGC_Gain * AGC_Attack; 277d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri } 278d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri else 279d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri { 280d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 281d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * The signal is too small so increase the gain 282d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 283d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri if (AGC_Gain > AGC_MaxGain) 284d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri { 285d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri AGC_Gain -= (AGC_Decay); 286d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri } 287d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri else 288d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri { 289d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri AGC_Gain += (AGC_Decay); 290d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri } 291d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri } 292d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 293d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 294d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Update the gain 295d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 296d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri Vol_Current += (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT); 297d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri } 298d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 299d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 300d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri /* 301d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri * Update the parameters 302d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri */ 303d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri pInstance->Volume = Vol_Current; /* Actual volume setting */ 304d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri pInstance->AGC_Gain = AGC_Gain; 305d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri 306d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri return; 307d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri} 308d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#endif /*BUILD_FLOAT*/ 309