diff options
Diffstat (limited to 'media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c')
-rwxr-xr-x | media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c new file mode 100755 index 0000000..40e0dbf --- /dev/null +++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/**************************************************************************************** + + $Author: beq07716 $ + $Revision: 1070 $ + $Date: 2010-07-02 11:22:18 +0200 (Fri, 02 Jul 2010) $ + +*****************************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "AGC.h" +#include "ScalarArithmetic.h" + + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +#define VOL_TC_SHIFT 21 /* As a power of 2 */ +#define DECAY_SHIFT 10 /* As a power of 2 */ + + +/****************************************************************************************/ +/* */ +/* FUNCTION: AGC_MIX_VOL_2St1Mon_D32_WRA */ +/* */ +/* DESCRIPTION: */ +/* Apply AGC and mix signals */ +/* */ +/* */ +/* StSrc ------------------| */ +/* | */ +/* ______ _|_ ________ */ +/* | | | | | | */ +/* MonoSrc -->| AGC |---->| + |----->| Volume |------------------------------+---> */ +/* | Gain | |___| | Gain | | */ +/* |______| |________| | */ +/* /|\ __________ ________ | */ +/* | | | | | | */ +/* |-------------------------------| AGC Gain |<--| Peak |<--| */ +/* | Update | | Detect | */ +/* |__________| |________| */ +/* */ +/* */ +/* PARAMETERS: */ +/* pInstance Instance pointer */ +/* pStereoIn Stereo source */ +/* pMonoIn Mono band pass source */ +/* pStereoOut Stereo destination */ +/* */ +/* RETURNS: */ +/* Void */ +/* */ +/* NOTES: */ +/* */ +/****************************************************************************************/ + +void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t *pInstance, /* Instance pointer */ + const LVM_INT32 *pStSrc, /* Stereo source */ + const LVM_INT32 *pMonoSrc, /* Mono source */ + LVM_INT32 *pDst, /* Stereo destination */ + LVM_UINT16 NumSamples) /* Number of samples */ +{ + + /* + * General variables + */ + LVM_UINT16 i; /* Sample index */ + LVM_INT32 Left; /* Left sample */ + LVM_INT32 Right; /* Right sample */ + LVM_INT32 Mono; /* Mono sample */ + LVM_INT32 AbsPeak; /* Absolute peak signal */ + LVM_INT32 HighWord; /* High word in intermediate calculations */ + LVM_INT32 LowWord; /* Low word in intermediate calculations */ + LVM_INT16 AGC_Mult; /* Short AGC gain */ + LVM_INT16 Vol_Mult; /* Short volume */ + + + /* + * Instance control variables + */ + LVM_INT32 AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */ + LVM_INT32 AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */ + LVM_INT16 AGC_GainShift = pInstance->AGC_GainShift; /* Get the AGC shift */ + LVM_INT16 AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */ + LVM_INT16 AGC_Decay = pInstance->AGC_Decay; /* Decay scaler */ + LVM_INT32 AGC_Target = pInstance->AGC_Target; /* Get the target level */ + LVM_INT32 Vol_Current = pInstance->Volume; /* Actual volume setting */ + LVM_INT32 Vol_Target = pInstance->Target; /* Target volume setting */ + LVM_INT16 Vol_Shift = pInstance->VolumeShift; /* Volume shift scaling */ + LVM_INT16 Vol_TC = pInstance->VolumeTC; /* Time constant */ + + + /* + * Process on a sample by sample basis + */ + for (i=0;i<NumSamples;i++) /* For each sample */ + { + + /* + * Get the short scalers + */ + AGC_Mult = (LVM_INT16)(AGC_Gain >> 16); /* Get the short AGC gain */ + Vol_Mult = (LVM_INT16)(Vol_Current >> 16); /* Get the short volume gain */ + + + /* + * Get the input samples + */ + Left = *pStSrc++; /* Get the left sample */ + Right = *pStSrc++; /* Get the right sample */ + Mono = *pMonoSrc++; /* Get the mono sample */ + + + /* + * Apply the AGC gain to the mono input and mix with the stereo signal + */ + HighWord = (AGC_Mult * (Mono >> 16)); /* signed long (Mono) by unsigned short (AGC_Mult) multiply */ + LowWord = (AGC_Mult * (Mono & 0xffff)); + Mono = (HighWord + (LowWord >> 16)) << (AGC_GainShift); + Left += Mono; /* Mix in the mono signal */ + Right += Mono; + + + /* + * Apply the volume and write to the output stream + */ + HighWord = (Vol_Mult * (Left >> 16)); /* signed long (Left) by unsigned short (Vol_Mult) multiply */ + LowWord = (Vol_Mult * (Left & 0xffff)); + Left = (HighWord + (LowWord >> 16)) << (Vol_Shift); + HighWord = (Vol_Mult * (Right >> 16)); /* signed long (Right) by unsigned short (Vol_Mult) multiply */ + LowWord = (Vol_Mult * (Right & 0xffff)); + Right = (HighWord + (LowWord >> 16)) << (Vol_Shift); + *pDst++ = Left; /* Save the results */ + *pDst++ = Right; + + + /* + * Update the AGC gain + */ + AbsPeak = (Abs_32(Left)>Abs_32(Right)) ? Abs_32(Left) : Abs_32(Right); /* Get the absolute peak */ + if (AbsPeak > AGC_Target) + { + /* + * The signal is too large so decrease the gain + */ + HighWord = (AGC_Attack * (AGC_Gain >> 16)); /* signed long (AGC_Gain) by unsigned short (AGC_Attack) multiply */ + LowWord = (AGC_Attack * (AGC_Gain & 0xffff)); + AGC_Gain = (HighWord + (LowWord >> 16)) << 1; + } + else + { + /* + * The signal is too small so increase the gain + */ + if (AGC_Gain > AGC_MaxGain) + { + AGC_Gain -= (AGC_Decay << DECAY_SHIFT); + } + else + { + AGC_Gain += (AGC_Decay << DECAY_SHIFT); + } + } + + /* + * Update the gain + */ + Vol_Current += Vol_TC * ((Vol_Target - Vol_Current) >> VOL_TC_SHIFT); + } + + + /* + * Update the parameters + */ + pInstance->Volume = Vol_Current; /* Actual volume setting */ + pInstance->AGC_Gain = AGC_Gain; + + return; +} + |