📄 amf_agccompressorcoretable_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_AGCCompressorCore_Render.asm#3 $
// Part of : VisualAudio V2.5.0
// Updated : $Date: 2006/10/12 $ by $Author: Fernando $
// Module Name : AMF_AGCCompressorCore_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 "processor.h"
#include "AMF_AGCCompressorCoreTable.h"
#include <asm_sprt.h>
// global routines
.global _AMF_AGCCompressorCoreTable_Render;
.segment /pm SEG_MOD_FAST_CODE;
////////////////////////////////////////////////////////////////////////////////
// AGCCompressorCore filter
//
_AMF_AGCCompressorCoreTable_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;
m12 = 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; // i3->buffers[1], output
i1=r4; //i1->testModuleInstance[0]
/**********************************************
* Find the max value in the tick
***********************************************/
f1 = f1 - f1,f0 = dm(i0,m4);
lcntr = r10, do (pc,1) until lce;
f1 = max(f0,f1), f0 = dm(i0,m4);
/*************************************************
* update envelop coeff depending attack or decay
* and one pole filter for envelope detector
**************************************************/
f0 = dm(AMF_AGCCompressorCoreTable_EnvState,i1);
r8=dm(AMF_AGCCompressorCoreTable_AttackCoef,i1);
f5=dm(AMF_AGCCompressorCoreTable_DecayCoefSmoothing,i1); // the smoothing coefs will be used by the smoother at the end,
f4=dm(AMF_AGCCompressorCoreTable_AttackCoefSmoothing,i1); // we decide here which one to use
r3=dm(AMF_AGCCompressorCoreTable_Hold,i1);
r13=dm(AMF_AGCCompressorCoreTable_Statecount,i1);
f2=f1-f0, f9=dm(AMF_AGCCompressorCoreTable_DecayCoef,i1); // r2=in-state (also does the comparison), f9 = decay coef
/* if LT f2=f9*f2; // if in<state, r2=decaycoef*(in-state), since this is a multiply, the alu condition isn't affected
if GE f2=f8*f2, f5=f4; */ // "else" r2=attackcoef*(in-state), and choose/remember the corresponding smoothing coef
if GT f2 = f8 * f2, f5 = f4;
if GT dm(AMF_AGCCompressorCoreTable_Statecount,i1) = r3;
/*To hold that many states before changing to decay.(i.e)When it changes
from attak to decay it will still retain attack coefficient for 'hold'
number of samples. So to change to decay coefficient the maxInput
has to be decreasing in amplitude for atleast hold number of samples*/
if GT jump Calculate_signal;
r3 = 0;
comp(r13,r3);
if LE f2=f9*f2;
if GT f2=f8*f2;
Calculate_signal:f0=f2+f0; // state = r0 = state+coef*(in-state)
dm(AMF_AGCCompressorCoreTable_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; // 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_AGCCompressorCoreTable_TablePoints,i1); // f8/s8=6.*exp + 6.*mant - 6. , this is the result
/******************************************************
* Find out where signal falls in the given input table
******************************************************/
i4 = dm(AMF_AGCCompressorCoreTable_InputTable,i1);
r13 = 0;
f1 = dm(i4,m4);
lcntr = r2, do Check_InputLevel_Table_Loopend until lce;
comp(f15,f1), f1 = dm(i4,m4);
Check_InputLevel_Table_Loopend:if gt r13 =r13 + 1; //r13->index
r2 = 0;
f3 = 0.0;
i12 = dm(AMF_AGCCompressorCoreTable_OutputTable,i1);
i4 = dm(AMF_AGCCompressorCoreTable_InputTable,i1);
/*********************************************
* Look for slope in the lookup table
* if signal is out of bounds extend linearly
**********************************************/
/* slope for signal which is <= minimum level of the input table */
comp(r13,r2), r2 = dm(AMF_AGCCompressorCoreTable_TablePoints,i1);
if ne jump Check_BeyondgivenThreshold;
f1 = dm(i4,m4),f6 = pm(i12,m12);
f2 = f15 - f1,f8 = dm(i4,m4), f4 = pm(i12,m12);
f8 = f8 - f1; // denominator
f4 = f4 - f6; // numerator
f0 = 0.0;
comp(f3,f8);
if ne call _CompressedCore_devide_func;
f3 = f0; // slope
jump SlopeCalculationComplete;
/* slope for signal which is >= max level of the input table */
Check_BeyondgivenThreshold:
comp(r13,r2), r0 = dm(AMF_AGCCompressorCoreTable_InputTable,i1);
if ne jump Check_GivenTable;
r1 = 2;
r2 = r2 - r1, r1 = dm(AMF_AGCCompressorCoreTable_OutputTable,i1);
r0 = r0 + r2;
r1 = r1 + r2, i4 = r0;
i12 = r1;
f1 = dm(i4,m4),f6 = pm(i12,m12);
f2 = f15 - f1,f8 = dm(i4,m4), f4 = pm(i12,m12);
f8 = f8 - f1; // denominator
f4 = f4 - f6; // numarator
comp(f3,f8);
if ne call _CompressedCore_devide_func;
f3 = f0; // slope
jump SlopeCalculationComplete;
/* falls under given range of input table, slope = (y2 - y1)/ (x2 - x1) */
Check_GivenTable:
r0 = dm(AMF_AGCCompressorCoreTable_InputTable,i1);
r13 = r13 - 1;
r0 = r0 + r13, r1 = dm(AMF_AGCCompressorCoreTable_OutputTable,i1);
r1 = r1 + r13, i4 = r0;
i12 = r1;
f1 = dm(i4,m4),f6 = pm(i12,m12);
f2 = f15 - f1,f8 = dm(i4,m4), f4 = pm(i12,m12); // sig_ths - inputlvel[index-1]
f8 = f8 - f1; // denominator
f4 = f4 - f6; // numerator
comp(f3,f8);
if ne call _CompressedCore_devide_func;
f3 = f0; // slope
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, f4 = dm(AMF_AGCCompressorCoreTable_Gain,i1);
/******************************************************
* Apply compressor gain on post gain
******************************************************/
f0 = f8 + f4;
/*********************************************************
* Convert from dB back to linear
***********************************************************/
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, f3 = dm(AMF_AGCCompressorCoreTable_SmoothingState,i1); // 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
/*************************************************************
* filter output with one pole filter running at sampling rate
**************************************************************/
f0 = 1.0;
f4 = f0 - f5; //(1-coefsmoothing)
f8 = f5 * f8; //coefsmoothing*signal_ths
f12 = f4 * f3; //(1-coefsmoothing) * smoothingstate
r13 = r10-1;
f0 = f8 + f12;
lcntr = r13, do output_write until lce;
f12 = f4 * f0,dm(i3,m4) = f0;
output_write:f0 = f8 + f12;
dm(i3,m4) = f0;
dm(AMF_AGCCompressorCoreTable_SmoothingState,i1) = f0;
r13=dm(AMF_AGCCompressorCoreTable_Statecount,i1);
r13 = r13 - r10; //statecount - = ticksize
dm(AMF_AGCCompressorCoreTable_Statecount,i1)=r13;
// 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_AGCCompressorCoreTable_Render.END:
nop;nop;
leaf_exit; // C-rth requires this instead of rts
//------------------------------------------------------------------------------------
.endseg;
#endif
/**************************************************************************
* Devide(x/y) function
**************************************************************************/
.global _CompressedCore_devide_func;
.segment SEG_MOD_FAST_CODE;
_CompressedCore_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;
_CompressedCore_devide_func.end: //rts(db);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -