File: yulewalk.sci

package info (click to toggle)
scilab 2.6-4
  • links: PTS
  • area: non-free
  • in suites: woody
  • size: 54,632 kB
  • ctags: 40,267
  • sloc: ansic: 267,851; fortran: 166,549; sh: 10,005; makefile: 4,119; tcl: 1,070; cpp: 233; csh: 143; asm: 135; perl: 130; java: 39
file content (155 lines) | stat: -rw-r--r-- 4,310 bytes parent folder | download | duplicates (2)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
function [Nz,Dz]=yulewalk(Norder, frq, mag)
//YULEWALK  filter design using a least-squares method.
//	Hz = YULEWALK(N,frq,mag) finds the N-th order iir filter
//
//		               n-1         n-2            
//		   B(z)   b(1)z     + b(2)z    + .... + b(n)
//	     H(z)= ---- = ---------------------------------
//		            n-1       n-2
//		   A(z)    z   + a(1)z    + .... + a(n)
//
//which matches the magnitude frequency response given by vectors F and M.
//Vectors frq and mag specify the frequency and magnitude of the desired
//frequency response. The frequencies in frq must be between 0.0 and 1.0,
//with 1.0 corresponding to half the sample rate. They must be in
//increasing order and start with 0.0 and end with 1.0. 
//
// Example: f=[0,0.4,0.4,0.6,0.6,1];H=[0,0,1,1,0,0];Hz=yulewalk(8,f,H);
//fs=1000;fhz = f*fs/2;  
//xbasc(0);xset('window',0);plot2d(fhz',H');
//xtitle('Desired Frequency Response')
//[frq,repf]=repfreq(Hz,0:0.001:0.5);
//xbasc(1);xset('window',1);plot2d(fs*frq',abs(repf'));
//xtitle('Obtained Frequency Response')
//
// Copyright INRIA
[LHS,RHS]=argn(0);
if RHS <>3
   error('Wrong number of input parameters.')
end
   npt=512;
  thelap=fix(npt/25);
   
[mf,nf]=size(frq);
[mm,nn]=size(mag);
if mm ~= mf | nn ~= nf
   error('You must specify the same number of frequencies and amplitudes.')
end
nbrk=max(mf,nf);
if mf < nf
   frq=frq';
   mag=mag';
end

if abs(frq(1)) > %eps | abs(frq(nbrk) - 1) > %eps
   error('The first frequency must be 0 and the last 1.')
end

npt=npt+1;
Ht=zeros(1,npt);

nint=nbrk-1;
df=frq(2:nf)-frq(1:nf-1);
if (or(df < 0))
   error('Frequencies must be non-decreasing.')
end

nb=1;
Ht(1)=mag(1);
for i=1:nint
    if df(i) == 0
       nb=nb - thelap/2;
       ne=nb + thelap;
    else
       ne=int(frq(i+1)*npt);
    end
    if (nb < 0 | ne > npt)
       error('Too abrupt amplitude change near end of frequency interval.')
    end
    j=nb:ne;
    if ne == nb
        inc=0;
    else
        inc=(j-nb)/(ne-nb);
    end
    Ht(nb:ne)=inc*mag(i+1) + (1 - inc)*mag(i);
    nb=ne + 1;
end
Ht=[Ht Ht(npt-1:-1:2)];
n=max(size(Ht));
n2=fix((n+1)/2);
nb=Norder;
nr=4*Norder;
nt=0:1:nr-1;
R=real(fft(Ht.*Ht,1));
R =R(1:nr).*(0.54+0.46*cos(%pi*nt/(nr-1)));
Rwindow=[1/2,ones(1,n2-1),zeros(1,n-n2)]; 

nr=max(size(R));
Rm=toeplitz(R(Norder+1:nr-1),R(Norder+1:-1:2));
Rhs=- R(Norder+2:nr);
denf=[1 Rhs/Rm'];

A=polystab(denf);
nA=size(A,'*');
Dz=poly(A(nA:-1:1),'z','c');
Qh=numf([R(1)/2,R(2:nr)],A,Norder);	// compute additive decomposition
Qhsci=poly(Qh( size(Qh,'*'):-1:1 ),'z','c')
aa=A(:);bb=Qh(:);
nna=max(size(aa));nnb=max(size(bb));
Ss=2*real((fft([Qh,zeros(1,n-nnb)],-1) ./ fft([A,zeros(1,n-nna)],-1)));
hh=fft(exp(fft( Rwindow.*fft(log(Ss),1),-1)),1);
impr=filter(1,A,[1 zeros(1,nr-1)]);
B=real(hh(1:nr)/toeplitz(impr,[1 zeros(1,nb)])');
nB=size(B,'*');
Nz=poly(B(nB:-1:1),'z','c');
B =real(numf(hh(1:nr),A,nb));
if LHS==1 then
  Nz=syslin('d',Nz/Dz);
end



function b=polystab(a);
//Utility function for use with yulewalk: polynomial stabilization.
//	polystab(A), where A is a vector of polynomial coefficients,
//	stabilizes the polynomial with respect to the unit circle;
//	roots whose magnitudes are greater than one are reflected
//	inside the unit circle.
if length(a) == 1, b=a; return, end
ll=size(a,'*');
ap=poly(a(ll:-1:1),'s','coeff');
v=roots(ap); i=find(v~=0);
vs=0.5*(sign(abs(v(i))-1)+1);
v(i)=(1-vs).*v(i) + vs./conj(v(i));
b=a(1)*coeff(poly(v,'s'));
b =b(ll:-1:1);
if ~or(imag(a))
	b=real(b);
end
  
function y=filter(b,a,x)
//Clone of Matlab filter function
//
// filter Digital filter.
//Y=filter(B, A, X) filters the data in vector X with the
//filter described by vectors A and B to create the filtered
//data Y.  
//Implementation of the standard difference equation:
//
//    y(n)=b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb)
//        - a(2)*y(n-1) - ... - a(na+1)*y(n-na)
na=size(a,'*');nb=size(b,'*');
if na<nb then a=[a,zeros(1,nb-na)];na=nb;end;
y=rtitr(poly(b(nb:-1:1),'z','c'),poly(a(na:-1:1),'z','c'),x)
if na>nb then y=y(na-nb+1:length(y));end

function b=numf(h,a,nb)
//NUMF	Find numerator B given impulse-response h of B/A and denominator A
//NB is the numerator order.  This function is used by yulewalk.
  
nh=max(size(h));
impr=filter(1,a,[1 zeros(1,nh-1)]);
b=h/toeplitz(impr,[1 zeros(1,nb)])';