mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-21 19:55:20 -05:00
159 lines
4.1 KiB
Fortran
159 lines
4.1 KiB
Fortran
subroutine refspectrum(id2,bclear,brefspec,buseref,fname)
|
|
|
|
! Input:
|
|
! id2 i*2 Raw 16-bit integer data, 12000 Hz sample rate
|
|
! brefspec logical True when accumulating a reference spectrum
|
|
|
|
parameter (NFFT=6912,NH=NFFT/2,NPOLYLOW=400,NPOLYHIGH=2600)
|
|
integer*2 id2(NFFT)
|
|
logical*1 bclear,brefspec,buseref,blastuse
|
|
|
|
real xs(0:NH-1) !Saved upper half of input chunk convolved with h(t)
|
|
real x(0:NFFT-1) !Work array
|
|
real*4 w(0:NFFT-1) !Window function
|
|
real*4 s(0:NH) !Average spectrum
|
|
real*4 fil(0:NH)
|
|
real*8 xfit(1500),yfit(1500),sigmay(1500),a(5),chisqr !Polyfit arrays
|
|
logical first
|
|
complex cx(0:NH) !Complex frequency-domain work array
|
|
complex cfil(0:NH)
|
|
character*(*) fname
|
|
common/spectra/syellow(6827),ref(0:NH),filter(0:NH)
|
|
equivalence(x,cx)
|
|
data first/.true./,blastuse/.false./
|
|
save
|
|
|
|
if(first) then
|
|
pi=4.0*atan(1.0)
|
|
do i=0,NFFT-1
|
|
ww=sin(i*pi/NFFT)
|
|
w(i)=ww*ww/NFFT
|
|
enddo
|
|
nsave=0
|
|
s=0.0
|
|
filter=1.0
|
|
xs=0.
|
|
first=.false.
|
|
endif
|
|
if(bclear) s=0.
|
|
|
|
if(brefspec) then
|
|
x(0:NH-1)=0.001*id2(1:NH)
|
|
x(NH:NFFT-1)=0.0
|
|
call four2a(cx,NFFT,1,-1,0) !r2c FFT
|
|
|
|
do i=1,NH
|
|
s(i)=s(i) + real(cx(i))**2 + aimag(cx(i))**2
|
|
enddo
|
|
nsave=nsave+1
|
|
|
|
fac0=0.9
|
|
if(mod(nsave,4).eq.0) then
|
|
df=12000.0/NFFT
|
|
ia=nint(1000.0/df)
|
|
ib=nint(2000.0/df)
|
|
avemid=sum(s(ia:ib))/(ib-ia+1)
|
|
do i=0,NH
|
|
fil(i)=0.
|
|
if(s(i).gt.0.0) then
|
|
fil(i)=sqrt(avemid/s(i))
|
|
endif
|
|
enddo
|
|
|
|
! Default range is 240 - 4000 Hz. For narrower filters, use frequencies
|
|
! at which gain is -20 dB relative to 1500 Hz.
|
|
ia=nint(240.0/df)
|
|
ib=nint(4000.0/df)
|
|
i0=nint(1500.0/df)
|
|
do i=i0,ia,-1
|
|
if(s(i)/s(i0).lt.0.01) exit
|
|
enddo
|
|
ia=i
|
|
do i=i0,ib,1
|
|
if(s(i)/s(i0).lt.0.01) exit
|
|
enddo
|
|
ib=i
|
|
|
|
fac=fac0
|
|
do i=ia,1,-1
|
|
fac=fac*fac0
|
|
fil(i)=fac*fil(i)
|
|
enddo
|
|
|
|
fac=fac0
|
|
do i=ib,NH
|
|
fac=fac*fac0
|
|
fil(i)=fac*fil(i)
|
|
enddo
|
|
|
|
do iter=1,100 !### ??? ###
|
|
call smo121(fil,NH)
|
|
enddo
|
|
|
|
do i=0,NH
|
|
filter(i)=-60.0
|
|
if(s(i).gt.0.0) filter(i)=20.0*log10(fil(i))
|
|
enddo
|
|
|
|
il=nint(NPOLYLOW/df)
|
|
ih=nint(NPOLYHIGH/df)
|
|
nfit=ih-il+1
|
|
mode=0
|
|
nterms=5
|
|
do i=1,nfit
|
|
xfit(i)=((i+il-1)*df-1500.0)/1000.0
|
|
yfit(i)=fil(i+il-1)
|
|
sigmay(i)=1.0
|
|
enddo
|
|
call polyfit(xfit,yfit,sigmay,nfit,nterms,mode,a,chisqr)
|
|
|
|
open(16,file=fname,status='unknown')
|
|
write(16,1003) NPOLYLOW,NPOLYHIGH,nterms,a
|
|
1003 format(3i5,5e25.16)
|
|
do i=1,NH
|
|
freq=i*df
|
|
ref(i)=db(s(i)/avemid)
|
|
write(16,1005) freq,s(i),ref(i),fil(i),filter(i)
|
|
1005 format(f10.3,e12.3,f12.6,e12.3,f12.6)
|
|
enddo
|
|
close(16)
|
|
endif
|
|
return
|
|
endif
|
|
|
|
if(buseref) then
|
|
if(blastuse.neqv.buseref) then !just enabled so read filter
|
|
fil=1.0
|
|
open(16,file=fname,status='old',err=999)
|
|
read(16,1003,err=20,end=999) ndummy,ndummy,nterms,a
|
|
goto 30
|
|
20 rewind(16) !allow for old style refspec.dat with no header
|
|
30 do i=1,NH
|
|
read(16,1005,err=999,end=999) freq,s(i),ref(i),fil(i),filter(i)
|
|
enddo
|
|
! Make the filter causal for overlap and add.
|
|
cx(0)=0.0
|
|
cx(1:NH)=fil(1:NH)/NFFT
|
|
call four2a(cx,NFFT,1,1,-1)
|
|
x=cshift(x,-400)
|
|
x(800:NH)=0.0
|
|
call four2a(cx,NFFT,1,-1,0)
|
|
cfil=cx
|
|
close(16)
|
|
endif
|
|
! Use overlap and add method to apply causal reference filter.
|
|
x(0:NH-1)=id2(1:NH)
|
|
x(NH:NFFT-1)=0.0
|
|
x=x/NFFT
|
|
call four2a(cx,NFFT,1,-1,0)
|
|
cx=cfil*cx
|
|
call four2a(cx,NFFT,1,1,-1)
|
|
x(0:NH-1)=x(0:NH-1)+xs
|
|
xs=x(NH:NFFT-1)
|
|
id2(1:NH)=nint(x(0:NH-1))
|
|
endif
|
|
blastuse=buseref
|
|
|
|
999 return
|
|
end subroutine refspectrum
|