File: cepstrum.sci

package info (click to toggle)
scilab 2.4-1
  • links: PTS
  • area: non-free
  • in suites: potato, slink
  • size: 55,196 kB
  • ctags: 38,019
  • sloc: ansic: 231,970; fortran: 148,976; tcl: 7,099; makefile: 4,585; sh: 2,978; csh: 154; cpp: 101; asm: 39; sed: 5
file content (63 lines) | stat: -rw-r--r-- 1,824 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
function fresp = cepstrum(w,mag)
// Uses the complex-cepstrum (Oppenheim & Schafer, Digital
//Signal Processing, p. 501) to generate, at the frequencies 
//w, a complex frequency response fresp whose magnitude is 
//equal to magnitude data mag and whose phase corresponds
//to a stable, minimum phase transfer function. 
//
// Copyright INRIA
[w,ind]=sort(-w);w=-w;mag=mag(ind);
dnum=length(w);

pw=sqrt(w(dnum)*w(1));
if pw<1.d-8 then error('invalid frequency range');end
tcomes=(w.*w)/pw/pw;

dw=acos((1-tcomes)./(1+tcomes));
lowf=dw(1);
highf=dw(length(dw));
if lowf <= 0 | highf >=%pi
  error('w should be positive')
end

nn=ceil((log(2*%pi/min(lowf,%pi-highf)))/log(2));
npts=2*(2^nn);hnpts =2^nn;
if npts<4096 then npts=4096;hnpts=2048;end

lmagin =(1/log(10))*log(mag);lindw =(%pi/hnpts)*(0:hnpts-1);
lmag=zeros(1,hnpts);topval=length(dw);
p=find(lindw<dw(1));lmag(p)=lmagin(1)*ones(1,length(p));
p=find(dw(topval)<=lindw);
lmag(p)=lmagin(topval)*ones(1,length(p));
for i=2:topval
  p=find(lindw>=dw(i-1) & lindw<dw(i));
  wrat=lindw(p) - dw(i-1)*ones(1,length(p));
  wrat=(1/(dw(i)-dw(i-1)))*wrat;
  lmag(p)=(ones(1,length(p))-wrat)*lmagin(i-1)+wrat*lmagin(i);
end
linmag=exp(log(10)*lmag);

dome=[lindw,(2*%pi)-fliplr(lindw)];
mag=[linmag,fliplr(linmag)];

ymag=log(mag.*mag);ycc=fft(ymag,1);nptso2=npts/2;xcc=ycc(1:nptso2);
xcc(1)=xcc(1)/2;xhat=exp(fft(xcc,-1));domeg=dome(1:2:nptso2-1);
xhat = xhat(1:nptso2/2);nptsslo=length(dw);nptsfst = length(domeg);

if domeg(1)<=dw(1) & domeg(nptsfst)>=dw(nptsslo)
  fresp=zeros(1,nptsslo);
  for i=1:nptsslo
    p=min(find(domeg>=dw(i)));
    wrat=(dw(i)-domeg(p-1))/(domeg(p)-domeg(p-1));
    fresp(i)=wrat*xhat(p) + (1-wrat)*xhat(p-1);
  end
else
  error('not sampled high enough')
end
fresp=fresp(:);

function m=fliplr(m)
//utility fct.
[p,q]=size(m);
m=m(:,q:-1:1);