/// script dependencies = [ "matplotlib", "scipy", ] ///
12import argparse 13from math import pi 14 15import matplotlib.pyplot as plt 16import numpy as np 17from scipy.signal import freqz, remez 18 19 20def main(): 21 args = parse_args() 22 23 weight_pb = 1 - 10 ** (-args.pbr / 20) 24 weight_sb = 10 ** (-args.sba / 20) 25 coefficients = remez( 26 args.n, 27 [0, args.fp, args.fe, args.fs / 2], 28 [1, 0], 29 weight=[weight_pb, weight_sb], 30 fs=args.fs, 31 ) 32 print([float(coeff) for coeff in coefficients]) 33 34 w, h = freqz(coefficients, worN=1 << 20) 35 36 figure = plt.figure() 37 axes = figure.add_subplot( 38 title="Filter Frequency Response", 39 xlabel="Frequency (Hz)", 40 ylabel="Gain (dB)", 41 xlim=(0, 40000), 42 ylim=(-80, 20), 43 ) 44 axes.grid(visible=True) 45 46 axes.plot(w * (args.fs / 2) / pi, 20 * np.log10(abs(h))) 47 axes.plot(2 * [24000], [-100, 100]) 48 axes.plot([0, args.fs], 2 * [-3]) 49 50 plt.show(block=True) 51 52 53def parse_args(): 54 arg_parser = argparse.ArgumentParser( 55 description="Generate a FIR low-pass filter using the Remez exchange algorithm" 56 ) 57 arg_parser.add_argument( 58 "-fs", type=float, required=True, help="Source frequency (Hz)" 59 ) 60 arg_parser.add_argument("-n", type=int, required=True, help="Number of taps") 61 arg_parser.add_argument( 62 "-fp", 63 default=16000, 64 type=float, 65 required=False, 66 help="Transition band start frequency (Hz) (default=16000)", 67 ) 68 arg_parser.add_argument( 69 "-fe", 70 default=24000, 71 type=float, 72 required=False, 73 help="Stopband edge frequency (Hz) (default=24000)", 74 ) 75 arg_parser.add_argument( 76 "-pbr", 77 default=0.1, 78 type=float, 79 required=False, 80 help="Desired passband ripple (dB) (default=0.1)", 81 ) 82 arg_parser.add_argument( 83 "-sba", 84 default=60, 85 type=float, 86 required=False, 87 help="Desired stopband attenuation (dB) (default=60)", 88 ) 89 return arg_parser.parse_args() 90 91 92if __name__ == "__main__": 93 main()