滤波器设计,在特定音频频率下寻找能量



我正在将Meinard müller和Sebastien Ewert的Matlab"Chroma Toolbox"改编并扩展为python。它旨在检测音频记录的每个分析帧中存在的音高。

第一步是确定音乐的调谐,Chroma Toolbox测试音乐是在标准A=440Hz下调谐,还是在半音的四分之一、三分之一、一半、三分之二或四分之三下调谐。这没关系,但在我的应用程序中,我需要在调优检测方面有更高的分辨率。

一旦从这些选择中的一个中选择了调谐,就选择了相应的滤波器组,该滤波器组用于找出在钢琴的范围内每个音高处有多少能量。(此外,波形被重新采样到22050、4410和882Hz)

滤波器组的系数存储在由Chroma Toolbox提供的.mat文件中。例如,用于检测标准调谐中间C(261.63Hz)处的能量的系数为b=[1.,-7.43749873,24.72954997,-47.94740681,59.25189976,-47.77885707、24.55599193、-7.35933913、0.98601284]和a=[000314443、-0.02341175、0.07794208、-0.115134062、0.18733283、-0.1151340 62、0.0779420 8、-0.0234117、0.003414443],中间C的采样率为4410 Hz。

这些系数用于对filtfilt的调用:我使用scipy.signal.filt(b,a,x),其中x是适当采样频率下的波形,低音为低,高音为高。此步骤在文件"audio_to_pitch_via_FB.m"中完成。

问题:

因为我想允许与Chroma工具箱中设计的调谐级别不同的调谐级别,所以我需要制作自己的滤波器组,因此需要知道如何计算滤波器系数。为此,我需要一个函数coeffs(freq,fs),它将找到正确的系数,以找到给定频率freq下的能量,用于采样频率fs的信号。我该怎么做?

这是其中一个.mat文件的名称,以防它包含有用的线索。"MIDI_FB_ellip_pitch_60_96_22050_Q25_minusQuarter.mat"

生成过滤器的代码位于generateMultiratePitchFilterbank.m文件中。ellip函数以相反的方式返回a和b,但在其他方面基本相同。

以下配方再现了您引用的数字:

import numpy as np
import scipy.signal as ss
def coeffs(pitch, fs, Q=25, stop=2, Rp=1, Rs=50):
    """Calculate filter coeffs for a given pitch and sampling rate, fs.
    See their source code for description of Q, stop, Rp, Rs"""
    nyq = fs/2.                       # Nyquist frequency
    pass_rel = 1/(2.*Q)             
    stop_rel = pass_rel * stop
    # The min-max edges of the pass band
    Wp = np.array([pitch - pass_rel*pitch, pitch+pass_rel*pitch])/nyq
    # And the stop band(s)
    Ws = np.array([pitch - stop_rel*pitch, pitch+stop_rel*pitch])/nyq
    # Get the order, natural freq
    n, Wn = ss.ellipord(Wp, Ws, Rp, Rs)
    # Get a and b:
    a, b = ss.ellip(n, Rp, Rs, Wn, btype="bandpass")
    return a, b

最新更新