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

📄 amf_delay_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_Delay_Render.asm#3 $ 
// Part of : VisualAudio V2.5.0 
// Updated : $Date: 2006/10/12 $ by $Author: Fernando $



//    Module Name     : AMF_Delay_Render.asm 
//    DSP Processor   : ADSP21161
//    Description     : Delay audio module ASM file.
//    Owner           : Analog Devices
//    Original Author : Tim Stilson    
//    Date               : 7/17/03
//====================================================================================
// Processor resources used:
// 86 words pmem INTERNAL
// 362 max cycles (TickSize=128) (106 + 4*tickSize/2)
// (SIMD used)
//====================================================================================

#if 1

    ////////////////////////////////////////////////////////////////////////////////
    //
    // History:
    //
    // 7/17/03 Tim Stilson: created
    //
    ////////////////////////////////////////////////////////////////////////////////
    //
    // Mono Delay with SIMD access to delay memory (for on-chip delay storage on 21161)
    //
    // Special Requirements:
    //        - DelaySize must be even, greater than or equal to TickSize, and greater than or equal to DelayLength
    //        - DelayBuffer must be allocated to size DelaySize+1, and that last word is used specially
    //
    ////////////////////////////////////////////////////////////////////////////////

#include "processor.h"
#include "AMF_Delay.h"
#include "asm_macros.h"
#include "asm_sprt.h"

// global routines
.global    _AMF_Delay_Render;            ;

.segment /pm SEG_MOD_FAST_CODE;

////////////////////////////////////////////////////////////////////////////////
// Delay filter
//
_AMF_Delay_Render:
    
 // push context on stack
     puts=mode1;
    r0=i3; puts=r0;
    r0=i2; puts=r0;
    r0=i1; puts=r0;
    r0=i0; puts=r0;
    r0=b1; puts=r0;
    r0=b0; puts=r0;

    i4=r8;                    // i4->*buffers
    
 // initialize input and output samples pointers
    i3=dm(0,i4);            // i1->buffers[0], input
    i2=dm(1,i4);            // i2->buffers[1], output

    i4=r4;                    //i4->testModuleInstance[0]
       
 // initialize coefficient pointer
    b1=dm(AMF_Delay_DelayBuffer,i4);       // buffer base
    l1=dm(AMF_Delay_DelaySize,i4);         // length of circular buffer (must be even, >= tickSize and also be >= delay length)
    r0=dm(AMF_Delay_Delay,i4);             // actual delay in samples
    i1=dm(AMF_Delay_DelayWritePtr,i4);        // current delay write pointer
    
    // setup read pointer
    b0=b1;                // same circular buffer for read ptr
    l0=l1;                // same circular buffer for read ptr
    r1=i1;                // writeptr
    r2=b1;                // buffer base
    r8=l1;                // buffer length
    r0=r1-r0;            // readPtr = writePtr-delay

AMF_Delay_While_Loop:
    comp(r0,r2);        // check against base of buffer
    if ge jump AMF_Delay_AfterWhile;
    r0=r0+r8;            // readPtr += bufferLength
    jump AMF_Delay_While_Loop;

AMF_Delay_AfterWhile:
    s0=r0;                // s0=readPtr;


    /////////// Fixup to handle interaction between SIMD reads and circular buffers ///////
    // if the end of the circular buffer is the first word of a SIMD read (i.e. the SIMD
    //   read crosses the circular buffer boundary between the PEx and PEy sides of the read)
    //   then the read will actually return the value beyond the end of the ciruclar buffer in the 
    //   PEy side of the read, rather than the first value in the circular buffer.  This is 
    //   because the read is commited before the circular-buffer pointer calculations are done
    //   (and probably because SIMD reads are only possible to contiguous pairs of words anyways).
    //   Thus, if we have an odd delay length, we may find that the buffer reads may have this problem.
    //   Therefore, we do a "fixup" to place the first value in the buffer also into the first word
    //   after the buffer, so that the SIMD read will return the right value.  The peculiarities of
    //   this fixup will place various restrictions on the setup:
    //       - The delay will use a "readPtr-follows-writePtr" (i.e. two-pointer) algorithm rather than
    //         the single-pointer method that all the other single-tap delay modules use.
    //         - The allocated length for the delay buffer must be one word longer than the circular
    //         buffer length.
    //       - To avoid worrying about the write pointer wrapping around more than once per tick, 
    //         the circular buffer length must be >= tickSize (this is the reason for using the
    //         two-pointer delay algorithm, by the way).  This allows us to do the fixup outside
    //         the inner loop and therefore not add much to the cost of the module.
    //       - to avoid worrying about the same interaction between the circular buffer and the 
    //         SIMD writes, the circular buffer is required to be an even length.
    //////////////////////////////////////////////////////////////////////////////////////
    // if delay is even, then skip all this
    // if neither pointer will wrap this tick, then skip the rest of this
    // if (writeptr < readptr) copy first word to one past the end of buffer (i.e. to buffer[bufferLength])
    // if (writePtr >= readptr) then it will write to first word in buffer during this
    //   tick, and it will do it before the read ptr gets to it, so we will copy that value to
    //   the word past the end of the buffer.
    //////////////////////// pseudo code /////////////////////////////////////////////////
    // if (delay&1 && (writePtr+tickSize >= bufferBase+bufferLength || readPtr+tickSize >= bufferBase+bufferLength))
    // {
    //     if (writePtr == buffer)
    //         buffer[bufferLength]=in[0];
    //     else if (writePtr < readPtr)
    //         buffer[bufferLength]=buffer[0];
    //     else
    //         buffer[bufferLength]=in[bufferBase+bufferLength-writePtr];
    // }
    //////////////////////////////////////////////////////////////////////////////////////


    r4=dm(AMF_Delay_Delay,i4);            // delay in samples
    r2=1;
    r2=r4 AND r2; // check to see if odd
    if eq jump AMF_Delay_AfterFixup;  // even, don't need to do anything special
        
    //r0=readptr
    //r1=i1;         //writePtr
    r2=b1;        //bufferBase
    
    comp(r1,r2);
    if ne jump AMF_Delay_NotEqual;        
        i0=b0;        // i0=buffer base
        m4=r8;
        r1=dm(m5,i3);        // in[0];
        dm(m4,i0)=r1;        // copied to the word after the end of the buffer
    jump AMF_Delay_AfterFixup;
AMF_Delay_NotEqual:

    r4=r1+r12;        // writePtr-ticksize
    r2=r2+r8;        // bufferBase+bufferLength;
    comp(r4,r2);
    if ge jump AMF_Delay_DoFixup;
    r4=r0+r12;        // readPtr-ticksize
    comp(r4,r2);
    if ge jump AMF_Delay_DoFixup;
    jump AMF_Delay_AfterFixup;
AMF_Delay_DoFixup:

    i0=b0;        // i0=buffer base
    comp(r1,r0);    // compare writePtr and readPtr
    if ge jump AMF_Delay_GreaterEqual;
        m4=r8;
        r1=dm(m5,i0);        // buffer[0];
        dm(m4,i0)=r1;        // copied to the word after the end of the buffer
    jump AMF_Delay_AfterFixup;
AMF_Delay_GreaterEqual:
    r2=r2-r1;        // bufferBase+bufferLength-writePtr
    m4=r2;
    r1=dm(m4,i3);        // r1=in[1+bufferBase+bufferLength-writePtr]
    m4=r8;
    dm(m4,i0)=r1;    // copied to the word after the end of the buffer
AMF_Delay_AfterFixup:

    i0=s0;                // restore readPtr;

    bit set MODE1 PEYEN;
    m4=2;

    r12=lshift r12 by -1;

    lcntr=r12, do AMF_Delay_Loop until lce;
        r1=dm(i3,m4);                                // r1 = in[i/i+1];
        r0=dm(i0,m4);                                // r0 = delay[readPtr/readPtr+1];
        dm(i2,m4)=r0;                                // out=delayout
AMF_Delay_Loop:
        dm(i1,m4)=r1;                                // delay[writePtr/writePtr+1]=in, incr and wrap index

    bit clr MODE1 PEYEN;
    l1 = 0;
    l0 = 0;

    r0=i1;
    dm(AMF_Delay_DelayWritePtr,i4)=r0;                 // store away current delay pointer

    
 // pop context off stack
    b0=gets(1);
    b1=gets(2);
    i0=gets(3);
    i1=gets(4);
    i2=gets(5);
    i3=gets(6);
    mode1=gets(7);
    alter(7);

//------------------------------------------------------------------------------------
_AMF_Delay_Render.END:
    leaf_exit; // C-rth requires this instead of rts
//------------------------------------------------------------------------------------
    
.endseg;
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -