作者的话
延时是非常常见的一种音频上的算法,而在ADI的SAHRC DSP中,可以很好的去实现,我们来看看是怎么做的。
硬件准备
ADSP-21489EVB:ADI 21489 DSP的开发板
产品链接:https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-5192690539.13.3cd16938GrbRa1&id=539694123232
AD-HP530ICE:ADI DSP通用仿真器
产品链接:https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-5192690539.11.27e0bfa3NS4TTS&id=38007242820
软件准备
Visual DSP++
Reverb Delay算法功能
通过简单的延时反馈方法实现混响或回声效果。
原理简介
如下图所示,原始信号与一个 IIR 梳状滤波器结合,通过调整延时及增益
参数来获得不同的效果。
系统函数为:
差分方程:
资源占用(MIPS, Memory requirement).
Memory: 数据段(段名 ReverbDelay_dmda)
(BufLengthL + BufLengthR)+8words (字长 32bits)
BufLengthL、BufLengthR 分别指左右延时缓冲区长度
代码段(段名 ReverbDelay_pmco),0x ee words (字长 48bits)
MFLOPS(处理左右声道各 1 个点): ReverbDelay 函数,0.00129
相关函数
函数一:InitReverbDelay(int *BufL, int *BufR, unsigned int *BufSize)
1.函数说明:初始化函数,将延时缓冲区置零。
2.输入参数:无
BufL 左声道延时缓冲区指针
BufR 右声道延时缓冲区指针
BufSize 左右声道延时缓冲区的长度
*BufSize 为左声道延时缓冲区长度;
*(BufSize+1)为右声道延时缓冲区长度;
3.输出参数:无
4.全局变量:
DelayBufPtrL、DelayBufPtrR 左右声道延时缓冲区指针。
DelayBufIndexL、DelayBufIndexR 往左右声道缓冲区写数据的索
引值。
DepthL、DepthR 左右声道延时缓冲区大小。
以上全局变量初始化以后,用于 ReverbDelay 函数。
5.返回值:无。
函数二:ReverbDelay(int *in, int *out, int DelaySampleNum, float
*Gain)
1.函数说明:将输入信号与延时反馈信号叠加产生混响或回声
2.输入参数:
in 输入数据指针。
*in 为左声道数据;
*(in+1)为右声道数据;
数据范围:int 类型表示的范围
DelaySampleNum 延时样本点参数指针。
*DelaySampleNum 左声道的延时样本点数;
*(DelaySampleNum + 1)右声道的延时样本点数。
数据范围:由 DepthL、DepthR 大小确定。
Gain 增益系数
*Gain 增益系数 a;
*(Gain+ 1)增益系数 b;
*(Gain+ 2)增益系数 c。
数据范围:0≤ a < 1;0≤(b,c) ≤1
3.输出参数:
out 输出数据指针。
*out 为左声道数据;
*(out+1)为右声道数据;
数据范围:int 类型表示的范围
4.返回值: 0 为正常;
1 延时参数超范围
2 增益参数超范围
3 延时及增益参数均超范围
应用举例
首先将 ReverbDelay.dlb, ReverbDelay.h 两个文件拷贝到自己的工程目录下,然后将它们添加到工程中;然后在 LDF 文件中给数据段ReverbDelay_dmda、程序段 ReverbDelay_pmco分配空间,接下来再写相关代码。
#include " ReverbDelay.h"
#define NUM_SAMPLES 512 //输入数据块长度
/*************************************************************************
- 调用 ReverbDelay.dlb 库函数需定义的参数
*************************************************************************/
// 延时的宏定义
#define DLine 4000 // Total Delay = DLine/fs 秒
// 定义两个声道的延时缓冲区大小
#define BufLengthL DLine
#define BufLengthR DLine
// 两个声道的延时缓冲区
#pragma section (“ReverbDelay_dmda”)
int DelayBufL[BufLengthL + 1];
#pragma section (“ReverbDelay_dmda”)
int DelayBufR[BufLengthR + 1];
// 两个延时缓冲区的长度
unsigned int BufLength[2] = { BufLengthL, BufLengthR };
float GainCoef[3] = {0.5, 0.7, 1}; // 增益系数,按顺序对应 a,b,c
int InputData[2]={0};
int OutputData[2]={0};
InitReverbDelay(DelayBufL, DelayBufR,BufLength); //初始化函数,此函数只调用一次。
for (i=0; i<NUM_SAMPLES; i++)
{
//取左声道数据
InputData[0] = (block_ptr+2i); // block_ptr 是 A/D D/A 收发数据的指针
//取右声道数据
InputData[1] = (block_ptr+2i + 1);
//对输入数据进行延时处理
ReverbDelay(InputData, OutputData, DelayNum, GainCoef);
//将处理后的左声道输出数据传给 D/A
(block_ptr+2i) = OutputData[0];
//将处理后的右声道输出数据传给 D/A
(block_ptr+2i 面+ 1) = OutputData[0];
}