summaryrefslogtreecommitdiff
path: root/macros/pei_tseng_notch.sci
blob: fcb6b9c87159a0897a0e5e9a9368ee7f14940cc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
function [ b, a ] = pei_tseng_notch ( frequencies, bandwidths )
//Return coefficients for an IIR notch-filter.
//Calling Sequence:
//[b, a] = pei_tseng_notch(frequencies, bandwidths)
//Parameters:
//frequencies: Real scalar/vector representing filter frequencies.
//bandwidths: Real scalar scalar/vector representing bandwidths to be used with filter.
//Description:
//THis function returns coefficients for an IIR notch-filter with one or more filter frequencies and according bandwidths.
//The filter is based on a all pass filter that performs phasereversal at filter frequencies. This leads to removal of those frequencies of the original and phase-distorted signal.
//Examples:
//sf = 800; sf2 = sf/2;
//data = [[1;zeros(sf-1,1)],sinetone(49,sf,1,1),sinetone(50,sf,1,1),sinetone(51,sf,1,1)];
//[b,a] = pei_tseng_notch ( 50 / sf2, 2/sf2 )
//b = 0.99213  -1.83322   0.99213
//a = 1.00000  -1.83322   0.98426

  if (nargin() ~= 2)
    error("Wrong number of input arguments.");
  elseif ( ~isvector(frequencies) | ~isvector(bandwidths) )
      if ( ~isscalar(frequencies) | ~isscalar(bandwidths) )
        error("All arguments must be vectors or scalars.");
      end
  elseif ( length(frequencies) ~= length (bandwidths) )
    error("All arguments must be of equal length.");
  elseif (~and( frequencies > 0 & frequencies < 1 ))
    error("All frequencies must be in (0, 1).");
  elseif (~and( bandwidths > 0 & bandwidths < 1 ))
    error("All bandwidths must be in (0, 1).");
  end

  frequencies = frequencies (:)';
  bandwidths  = bandwidths (:)';

  frequencies = frequencies*%pi;
  bandwidths  = bandwidths*%pi;
  M2 = 2 * length(frequencies);

  a = [ frequencies - bandwidths / 2; frequencies ];
  omega = a(:);
  factors = ( 1 : 2 : M2 );
  b = [ -%pi * factors + %pi / 2; -%pi * factors ];
  phi = b(:);
  t_beta = tan ( ( phi + M2 * omega ) / 2 );

  Q = zeros (M2, M2);

  for k = 1 : M2
    Q ( :, k ) = sin ( k .* omega ) - t_beta .* cos ( k .* omega );
  end

  h_a   = ( Q \ t_beta )';
  denom = [ 1, h_a ];
  num   = [ flipdim(h_a, 2), 1 ];

  a = denom;
  b = ( num + denom ) / 2;

endfunction

//input validation:
//assert_checkerror("pei_tseng_notch()", "Wrong number of input arguments.");
//assert_checkerror("pei_tseng_notch([1, 2, 3])", "Wrong number of input arguments.");
//assert_checkerror("pei_tseng_notch([1, 2; 3, 4], [4; 5; 6])", "All arguments must be vectors or scalars.");
//assert_checkerror("pei_tseng_notch([1, 2, 3, 4], [5, 6])", "All arguments must be of equal length.");
//assert_checkerror("pei_tseng_notch([1, 2, 3], [4, 5, 6])", "All frequencies must be in (0, 1).");
//assert_checkerror("pei_tseng_notch([0.1, 0.2, 0.3], [4, 5, 6])", "All bandwidths must be in (0, 1).");

//tests:
//assert_checkequal(pei_tseng_notch(0.2, 0.4), [0 0 0]);
//assert_checkalmostequal(pei_tseng_notch([0.2, 0.5, 0.9], [0.1, 0.3, 0.5]), [0.41549, 0.11803, -0.03227, 0.23606, -0.03227, 0.11803, 0.41549], 5*10^-4);
//assert_checkequal(pei_tseng_notch([0.2; 0.5; 0.9], [0.1, 0.3, 0.5]), pei_tseng_notch([0.2, 0.5, 0.9], [0.1; 0.3; 0.5]));
//assert_checkalmostequal(pei_tseng_notch([0.2, 0.7], [0.1, 0.3]), [0.60331, -0.26694, 0.05905, -0.26694, 0.60331], 5*10^-4);