You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

529 lines
17KB

  1. # analog-filter.rb -- analog-filter.scm --> analog-filter.rb -*- snd-ruby -*-
  2. # Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net>
  3. # Created: Tue Aug 01 22:58:31 CEST 2006
  4. # Changed: Wed Nov 17 22:07:58 CET 2010
  5. # Commentary:
  6. #
  7. # ;;; various even order analog filters, based primarily on Anders Johansson's (GPL'd) code
  8. #
  9. # module Analog_filter
  10. # make_butterworth_lowpass(n, fc)
  11. # make_butterworth_highpass(n, fc)
  12. # make_butterworth_bandpass(n, fl, fh)
  13. # make_butterworth_bandstop(n, fl, fh)
  14. #
  15. # make_chebyshev_lowpass(n, fc, ripple = 1.0)
  16. # make_chebyshev_highpass(n, fc, ripple = 1.0)
  17. # make_chebyshev_bandpass(n, fl, fh, ripple = 1.0)
  18. # make_chebyshev_bandstop(n, fl, fh, ripple = 1.0)
  19. #
  20. # make_inverse_chebyshev_lowpass(n, fc, loss_dB = 60.0)
  21. # make_inverse_chebyshev_highpass(n, fc, loss_dB = 60.0)
  22. # make_inverse_chebyshev_bandpass(n, fl, fh, loss_dB = 60.0)
  23. # make_inverse_chebyshev_bandstop(n, fl, fh, loss_dB = 60.0)
  24. #
  25. # make_bessel_lowpass(n, fc)
  26. # make_bessel_highpass(n, fc)
  27. # make_bessel_bandpass(n, fl, fh)
  28. # make_bessel_bandstop(n, fl, fh)
  29. #
  30. # make_elliptic_lowpass(n, fc, ripple = 1.0, loss_dB = 60.0)
  31. # make_elliptic_highpass(n, fc, ripple = 1.0, loss_dB = 60.0)
  32. # make_elliptic_bandpass(n, fl, fh, ripple = 1.0, loss_dB = 60.0)
  33. # make_elliptic_bandstop(n, fl, fh, ripple = 1.0, loss_dB = 60.0)
  34. #
  35. # Code:
  36. require "clm"
  37. require "dsp"
  38. module Analog_filter
  39. def analog2digital(n, num, den, fz)
  40. g = 1.0
  41. wc = tan(PI * fz)
  42. wcc = wc * wc
  43. c = Vct.new(2 * n)
  44. j = 0
  45. k = 0
  46. 0.step(n - 1, 2) do |i|
  47. nt0 = num[j + 0] / wcc
  48. nt1 = num[j + 1] / wc
  49. nt2 = num[j + 2]
  50. dt0 = den[j + 0] / wcc
  51. dt1 = den[j + 1] / wc
  52. dt2 = den[j + 2]
  53. kd = dt0 + dt1 + dt2
  54. kn = nt0 + nt1 + nt2
  55. c[k + 0] = (2.0 * dt2 - 2.0 * dt0) / kd
  56. c[k + 1] = (dt0 + (-dt1) + dt2) / kd
  57. c[k + 2] = (2.0 * nt2 - 2.0 * nt0) / kn
  58. c[k + 3] = (nt0 + (-nt1) + nt2) / kn
  59. g *= (kn / kd)
  60. j += 3
  61. k += 4
  62. end
  63. a = []
  64. b = []
  65. k = 0
  66. 0.step(n - 1, 2) do |i|
  67. a.unshift(vct(c[k + 3], c[k + 2], c[k + 3]))
  68. b.unshift(vct(1.0, c[k], c[k + 1]))
  69. k += 4
  70. end
  71. [cascade2canonical(a).scale!(g), cascade2canonical(b)]
  72. end
  73. def prototype2highpass(n, num, den)
  74. g = 1.0
  75. numt = Vct.new(num.length)
  76. dent = Vct.new(den.length)
  77. i = 0
  78. 0.step(n - 1, 2) do |k|
  79. g *= (num[i + 2] / den[i + 2])
  80. numt[i + 0] = 1.0
  81. numt[i + 1] = num[i + 1] / num[i + 2]
  82. numt[i + 2] = num[i + 0] / num[i + 2]
  83. dent[i + 0] = 1.0
  84. dent[i + 1] = den[i + 1] / den[i + 2]
  85. dent[i + 2] = den[i + 0] / den[i + 2]
  86. i += 3
  87. end
  88. numt[0] = g
  89. [numt, dent]
  90. end
  91. #
  92. # === BUTTERWORTH ===
  93. #
  94. def butterworth_prototype(n)
  95. len = (n * 3) / 2
  96. num = Vct.new(len)
  97. den = Vct.new(len)
  98. n2 = 2.0 * n
  99. j = 0
  100. 1.step(n - 1, 2) do |w|
  101. num[j + 0] = 0.0
  102. num[j + 1] = 0.0
  103. num[j + 2] = 1.0
  104. den[j + 0] = 1.0
  105. den[j + 1] = 2.0 * cos((w * PI) / n2)
  106. den[j + 2] = 1.0
  107. j += 3
  108. end
  109. [num, den]
  110. end
  111. # n = order, fc = cutoff freq (srate = 1.0)
  112. add_help(:make_butterworth_lowpass,
  113. "make_butterworth_lowpass(n, fc): \
  114. returns a lowpass Buttterworth filter; N = order, \
  115. FC = cutoff freq (srate = 1.0): make_butterworth_lowpass(8, 0.1)")
  116. def make_butterworth_lowpass(n, fc)
  117. if n.odd? then n += 1 end
  118. proto = butterworth_prototype(n)
  119. coeffs = analog2digital(n, proto[0], proto[1], fc)
  120. make_filter(:xcoeffs, coeffs[0], :ycoeffs, coeffs[1])
  121. end
  122. add_help(:make_butterworth_highpass,
  123. "make_butterworth_highpass(n, fc): \
  124. returns a highpass Buttterworth filter; N = order, \
  125. FC = cutoff freq (srate = 1.0): make_butterworth_highpass(8, 0.1)")
  126. def make_butterworth_highpass(n, fc)
  127. if n.odd? then n += 1 end
  128. proto = butterworth_prototype(n)
  129. hproto = prototype2highpass(n, proto[0], proto[1])
  130. coeffs = analog2digital(n, hproto[0], hproto[1], fc)
  131. make_filter(:xcoeffs, coeffs[0], :ycoeffs, coeffs[1])
  132. end
  133. add_help(:make_butterworth_bandpass,
  134. "make_butterworth_bandpass(n, fl, fh): \
  135. returns a bandpass Buttterworth filter; N = order, \
  136. FL and FH are (1.0-based) edge freqs: make_butterworth_bandpass(4, 0.1, 0.2)")
  137. def make_butterworth_bandpass(n, fl, fh)
  138. lp = make_butterworth_lowpass(n, fh)
  139. hp = make_butterworth_highpass(n, fl)
  140. lambda do |y| filter(lp, filter(hp, y)) end
  141. end
  142. add_help(:make_butterworth_bandstop,
  143. "make_butterworth_bandstop(n, fl, fh): \
  144. returns a bandstop Buttterworth filter; N = order, \
  145. FL and FH are (1.0-based) edge freqs: make_butterworth_bandstop(4, 0.1, 0.2)")
  146. def make_butterworth_bandstop(n, fl, fh)
  147. lp = make_butterworth_lowpass(n, fl)
  148. hp = make_butterworth_highpass(n, fh)
  149. lambda do |y| filter(lp, y) + filter(hp, y) end
  150. end
  151. #
  152. # === CHEBYSHEV ===
  153. #
  154. # ripple in dB (positive)
  155. def chebyshev_prototype(n, ripple = 1.0)
  156. e = sqrt((10.0 ** (0.1 * ripple)) - 1.0)
  157. v0 = asinh(1.0 / e) / n.to_f
  158. len = (n * 3) / 2
  159. n2 = 2.0 * n
  160. sinhv0 = sinh(v0)
  161. coshv0 = cosh(v0)
  162. num = Vct.new(len)
  163. den = Vct.new(len)
  164. j = 0
  165. 1.step(n - 1, 2) do |l|
  166. lpi = l * PI
  167. u = -(sinhv0 * sin(lpi / n2))
  168. w = coshv0 * cos(lpi / n2)
  169. num[j + 0] = 0.0
  170. num[j + 1] = 0.0
  171. num[j + 2] = 1.0
  172. den[j + 0] = 1.0
  173. den[j + 1] = -2.0 * u
  174. den[j + 2] = u * u + w * w
  175. j += 3
  176. end
  177. num[2] = (2.0 ** (2 - n)) / (3.2 ** (log(ripple) / log(10.0)))
  178. [num, den]
  179. end
  180. # n = order, fc = cutoff freq (srate = 1.0)
  181. add_help(:make_chebyshev_lowpass,
  182. "make_chebyshev_lowpass(n, fc, ripple=1.0): \
  183. returns a lowpass Chebyshev filter; N = order, \
  184. FC = cutoff freq (srate = 1.0): make_chebyshev_lowpass(8, 0.1)")
  185. def make_chebyshev_lowpass(n, fc, ripple = 1.0)
  186. if n.odd? then n += 1 end
  187. proto = chebyshev_prototype(n, ripple)
  188. coeffs = analog2digital(n, proto[0], proto[1], fc)
  189. make_filter(:xcoeffs, coeffs[0], :ycoeffs, coeffs[1])
  190. end
  191. add_help(:make_chebyshev_highpass,
  192. "make_chebyshev_highpass(n, fc, ripple=1.0): \
  193. returns a highpass Chebyshev filter; N = order, \
  194. FC = cutoff freq (srate = 1.0): make_chebyshev_highpass(8, 0.1, 0.01)")
  195. def make_chebyshev_highpass(n, fc, ripple = 1.0)
  196. if n.odd? then n += 1 end
  197. proto = chebyshev_prototype(n, ripple)
  198. hproto = prototype2highpass(n, proto[0], proto[1])
  199. coeffs = analog2digital(n, hproto[0], hproto[1], fc)
  200. make_filter(:xcoeffs, coeffs[0], :ycoeffs, coeffs[1])
  201. end
  202. add_help(:make_chebyshev_bandpass,
  203. "make_chebyshev_bandpass(n, fl, fh, ripple=1.0): \
  204. returns a bandpass Chebyshev filter; N = order, \
  205. FL and FH = edge freq (srate = 1.0): make_chebyshev_highpass(8, 0.1, 0.01)")
  206. def make_chebyshev_bandpass(n, fl, fh, ripple = 1.0)
  207. lp = make_chebyshev_lowpass(n, fh, ripple)
  208. hp = make_chebyshev_highpass(n, fl, ripple)
  209. lambda do |y| filter(lp, filter(hp, y)) end
  210. end
  211. add_help(:make_chebyshev_bandstop,
  212. "make_chebyshev_bandstop(n, fl, fh, ripple=1.0): \
  213. returns a bandstop Chebyshev filter; N = order, \
  214. FL and FH = edge freqs (srate = 1.0): make_chebyshev_bandstop(8, 0.1, 0.4, 0.01)")
  215. def make_chebyshev_bandstop(n, fl, fh, ripple = 1.0)
  216. lp = make_chebyshev_lowpass(n, fl, ripple)
  217. hp = make_chebyshev_highpass(n, fh, ripple)
  218. lambda do |y| filter(lp, y) + filter(hp, y) end
  219. end
  220. #
  221. # === INVERSE CHEBYSHEV ===
  222. #
  223. def inverse_chebyshev_prototype(n, loss_dB = 60.0)
  224. e = sqrt(1.0 / (10.0 ** (0.1 * loss_dB) - 1.0))
  225. v0 = asinh(1.0 / e) / n.to_f
  226. len = (n * 3) / 2
  227. n2 = 2.0 * n
  228. num = Vct.new(len)
  229. den = Vct.new(len)
  230. pl = 0.0
  231. j = 0
  232. 1.0.step(n - 1, 2.0) do |l|
  233. lpi = l * PI
  234. u = -(sinh(v0) * sin(lpi / n2))
  235. w = cosh(v0) * cos(lpi / n2)
  236. t = 1.0 / sin(((l + pl) * PI) / n2)
  237. num[j + 0] = 1.0
  238. num[j + 1] = 0.0
  239. num[j + 2] = t * t
  240. den[j + 0] = 1.0
  241. den[j + 1] = (-2.0 * u) / (u * u + w * w)
  242. den[j + 2] = 1.0 / (u * u + w * w)
  243. j += 3
  244. end
  245. [num, den, 1.122 ** -loss_dB]
  246. end
  247. # n = order, fc = cutoff freq (srate = 1.0)
  248. add_help(:make_inverse_chebyshev_lowpass,
  249. "make_inverse_chebyshev_lowpass(n, fc, loss_dB=60.0): \
  250. returns a lowpass inverse-Chebyshev filter; N = order, \
  251. FC = cutoff freq (srate = 1.0): make_inverse_chebyshev_lowpass(10, 0.4, 120)")
  252. def make_inverse_chebyshev_lowpass(n, fc, loss_dB = 60.0)
  253. if n.odd? then n += 1 end
  254. proto = inverse_chebyshev_prototype(n, loss_dB)
  255. coeffs = analog2digital(n, proto[0], proto[1], fc)
  256. make_filter(:xcoeffs, coeffs[0].scale!(proto[2]), :ycoeffs, coeffs[1])
  257. end
  258. add_help(:make_inverse_chebyshev_highpass,
  259. "make_inverse_chebyshev_highpass(n, fc, loss_dB=60.0): \
  260. returns a highpass inverse-Chebyshev filter; N = order, \
  261. FC = cutoff freq (srate = 1.0): make_inverse_chebyshev_highpass(10, 0.1, 120)")
  262. def make_inverse_chebyshev_highpass(n, fc, loss_dB = 60.0)
  263. if n.odd? then n += 1 end
  264. proto = inverse_chebyshev_prototype(n, loss_dB)
  265. hproto = prototype2highpass(n, proto[0], proto[1])
  266. coeffs = analog2digital(n, hproto[0], hproto[1], fc)
  267. make_filter(:xcoeffs, coeffs[0].scale!(proto[2]), :ycoeffs, coeffs[1])
  268. end
  269. add_help(:make_inverse_chebyshev_bandpass,
  270. "make_inverse_chebyshev_bandpass(n, fl, fh, loss_dB=60.0): \
  271. returns a bandpass inverse-Chebyshev filter; N = order, \
  272. FL and FH are edge freqs (srate = 1.0): make_inverse_chebyshev_bandpass(8, 0.1, 0.4)")
  273. def make_inverse_chebyshev_bandpass(n, fl, fh, loss_dB = 60.0)
  274. lp = make_inverse_chebyshev_lowpass(n, fh, loss_dB)
  275. hp = make_inverse_chebyshev_highpass(n, fl, loss_dB)
  276. lambda do |y| filter(lp, filter(hp, y)) end
  277. end
  278. add_help(:make_inverse_chebyshev_bandstop,
  279. "make_inverse_chebyshev_bandstop(n, fl, fh, loss_dB=60.0): \
  280. returns a bandstop inverse-Chebyshev filter; N = order, \
  281. FL and FH are edge freqs (srate = 1.0): make_inverse_chebyshev_bandstop(8, 0.1, 0.4, 90)")
  282. def make_inverse_chebyshev_bandstop(n, fl, fh, loss_dB = 60.0)
  283. lp = make_inverse_chebyshev_lowpass(n, fl, loss_dB)
  284. hp = make_inverse_chebyshev_highpass(n, fh, loss_dB)
  285. lambda do |y| filter(lp, y) + filter(hp, y) end
  286. end
  287. if provided? :gsl
  288. # requires with-gsl
  289. if defined? gsl_roots
  290. # gsl_roots isn't defined for ruby in snd-xen.c
  291. #
  292. # === BESSEL(-Thompson) ===
  293. #
  294. def fact(n)
  295. x = 1
  296. 2.upto(n) do |i| x *= i end
  297. x
  298. end
  299. def bessel_i(n)
  300. Vct.new(n + 1) do |i| fact(2 * n - i) / ((2 ** (n - i)) * fact(i) * fact(n - i)) end
  301. end
  302. def bessel_prototype(n)
  303. len = (n * 3) / 2
  304. num = Vct.new(len)
  305. den = Vct.new(len)
  306. b2 = bessel_i(n)
  307. p = gsl_roots(b2.to_a)
  308. p.map! do |x| x / (b2[0] ** (1.0 / n)) end
  309. j = 0
  310. 0.step(n - 1, 2) do |i|
  311. num[j + 0] = 0.0
  312. num[j + 0] = 0.0
  313. num[j + 2] = 1.0
  314. den[j + 0] = 1.0
  315. den[j + 0] = -2.0 * p[i].real
  316. den[j + 2] = (p[i] * p[i + 1]).real
  317. j += 3
  318. end
  319. [num, den]
  320. end
  321. add_help(:make_bessel_lowpass,
  322. "make_bessel_lowpass(n, fc): \
  323. returns a lowpass Bessel filter; N = order, \
  324. FC = cutoff freq (srate = 1.0): make_bessel_lowpass(4, 0.1)")
  325. def make_bessel_lowpass(n, fc)
  326. if n.odd? then n += 1 end
  327. proto = bessel_prototype(n)
  328. coeffs = analog2digital(n, proto[0], proto[1], fc)
  329. make_filter(:xcoeffs, coeffs[0], :ycoeffs, coeffs[1])
  330. end
  331. add_help(:make_bessel_highpass,
  332. "make_bessel_highpass(n, fc): \
  333. returns a highpass Bessel filter; N = order, \
  334. FC = cutoff freq (srate = 1.0): make_bessel_highpass(8, 0.1)")
  335. def make_bessel_highpass(n, fc)
  336. if n.odd? then n += 1 end
  337. proto = bessel_prototype(n)
  338. hproto = prototype2highpass(n, proto[0], proto[1])
  339. coeffs = analog2digital(n, hproto[0], hproto[1], fc)
  340. make_filter(:xcoeffs, coeffs[0], :ycoeffs, coeffs[1])
  341. end
  342. add_help(:make_bessel_bandpass,
  343. "make_bessel_bandpass(n, fl, fh): \
  344. returns a bandpass Bessel filter; N = order, \
  345. FL and FH are edge freqs (srate = 1.0): make_bessel_bandpass(4, 0.1, 0.2)")
  346. def make_bessel_bandpass(n, fl, fh)
  347. lp = make_bessel_lowpass(n, fh)
  348. hp = make_bessel_highpass(n, fl)
  349. lambda do |y| filter(lp, filter(hp, y)) end
  350. end
  351. add_help(:make_bessel_bandstop,
  352. "make_bessel_bandstop(n, fl, fh): \
  353. returns a bandstop Bessel filter; N = order, \
  354. FL and FH are edge freqs (srate = 1.0): make_bessel_bandstop(8, 0.1, 0.2)")
  355. def make_bessel_bandstop(n, fl, fh, ripple = 1.0, loss_dB = 60.0)
  356. lp = make_bessel_lowpass(n, fl)
  357. hp = make_bessel_highpass(n, fh)
  358. lambda do |y| filter(lp, y) + filter(hp, y) end
  359. end
  360. end
  361. #
  362. # === ELLIPTIC ===
  363. #
  364. def minimize_function(f, xmin, xmax, arg1 = nil, arg2 = nil)
  365. fx = snd_func(f, xmin, arg1, arg2)
  366. n = 20
  367. x = Vct.new(n)
  368. n.times do |i|
  369. step = (xmax - xmin) / (n - 1.0)
  370. s = xmin
  371. (n - 1).times do |j|
  372. x[j] = s
  373. s += step
  374. end
  375. x[n - 1] = xmax
  376. n.times do |j|
  377. ft = snd_func(f, x[j], arg1, arg2)
  378. if ft < fx
  379. fx = ft
  380. xmax = (j < (n - 1)) ? x[j + 1] : x[n - 1]
  381. xmin = j > 0 ? x[j - 1] : x[0]
  382. end
  383. end
  384. end
  385. (xmax + xmin) / 2.0
  386. end
  387. def findm(m, arg1, arg2)
  388. (gsl_ellipk(m) / gsl_ellipk(1.0 - m) - arg1).abs
  389. end
  390. def findv(u, arg1, arg2)
  391. vals = gsl_ellipj(u, arg1)
  392. (arg2 - vals[0] / vals[1]).abs
  393. end
  394. def elliptic_prototype(n, ripple = 1.0, loss_dB = 60.0)
  395. e = sqrt((10.0 ** (0.1 * ripple)) - 1.0)
  396. k1 = e / sqrt((10.0 ** (0.1 * loss_dB)) - 1.0)
  397. k1p = sqrt(1.0 - k1 * k1)
  398. kr = m = k = 0.0
  399. len = (n * 3) / 2
  400. num = Vct.new(len)
  401. den = Vct.new(len)
  402. g = 1.0
  403. eps = 0.0000001
  404. if (1.0 - k1p * k1p).abs > eps
  405. kr = n.to_f * (gsl_ellipk(k1 * k1) / gsl_ellipk(k1p * k1p))
  406. end
  407. m = minimize_function(:findm, 0.001, 0.999, kr)
  408. k = gsl_ellipk(m)
  409. cv = Vct.new((0.5 * 3 * (n + 1)).floor)
  410. j = 0
  411. 0.step(n - 1, 2) do |i|
  412. vals = gsl_ellipj(((i + 1) * k) / n.to_f, m)
  413. sn, cn, dn = vals[0..2]
  414. cv[j + 0] = sn
  415. cv[j + 1] = cn
  416. cv[j + 2] = dn
  417. z = Complex(0.0, -1.0) / (sqrt(m) * sn)
  418. pz = (z * make_rectangular(z.real, -z.imag)).real
  419. g /= pz
  420. num[j + 0] = 1.0
  421. num[j + 1] = -2.0 * z.real
  422. num[j + 2] = pz
  423. j += 3
  424. end
  425. optarg0 = k1p * k1p
  426. optarg1 = 1.0 / e
  427. minf = minimize_function(:findv, 0.0, 1.0 / e, optarg0, optarg1)
  428. v0 = (k * minf) / (n.to_f * gsl_ellipk(k * k1))
  429. vals = gsl_ellipj(v0, 1.0 - m)
  430. sn, cn, dn = vals[0..2]
  431. j = 0
  432. 0.step(n - 1, 2) do |i|
  433. p = -(cv[j + 1] * cv[j + 2] * sn * cn + (Complex(0.0, 1.0) * cv[j + 0] * dn)) /
  434. (1.0 - (cv[j + 2] * sn * cv[j + 2] * sn))
  435. pp = (p * make_rectangular(p.real, -p.imag)).real
  436. g *= pp
  437. den[j + 0] = 1.0
  438. den[j + 1] = -2.0 * p.real
  439. den[j + 2] = pp
  440. j += 3
  441. end
  442. g = (g / sqrt(1.0 + e * e)).abs
  443. [num, den, g]
  444. end
  445. # n = order, fc = cutoff freq (srate = 1.0)
  446. add_help(:make_elliptic_lowpass,
  447. "make_elliptic_lowpass(n, fc, ripple=1.0, loss_dB=60.0): \
  448. returns a lowpass elliptic filter; N = order, \
  449. FC = cutoff freq (srate = 1.0): make_elliptic_lowpass(8, 0.25, 0.01, 90)")
  450. def make_elliptic_lowpass(n, fc, ripple = 1.0, loss_dB = 60.0)
  451. if n.odd? then n += 1 end
  452. proto = elliptic_prototype(n, ripple, loss_dB)
  453. coeffs = analog2digital(n, proto[0], proto[1], fc)
  454. make_filter(:xcoeffs, coeffs[0].scale!(proto[2]), :ycoeffs, coeffs[1])
  455. end
  456. add_help(:make_elliptic_highpass,
  457. "make_elliptic_highpass(n, fc, ripple=1.0, loss_dB=60.0): \
  458. returns a highpass elliptic filter; N = order, \
  459. FC = cutoff freq (srate = 1.0): make_elliptic_highpass(8, 0.25, 0.01, 90)")
  460. def make_elliptic_highpass(n, fc, ripple = 1.0, loss_dB = 60.0)
  461. if n.odd? then n += 1 end
  462. proto = elliptic_prototype(n, ripple, loss_dB)
  463. hproto = prototype2highpass(n, proto[0], proto[1])
  464. coeffs = analog2digital(n, hproto[0], hproto[1], fc)
  465. make_filter(:xcoeffs, coeffs[0].scale!(proto[2]), :ycoeffs, coeffs[1])
  466. end
  467. add_help(:make_elliptic_bandpass,
  468. "make_elliptic_bandpass(n, fl, fh, ripple=1.0, loss_dB=60.0): \
  469. returns a bandpass elliptic filter; N = order, \
  470. FL and FH are edge freqs (srate = 1.0): make_elliptic_bandpass(6, 0.1, 0.2, 0.1, 90)")
  471. def make_elliptic_bandpass(n, fl, fh, ripple = 1.0, loss_dB = 60.0)
  472. lp = make_elliptic_lowpass(n, fh, ripple, loss_dB)
  473. hp = make_elliptic_highpass(n, fl, ripple, loss_dB)
  474. lambda do |y| filter(lp, filter(hp, y)) end
  475. end
  476. add_help(:make_elliptic_bandstop,
  477. "make_elliptic_bandstop(n, fl, fh, ripple=1.0, loss_dB=60.0): \
  478. returns a bandstop elliptic filter; N = order, \
  479. FL and FH are edge freqs (srate = 1.0): make_elliptic_bandstop(6, 0.1, 0.2, 0.1, 90)")
  480. def make_elliptic_bandstop(n, fl, fh, ripple = 1.0, loss_dB = 60.0)
  481. lp = make_elliptic_lowpass(n, fl, ripple, loss_dB)
  482. hp = make_elliptic_highpass(n, fh, ripple, loss_dB)
  483. lambda do |y| filter(lp, y) + filter(hp, y) end
  484. end
  485. end
  486. end
  487. include Analog_filter
  488. # analog-filter.rb ends here