📄 amf_agclimitercoretable_render.asm
字号:
// Copyright(c) 2005 Analog Devices, Inc. All Rights Reserved.
// This software is proprietary and confidential to Analog Devices, Inc. and its licensors.
// File : $Id: //depot/development/visualaudio/modules/2.5.0/SHARC/Source/AMF_AGCLimiterCore_Render.asm#3 $
// Part of : VisualAudio V2.5.0
// Updated : $Date: 2007-08-08 12:37:19 +0530 (Wed, 08 Aug 2007) $ by $Author: kdasari2 $
// Module Name : AMF_AGCLimiterCore_Render.asm
// DSP Processor : ADSP21161
// Original Author : Tim Stilson
// Date : 8/28/03
//====================================================================================
// Processor resources used:
// 79 words pmem
// 273 cycles, tickSize=128, (145 + 2*(tickSize/2))
// (SIMD used)
//====================================================================================
#if 1
////////////////////////////////////////////////////////////////////////////////
//
// History:
//
// 8/28/03 Kishore Dasari:
//
////////////////////////////////////////////////////////////////////////////////
#include "AMF_AGCLimiterCoreTable.h"
#include "processor.h"
#include <asm_sprt.h>
// global routines
.global _AMF_AGCLimiterCoreTable_Render;
.segment /pm SEG_MOD_FAST_CODE;
////////////////////////////////////////////////////////////////////////////////
// AGCLimiterCore filter
//
_AMF_AGCLimiterCoreTable_Render:
// push context on stack
puts = mode1;
puts = r10;
r0 = i3; puts = r0;
r0=i0; puts=r0;
r0=i1; puts=r0;
puts=r3;
puts=r5;
puts=r9;
puts=r13;
puts=r14;
puts=r15;
puts=r6;
i1=r8; // i1->*buffers
r10 = r12; //block size
m4 = 1;
m8 = 1;
// initialize input and output samples pointers
i0=dm(0,i1); // i0->buffers[0], input
i4=dm(1,i1); // i4->buffers[1], output
i3 = i4; // buffers[1], output
i1=r4; //i1->testModuleInstance[0]
/**********************************************
* Doing limiting for each sample
***********************************************/
lcntr = r10, do agc_block until lce;
f1 = dm(i0,m4); //contains input.
/*************************************************
* update envelop coeff depending attack or decay
* and one pole filter for envelope detector
**************************************************/
f0 = dm(AMF_AGCLimiterCoreTable_EnvState,i1);
r8=dm(AMF_AGCLimiterCoreTable_AttackCoef,i1);
f2=f1-f0, f9=dm(AMF_AGCLimiterCoreTable_DecayCoef,i1); // r2=in-state (also does the comparison), f9 = decay coef
if LE f2=f9*f2; // if in<state, r2=decaycoef*(in-state), (since this is a multiply, the alu condition isn't affected, right?)
if GT f2=f8*f2; // "else" r2=attackcoef*(in-state), and choose/remember the corresponding smoothing coef
f0=f2+f0; // state = r0 = state+coef*(in-state)
dm(AMF_AGCLimiterCoreTable_EnvState,i1)=f0;
/**********************************************************
* Convert to dB
***********************************************************/
// using lower-accuracy approximation to dB... using straight-line interp instread of table lookup to handle mantissa part:
// 6.0206*(exponent + mantissa - 1) rather than 6.0206*(exponent + log2table(mantissa))
// this is quicker and didn't seem to have terrible effect on quality
// basic assumption: float mantissa = scalb x by (-logb x) gives a value in the range 1 -> 2 (verified)
// instead of doing out=6.0206*(exp + (mant-1)), we're doing 6.0206*exp - 6.0206 + 6.0206*mant
// (this, by giving us an extra independent multiply, allows us to overlap the conversion of the exp into float)
f4=6.0206;
r14=r14-r14, s5=f5; // clear r14/s14, put smoother coef in PEy side too
r8=logb f0, f15=f4; // r8/s8 = exponent(tmp), copy f4 into higher reg for parallel op below
r3=-r8;
f2=scalb f0 by r3; // f2/s2 = mantissa(tmp) (in range 1-2)
f8=f2*f4, f1=float r8 by r14; // f8/s2=6.*mant, convert exponent to float
f1=f1*f4, f8=f8-f15; // f1/s1=6.*exp, f8/s8=6.*mant - 6.
f15=f1+f8,r2 = dm(AMF_AGCLimiterCoreTable_TablePoints,i1); // f8/s8=6.*exp + 6.*mant - 6. , this is the result
/*This code is requires to get finite o/p when input is 0
and also envstate is 0 but for all practical purposes this
can be ignored.
f3 = 0;
comp(f3,f0);
f3 = -12.0412;
if eq f15 = f3; */
/******************************************************
* Find out where signal falls in the given input table
******************************************************/
i4 = dm(AMF_AGCLimiterCoreTable_InputTable,i1);
r13 = 0;
f1 = dm(i4,m4);
lcntr = r2, do Limiter_Check_InputLevel_Table_Loopend until lce;
comp(f15,f1), f1 = dm(i4,m4);
Limiter_Check_InputLevel_Table_Loopend:if gt r13 =r13 + 1;
r2 = 0;
f3 = 0.0;
i12 = dm(AMF_AGCLimiterCoreTable_OutputTable,i1);
i4 = dm(AMF_AGCLimiterCoreTable_InputTable,i1);
/* slope for signal which is <= minimum level of the input table */
comp(r13,r2), r2 = dm(AMF_AGCLimiterCoreTable_TablePoints,i1);
if ne jump Limiter_Check_BeyondgivenThreshold;
f1 = dm(i4,m4),f6 = pm(i12,m8);
f2 = f15 - f1,f8 = dm(i4,m4), f4 = pm(i12,m8);
f8 = f8 - f1; // denominator
f4 = f4 - f6; // numarator
f0 = 0.0;
comp(f3,f8);
if ne call _LimitreCore_devide_func;
f3 = f0; // slope
jump Limiter_SlopeCalculationComplete;
/* slope for signal which is >= max level of the input table */
Limiter_Check_BeyondgivenThreshold:
comp(r13,r2), r0 = dm(AMF_AGCLimiterCoreTable_InputTable,i1);
if ne jump Limiter_Check_GivenTable;
r1 = 2;
r2 = r2 - r1, r1 = dm(AMF_AGCLimiterCoreTable_OutputTable,i1);
r0 = r0 + r2;
r1 = r1 + r2, i4 = r0;
i12 = r1;
f1 = dm(i4,m4),f6 = pm(i12,m8);
f2 = f15 - f1,f8 = dm(i4,m4), f4 = pm(i12,m8);
f8 = f8 - f1; // denominator
f4 = f4 - f6; // numarator
comp(f3,f8);
if ne call _LimitreCore_devide_func;
f3 = f0; // slope
jump Limiter_SlopeCalculationComplete;
/* falls under given range of input table, slope = (y2 - y1)/ (x2 - x1) */
Limiter_Check_GivenTable:
r0 = dm(AMF_AGCLimiterCoreTable_InputTable,i1);
r13 = r13 - 1;
r0 = r0 + r13, r1 = dm(AMF_AGCLimiterCoreTable_OutputTable,i1);
r1 = r1 + r13, i4 = r0;
i12 = r1;
f1 = dm(i4,m4),f6 = pm(i12,m8);
f2 = f15 - f1,f8 = dm(i4,m4), f4 = pm(i12,m8); // sig_ths - inputlvel[index-1]
f8 = f8 - f1; // denominator
f4 = f4 - f6; // numarator
comp(f3,f8);
if ne call _LimitreCore_devide_func;
f3 = f0; // slope
Limiter_SlopeCalculationComplete:
/*************************************************
* Calculate the gain depending on input level
* if the input level falls out of the table
* Linearly extend the line segments.
*************************************************/
f8 = f3 * f2;
f8 = f8 + f6; // temp = output_levels[index-1] + slope*(signal_ths - input_levels[index-1]);
f8 = f8 - f15;
f0 = dm(AMF_AGCLimiterCoreTable_Gain,i1);
f0 = f0 + f8;
/*********************************************************
* Convert from dB back to lin and write to output
***********************************************************/
f1=0.166096; // this is the input scale of the dB->lin conversion
f0=f0*f1; // f0/s0=tmp[i/i+1]*0.166096, 0.166096 = log2(10)/20;
bit set mode1 TRUNCATE; // round to -inf for the fp->int conversion (the fix operation)
f9=1.0;
r1=fix f0; // r1=(int)floor(tmp);
f2=float r1; // back to float to get fractional part
f2=f0-f2; // f2=fractional part, read next in
f2=f2+f9; // f2 = frac + 1;
f8=scalb f2 by r1; // f8 = (frac + 1)*2^floor(tmp) (this will be the target for the smoother below)
bit clr mode1 TRUNCATE; // reset rounding mode
/******************************************************************/
//Write back output
agc_block:dm(i3,m4)=f8;
// pop context off stack
r6=gets(1);
r15=gets(2);
r14=gets(3);
r13=gets(4);
r9=gets(5);
r5=gets(6);
r3=gets(7);
i1=gets(8);
i0=gets(9);
i3=gets(10);
r10 = gets(11);
mode1 =gets(12);
alter(12);
//------------------------------------------------------------------------------------
_AMF_AGCLimiterCoreTable_Render.END:
nop;
leaf_exit; // C-rth requires this instead of rts
//------------------------------------------------------------------------------------
.endseg;
#endif
/**************************************************************************
* Devide(x/y) function
**************************************************************************/
.global _LimitreCore_devide_func;
.segment SEG_MOD_FAST_CODE;
_LimitreCore_devide_func:
leaf_entry;
f12 = f8;
f8 = 2.0;
f0 = recips f12; //{get 8 bit seed r0=1/d}
f12 = f0*f12; //{d' = d*r0}
f4 = f0*f4, f0 = f8-f12; //{f0=r1=2-d', f7=n*r0}
f12 = f0*f12; //{f12=d'-d'*r1}
f4 = f0*f4, f0 = f8-f12; //{f7=n*r0*r1, f0=r2=2-d'}
f12 = f0*f12; //{f12=d'=d'*r2}
f4 = f0*f4, f0 = f8-f12; //{f7=n*r0*r1*r2, f0=r3=2-d'}
f0 = f0*f4; //{f7=n*r0*r1*r2*r3}
rts;
_LimitreCore_devide_func.end: //rts(db);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -