I Wrote a bessel filter function
Wolfgang Heidrich <[email protected]> Sun, 29 Jul 2007 19:27:40 +0200
| Newsgroups | gmane.comp.gnu.octave.sources |
|---|---|
| Organization | Privat |
| Message-ID | <[email protected]> |
--Boundary-00=_M4MrGX3Zvma0O70
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Dear all,
I used octave to write some code to compute the coefficients of the
transferfunction of a bessel filter, because I couldn't find these
coefficients in the web. The reverse bessel polynomial is splitted in
quadratic terms using the roots() function, I also normalize the function so
that it is useful for filter design (3dB cutoff at frequency=1*i). Quadratic
terms are good for designing signal filters with operational amplifiers in
electrical engineering.
As I'm new to octave I don't know if I did it in the optimal way. On
http://www.hw-loesungen.de/besselfilter.pdf you can find the mathematical
background I used to write that code. Here is the code, you can include it in
Octave.
With this code you can generate the coefficients for bessel filters with as
many poles as you like, only restricted by numerical accuracy.
Further I would like to thank all people who contributed to octave, it is
great!
Best,
Wolfgang
--
Wolfgang A. Heidrich
--Boundary-00=_M4MrGX3Zvma0O70
Content-Type: text/x-objcsrc;
charset="us-ascii";
name="bessel.m"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="bessel.m"
## Copyright (C) 2007 Wolfgang A. Heidrich
##
## This is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## -*- texinfo -*-
## @deftypefn {Function File} {} bessel (@var{n})
##
## For a scalar @var{n}, return
## the coefficients of the quadratic terms of the
## factorized reverse bessel polynomial B(s), normalized so that B(i)=sqrt(2).
## @iftex
## @tex
## $$
## B(s)= (1+a_{1}x+b_{1}x^{2})(1+a_{2}x+b_{2}x^{2})(1+a_{3}x+b_{3}x^{2})\ldots
## $$
## @end tex
## @end iftex
## @ifinfo
##
## @example
## B(s)= (1 + a(1) * x + b(1)*x^2) * (1 + a(2) * x + b(2)*x^2) * ...
## @end example
## @end ifinfo
## @end deftypefn
## Author: Wolfgang Arne Heidrich
## Created: 29 July 2007
## Read http://www.hw-loesungen.de/besselfilter.pdf
## to understand how this code works.
function [a,b] = bessel (arg)
if ( (nargout!=2) || (nargin != 1) || (size(arg)(1)!=1)
|| (size(arg)(2)!=1)
)
usage ("[a,b]=bessel(n) where n is an integer number");
endif
n=arg(1);
printf("Bessel polynomial number of poles: %d\n", n );
% printf(" %2d */ ", n );
% First we generate the bessel polynomial using the recursive formula
% v(n-ind+1) = 2*(n-ind+1)*cf/ind/(2*n-ind+1);
cz=1;cn=1; % to be calculated coefficients as integernumbers
cf=1; % to be calculated coefficients as floating numbers
puts("c0=1\nc1=1\n");
v(n)=1;
v(n+1)=1;
for ind=2:n
cz = 2*(n-ind+1)*cz;
cn = ind*(2*n-ind+1)*cn;
cf = 2*(n-ind+1)*cf/ind/(2*n-ind+1);
% just for fun we also calculate the fraction with integer
% numerator cz and demoninator cn
if( cz<cn ) min=cz; else min=cn; end;
w=sqrt(min)+1;
for k=2:w
while( (rem(cz,k)==0) && (rem(cn,k)==0) )
cz=cz/k;
cn=cn/k;
end
end
% Here I print out the integer numerator cz and demoninator cn,
% that aren't used further.
printf("c%i=%i/%i=%g\n", ind, cz, cn,cf );
%v(n-ind+1)=cz/cn;
v(n-ind+1)=cf;
end
puts("\n");
r=roots(v); % these are the roots of the polynomial
% Now we want to find the 3dB-Frequency omega of this filter.
% i must be here the imaginary unit sqrt(-1) !
omega=0;
while( abs(polyval( v,i*omega ) ) < 2 )
omega++;
end
w2 = sqrt(2);
xa=0;xb=omega;
diff = 1;
count=0;
while( abs(diff) > 1e-10 )
omega = (xa+xb)/2;
diff = w2 - abs(polyval( v,i*omega ) );
if( diff > 0 )
xa = (xa+xb)/2;
else
xb = (xa+xb)/2;
end
count++;
end
% printf("3dB-cutoff frequency:%g count:%i erg:%g\n",
% omega, count, abs(polyval( v,i*omega )) );
%
% OK, now we got the n roots of the bessel polynomial. Most of the
% roots are complex numbers, but for even orders we always have one
% root with imaginary part = zero. Now we want to determine the quadratic
% terms: We know: (x-r)(x-~r) = x^2 - 2*x*real(r) + |r|^2
% And we want this to divide
% by |r|^2 : (x-r)(x-~r)/(|r|^2) = x^2/(|r|^2) - 2*x*real(r)/(|r|^2) + 1
% We only take the poles with imgaginary part > 0
% I assume for conjugated roots in r=roots(v) :
% first comes the root with imaginary part > 0, then
% comes the root with imaginary part < 0.
% For other roots we know that the imaginary part is always zero.
% I want to check this, to be sure that we extract only the wanted roots,
% because I don't know if the accuracy of octave or the computer is good
% enough, so that for example for a noncomplex root the calculated
% imaginary part really is exact zero.
cnt=1;
for ind=1:n
if( imag(r(ind)) > 0 )
if( imag(r(ind+1))!=-imag(r(ind)) )
error("Expected exact conjugated pole");
end
% it is fantastic that octave works so accurately,
% that imag(r(ind+1)) == -imag(r(ind)) exactly !!!
a(cnt)=-omega*2.0*real(r(ind))/(abs(r(ind))^2);
b(cnt)=omega^2*1.0/(abs(r(ind))^2);
%printf("a=%.10f b=%.10f\n", a(cnt), b(cnt) );
%printf("%.10f,", a(cnt) );
%printf("%.10f,", b(cnt) );
cnt++;
else
if( imag(r(ind)) == 0 )
% (x-r)/(-r) = -x/r + 1
a(cnt) = -omega*1.0/r(ind);
b(cnt)=0;
%printf("a=%.10f b=%.10f\n", a(cnt), 0 );
%printf("%.10f,", a(cnt) );
%printf("%.10f,", 0 );
cnt++;
end
end
end
puts("\n");
end
--Boundary-00=_M4MrGX3Zvma0O70
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Octave-sources mailing list
[email protected]
https://www.cae.wisc.edu/mailman/listinfo/octave-sources
--Boundary-00=_M4MrGX3Zvma0O70--