SHARC音频DSP的算法详解(八)Parameter EQ (PEQ)的实现及代码详解
作者的话
PEQ,常见的滤波器,在SHARC上怎么去做,请看下面的详解。
硬件准备
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++
PEQ的算法功能
实现参量均衡器(PEQ)的功能,包含两个部分:
1、计算 PEQ 的滤波器系数;
2、利用计算得到的滤波器系数对输入数据进行滤波处理。
原理简介
参量均衡器一般用于补偿声音信号中不足的频率成分,衰减过多的频率成
分。使用过程中有三个参数可以调:中心频率 fC、Q 值、增益值 Gain。下图为参量均衡器的示意图。

图A

图B
由图(b)可以计算出 Q 值:

数字参量均衡器可通过一个二阶的 IIR 滤波器来实现,其网络结构为:

其中滤波系数 a0 = 1, 其它 5 个系数有各种计算方法,下面是其中一种。


然后用 a0 对其它系数做归一化处理。
上述各式中,g 表示用户设置好的增益值(dB);Fc 为中心频率,Fs 为系
统的采样率; Q 即为参量均衡的 Q 值,由前面(1)式确定。
资源占用(MIPS, Memory requirement).
Memory: dm 数据段(段名 PEQVar_dmda), 5* NSECTIONS+1words (字长 32bits)
pm 数据段(段名 PEQCoef_pmda),5*NSECTIONS words (字长 32bits)
代码段(段名 PEQ_pmco),0x 113words (字长 48bits)
MFLOPS(1 个 PEQ 处理 1 个数据): EQFilter 函数,0.0002
相关函数
函数一:int CalulateEQParam(float pm *coeffs, int sections, int Fs,
float *fcPtr, float *QPtr, float *GainPtr);
1.函数说明:根据 PEQ 的 3 个参数(中心频率、Q 值、增益)计算
滤波器系数
2.输入参数:
fcPtr, 中心频率指针,中心频率范围:20~20000Hz
QPtr, Q 值指针, Q 值范围:0.5~32
GainPtr,增益值指针,以 dB 表示,增益值范围:-20~20
sections, PEQ 个数
Fs,采样频率
3.输出参数:
coeffs, 计算出来的滤波器系数
4.返回值:
0 正常
1 fc 超出范围
2 Q 超范围
3 增益超范围
函数二:InitEQFilter(float dm *state, int nstate);
1.函数说明:初始化 EQ 滤波器的中间延时缓冲区数据
2.输入参数:
state:滤波过程中的数据延时缓冲区
nstate:滤波过程中的延时缓冲大小
3.输出参数:无
4.返回值:无
函数三: EQFilter(float *in, float *out, float pm *coeffs, float dm *state,
int samples, int sections);
1.函数说明:根据 PEQ 滤波器系数对输入数据进行滤波
2.输入参数:
in 输入数据指针
state,滤波过程中的数据延时缓冲区
coeffs,PEQ 滤波器系数
samples,输入数据长度
sections,PEQ 个数
3.输出参数:
out 输出数据指针。
4.返回值:无
应用举例
首先将 PEQfilter.dlb, PEQfilter.h 两个文件拷贝到自己的工程目录下,然后将它们添加到工程中;然后在 LDF 文件中给数据段 PEQVar_dmda、PEQCoef_pmda,程序段PEQ_pmco 分配空间,接下来再写相关代码。
#include “PEQfilter.h”
/******************************************************************************
- 调用 PEQfilter.dlb 库函数需定义的参数
****************************************************************************/
#define NSECTIONS 2 // PEQ 个数
#define NSAMPLES 512 // 需处理的数据个数
#define NSTATE ((2NSECTIONS)+1) // 滤波过程中的延时缓冲大小
#define FS 48000 // 采样率
#pragma section (“PEQVar_dmda”)
float state[NSTATE]; // PEQ 滤波的中间延时缓冲数据
// 预设的滤波器系数. 如果是用 MALAB 直接算出来的滤波系数,则按以下方法排列系数。
#pragma section (“PEQCoef_pmda”)
// -a2, -a1, b2, b1, b0
float pm coeffs[5NSECTIONS]={-0.7474,1.7259,0.8143, -1.6285,0.8143};
// PEQ 的 3 个参数
#pragma section (“PEQVar_dmda”)
float CenterFc[NSECTIONS]; // 中心频率
#pragma section (“PEQVar_dmda”)
float QValue[NSECTIONS]; // Q 值
#pragma section (“PEQVar_dmda”)
float Gain_dBValue[NSECTIONS]; // 以 dB 表示的增益值
// 输入输出数组
float InputData[NSAMPLES]={0};
float OutputData[NSAMPLES]={0};
// 如果 PEQ 的参数需更新,则重新计算滤波器系数
if (New_Parameter_Flag)
{
CenterFc[0] = 1000; // 设置 PEQ 的中心频率
CenterFc[1] = 2000; // 设置 PEQ 的中心频率
QValue[0] = 10; // 设置 Q 值
QValue[1] = 32; // 设置 Q 值
Gain_dBValue[0] = -22; // 设置增益值, 单位为 dB
Gain_dBValue[1] = -10; // 设置增益值, 单位为 dB
// 计算 PEQ 的滤波器系数,存储到全局变量 coeffs 数组。
ErrFlag = CalulateEQParam(coeffs, NSECTIONS, FS, CenterFc, QValue,
Gain_dBValue);
New_Parameter_Flag = 0;
}
// 第一次调用 PEQ 滤波之前先做初始化工作
if (FirstPEQ_Flag)
{
InitEQFilter(state, NSTATE);
FirstPEQ_Flag = 0;
} //对输入数据进行 PEQ 滤波处理
EQFilter(InputData,OutputData,coeffs, state, NSAMPLES, NSECTIONS);
更多推荐



所有评论(0)