首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Goertzel算法实现

Goertzel算法实现

Goertzel基本算法在每次采样后立即进行处理,在每个第N次采样进行一次音调检测。在采用FFT算法时,我们要对成块的采样进行处理,但这并不意味着必须按块来处理数据。数字处理的时间很短,因此如果每次采样都存在一次中断,那么这些数字处理完全可以在中断服务程序(ISR)内完成。或者,如果系统中存在采样缓存,那么可以持续采样,然后进行批处理。

在真正运行Goertzel算法之前,必须进行下面的初步计算:

1. 决定采样率;

2. 选择块大小,即N;

3. 预先进行一次余弦和正弦计算;

4. 预先计算一个系数。

这些计算均可以预先完成,然后硬编码到程序中,从而节省RAM和ROM空间,也可以动态方式计算。

选择合适的采样率

实际上,采样率可能已经由应用本身决定了。例如,在电信应用中普遍采用8kHz的采样率,即每秒8,000个采样。又如,模数转换器(或编解码器)的工作频率可能是由一个我们无法控制的外部时钟或外部晶振决定。

但如果我们可以选择采样率,那么就必须遵循奈奎斯特采样定理:采样率至少不低于最高信号频率的两倍。这是是因为如果我们要检测多个频率,那么采用更高的采样率可能会得到更好的结果。而且我们都希望采样率与每一个感兴趣的频率之间均呈整数倍关系。

块大小的设置

Goertzel算法中的块大小N与相应的FFT中的点数类似,它控制了频率分辨率的大小。例如,若采样率为8kHz,而N为100个采样,那么频率分辨率就是80Hz。

这就可能使我们为了获取最大的频率分辨率而尽量将N取高。然而N越大,检测到每个音调所需的时间就越多,因为我们必须等所有这N个采样都完成后才能开始处理。例如,采样率为8kHz时,累积800个采样需要100ms。若想缩短检测音调的时间,就必须适当调整N的值。

影响N的选择的另一个因素是采样率和目标频率之间的关系。比较理想情况是目标频率在相应的频率分辨率的中点范围内,也就是说,我们希望目标频率是sample_rate/N比值的整数倍。值得庆幸的是,Goertzel算法中的N与FFT中不同,不必是2的整数次幂。

预计算常数

在采样率和块大小确定之后,只须通过下面5个简单的计算来得出处理时所需要的常数:
k = (N*target_freq)/sample_tate
w = (2*π/N)*k
cosine = cos w
sine = sin w
coeff = 2 * cosine
每一次采样处理中都需要3个变量,我们称其为Q0'、Q1'和Q2。Q1是前一次采样处理的Q0值,Q2是在两次采样前的Q0值(或Q1在本次采样前的值)。

在每个采样块的开始时,都必须将Q1和Q2初始化为0。每个采样都需要按照下面三个等式进行计算:

Q0 = coeff * Q1 - Q2 + sample
Q2 = Q1
Q1 = Q0
在进行N次预采样计算之后,可以检测到音调是否存在。

real = (Q1 - Q2 * cosine)
imag = (Q2 * sine)
magnitude2 = real2 + imag2
这时只需进行一次简单的幅度门限测试就可以判断出是否有音调存在。之后,将Q2和Q1复位到0,开始下一个块的处理。

Goertzel优化算法

Goertzel优化算法比Goertzel基本算法所需的计算量小,但这是以损失相位信息为代价。

在Goertzel优化算法中每个采样处理完全一样,但处理的结果与Goertzel基本算法不同。在Goertzel基本算法中,通常需要计算信号的实部和虚部,然后将实部和虚部的计算结果转换为相应的幅度平方。而在优化Goertzel算法中则不需计算实部和虚部,直接计算下式:

magnitude2 = Q1^2 +Q2^2-Q1*Q2*coeff
继承事业,薪火相传
好帖子,路过帮顶,学习了
返回列表