lasp/src/lasp/filter/fir_design.py

87 lines
2.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""!
Author: J.A. de Jong - ASCEE
Description: Designs octave band FIR filters from 16Hz to 16 kHz for a sampling
frequency of 48 kHz.
"""
# from asceefigs.plot import Bode, close, Figure
__all__ = ['freqResponse', 'bandpass_fir_design', 'lowpass_fir_design',
'arbitrary_fir_design']
import numpy as np
from scipy.signal import freqz, hann, firwin2
def freqResponse(fs, freq, coefs_b, coefs_a=1.):
"""
Computes the frequency response of the filter defined with the filter
coefficients:
Args:
fs: Sampling frequency [Hz]
freq: Array of frequencies to compute the response for
coefs_b: Forward coefficients (FIR coefficients)
coefs_a: Feedback coefficients (IIR)
Returns:
Complex frequency response for frequencies given in array
"""
Omg = 2*np.pi*freq/fs
w, H = freqz(coefs_b, coefs_a, worN=Omg)
return H
def bandpass_fir_design(L, fs, fl, fu, window=hann):
"""
Construct a bandpass filter
"""
assert fs/2 > fu, "Nyquist frequency needs to be higher than upper cut-off"
assert fu > fl, "Cut-off needs to be lower than Nyquist freq"
Omg2 = 2*np.pi*fu/fs
Omg1 = 2*np.pi*fl/fs
fir = np.empty(L, dtype=float)
# First Create ideal band-pass filter
fir[L//2] = (Omg2-Omg1)/np.pi
for n in range(1, L//2):
fir[n+L//2] = (np.sin(n*Omg2)-np.sin(n*Omg1))/(n*np.pi)
fir[L//2-n] = (np.sin(n*Omg2)-np.sin(n*Omg1))/(n*np.pi)
win = window(L, True)
fir_win = fir*win
return fir_win
def lowpass_fir_design(L, fs, fc, window=hann):
assert fs/2 > fc, "Nyquist frequency needs to be higher" \
" than upper cut-off"
Omgc = 2*np.pi*fc/fs
fir = np.empty(L, dtype=float)
# First Create ideal band-pass filter
fir[L//2] = Omgc/np.pi
for n in range(1, L//2):
fir[n+L//2] = np.sin(n*Omgc)/(n*np.pi)
fir[L//2-n] = np.sin(n*Omgc)/(n*np.pi)
win = window(L, True)
fir_win = fir*win
return fir_win
def arbitrary_fir_design(fs, L, freq, amps, window='hann'):
"""
Last frequency of freq should be fs/2
"""
return firwin2(L, freq, amps, fs=fs, window=window)