⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amf_agclimitercoretable_render.asm

📁 ADI SHARC DSP 音频算法标准模块库
💻 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 + -