mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	Use 3rd order polynomial fit to estimate the noise baseline. The
polynomial fit is done over 400 Hz bandwidth for T/R periods longer than 15s, and over approx. 600 Hz (10 times the signal bandwidth) for T/R period of 15s.
This commit is contained in:
		
							parent
							
								
									d82b9f5b0e
								
							
						
					
					
						commit
						5ca81a6507
					
				@ -618,6 +618,7 @@ set (wsjt_FSRCS
 | 
				
			|||||||
  lib/fst4/osd240_101.f90
 | 
					  lib/fst4/osd240_101.f90
 | 
				
			||||||
  lib/fst4/osd240_74.f90
 | 
					  lib/fst4/osd240_74.f90
 | 
				
			||||||
  lib/fst4/get_crc24.f90
 | 
					  lib/fst4/get_crc24.f90
 | 
				
			||||||
 | 
					  lib/fst4/fst4_baseline.f90
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# temporary workaround for a gfortran v7.3 ICE on Fedora 27 64-bit
 | 
					# temporary workaround for a gfortran v7.3 ICE on Fedora 27 64-bit
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								lib/fst4/fst4_baseline.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								lib/fst4/fst4_baseline.f90
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					subroutine fst4_baseline(s,np,ia,ib,npct,sbase)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					! Fit baseline to spectrum (for FST4)
 | 
				
			||||||
 | 
					! Input:  s(npts)         Linear scale in power
 | 
				
			||||||
 | 
					! Output: sbase(npts)    Baseline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  implicit real*8 (a-h,o-z)
 | 
				
			||||||
 | 
					  real*4 s(np),sw(np)
 | 
				
			||||||
 | 
					  real*4 sbase(np)
 | 
				
			||||||
 | 
					  real*4 base
 | 
				
			||||||
 | 
					  real*8 x(1000),y(1000),a(5)
 | 
				
			||||||
 | 
					  data nseg/8/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  do i=ia,ib
 | 
				
			||||||
 | 
					     sw(i)=10.0*log10(s(i))            !Convert to dB scale
 | 
				
			||||||
 | 
					  enddo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  nterms=3
 | 
				
			||||||
 | 
					  nlen=(ib-ia+1)/nseg                 !Length of test segment
 | 
				
			||||||
 | 
					  i0=(ib-ia+1)/2                      !Midpoint
 | 
				
			||||||
 | 
					  k=0
 | 
				
			||||||
 | 
					  do n=1,nseg                         !Loop over all segments
 | 
				
			||||||
 | 
					     ja=ia + (n-1)*nlen
 | 
				
			||||||
 | 
					     jb=ja+nlen-1
 | 
				
			||||||
 | 
					     call pctile(sw(ja),nlen,npct,base) !Find lowest npct of points
 | 
				
			||||||
 | 
					     do i=ja,jb
 | 
				
			||||||
 | 
					        if(sw(i).le.base) then
 | 
				
			||||||
 | 
					           if (k.lt.1000) k=k+1       !Save all "lower envelope" points
 | 
				
			||||||
 | 
					           x(k)=i-i0
 | 
				
			||||||
 | 
					           y(k)=sw(i)
 | 
				
			||||||
 | 
					        endif
 | 
				
			||||||
 | 
					     enddo
 | 
				
			||||||
 | 
					  enddo
 | 
				
			||||||
 | 
					  kz=k
 | 
				
			||||||
 | 
					  a=0.
 | 
				
			||||||
 | 
					  call polyfit(x,y,y,kz,nterms,0,a,chisqr)  !Fit a low-order polynomial
 | 
				
			||||||
 | 
					  sbase=0.0
 | 
				
			||||||
 | 
					  do i=ia,ib
 | 
				
			||||||
 | 
					     t=i-i0
 | 
				
			||||||
 | 
					     sbase(i)=a(1)+t*(a(2)+t*(a(3))) + 0.2
 | 
				
			||||||
 | 
					!     write(51,3051) i,sw(i),sbase(i)
 | 
				
			||||||
 | 
					!3051 format(i8,2f12.3)
 | 
				
			||||||
 | 
					  enddo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sbase=10**(sbase/10.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return
 | 
				
			||||||
 | 
					end subroutine fst4_baseline
 | 
				
			||||||
@ -49,7 +49,7 @@ contains
 | 
				
			|||||||
      complex, allocatable :: cframe(:)
 | 
					      complex, allocatable :: cframe(:)
 | 
				
			||||||
      complex, allocatable :: c_bigfft(:)          !Complex waveform
 | 
					      complex, allocatable :: c_bigfft(:)          !Complex waveform
 | 
				
			||||||
      real llr(240),llrs(240,4)
 | 
					      real llr(240),llrs(240,4)
 | 
				
			||||||
      real candidates(200,4)
 | 
					      real candidates(200,5)
 | 
				
			||||||
      real bitmetrics(320,4)
 | 
					      real bitmetrics(320,4)
 | 
				
			||||||
      real s4(0:3,NN)
 | 
					      real s4(0:3,NN)
 | 
				
			||||||
      real minsync
 | 
					      real minsync
 | 
				
			||||||
@ -254,14 +254,19 @@ contains
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      nhicoh=1
 | 
					      nhicoh=1
 | 
				
			||||||
      nsyncoh=8
 | 
					      nsyncoh=8
 | 
				
			||||||
      fa=max(100,nint(nfqso+1.5*hmod*baud-ntol))
 | 
					      if(iwspr.eq.1) then
 | 
				
			||||||
      fb=min(4800,nint(nfqso+1.5*hmod*baud+ntol))
 | 
					         fa=1400.0
 | 
				
			||||||
      minsync=1.2
 | 
					         fb=1600.0
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					         fa=max(100,nint(nfqso+1.5*hmod*baud-ntol))
 | 
				
			||||||
 | 
					         fb=min(4800,nint(nfqso+1.5*hmod*baud+ntol))
 | 
				
			||||||
 | 
					      endif
 | 
				
			||||||
 | 
					      minsync=1.20
 | 
				
			||||||
      if(ntrperiod.eq.15) minsync=1.15
 | 
					      if(ntrperiod.eq.15) minsync=1.15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
! Get first approximation of candidate frequencies
 | 
					! Get first approximation of candidate frequencies
 | 
				
			||||||
      call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,     &
 | 
					      call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,     &
 | 
				
			||||||
         minsync,ncand,candidates,base)
 | 
					         minsync,ncand,candidates)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      ndecodes=0
 | 
					      ndecodes=0
 | 
				
			||||||
      decodes=' '
 | 
					      decodes=' '
 | 
				
			||||||
@ -317,7 +322,7 @@ contains
 | 
				
			|||||||
      enddo
 | 
					      enddo
 | 
				
			||||||
      ncand=ic
 | 
					      ncand=ic
 | 
				
			||||||
      xsnr=0.
 | 
					      xsnr=0.
 | 
				
			||||||
 | 
					!write(*,*) 'ncand ',ncand
 | 
				
			||||||
      do icand=1,ncand
 | 
					      do icand=1,ncand
 | 
				
			||||||
         sync=candidates(icand,2)
 | 
					         sync=candidates(icand,2)
 | 
				
			||||||
         fc_synced=candidates(icand,3)
 | 
					         fc_synced=candidates(icand,3)
 | 
				
			||||||
@ -465,6 +470,7 @@ contains
 | 
				
			|||||||
                     do i=1,NN
 | 
					                     do i=1,NN
 | 
				
			||||||
                        xsig=xsig+s4(itone(i),i)
 | 
					                        xsig=xsig+s4(itone(i),i)
 | 
				
			||||||
                     enddo
 | 
					                     enddo
 | 
				
			||||||
 | 
					                     base=candidates(icand,5)
 | 
				
			||||||
                     arg=600.0*(xsig/base)-1.0
 | 
					                     arg=600.0*(xsig/base)-1.0
 | 
				
			||||||
                     if(arg.gt.0.0) then
 | 
					                     if(arg.gt.0.0) then
 | 
				
			||||||
                        xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0)
 | 
					                        xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0)
 | 
				
			||||||
@ -645,14 +651,15 @@ contains
 | 
				
			|||||||
   end subroutine fst4_downsample
 | 
					   end subroutine fst4_downsample
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   subroutine get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,   &
 | 
					   subroutine get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,   &
 | 
				
			||||||
      minsync,ncand,candidates,base)
 | 
					      minsync,ncand,candidates)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      complex c_bigfft(0:nfft1/2)              !Full length FFT of raw data
 | 
					      complex c_bigfft(0:nfft1/2)              !Full length FFT of raw data
 | 
				
			||||||
      integer hmod                             !Modulation index (submode)
 | 
					      integer hmod                             !Modulation index (submode)
 | 
				
			||||||
      integer im(1)                            !For maxloc
 | 
					      integer im(1)                            !For maxloc
 | 
				
			||||||
      real candidates(200,4)                   !Candidate list
 | 
					      real candidates(200,5)                   !Candidate list
 | 
				
			||||||
      real, allocatable :: s(:)                !Low resolution power spectrum
 | 
					      real, allocatable :: s(:)                !Low resolution power spectrum
 | 
				
			||||||
      real, allocatable :: s2(:)               !CCF of s() with 4 tones
 | 
					      real, allocatable :: s2(:)               !CCF of s() with 4 tones
 | 
				
			||||||
 | 
					      real, allocatable :: sbase(:)            !noise baseline estimate
 | 
				
			||||||
      real xdb(-3:3)                           !Model 4-tone CCF peaks
 | 
					      real xdb(-3:3)                           !Model 4-tone CCF peaks
 | 
				
			||||||
      real minsync
 | 
					      real minsync
 | 
				
			||||||
      data xdb/0.25,0.50,0.75,1.0,0.75,0.50,0.25/
 | 
					      data xdb/0.25,0.50,0.75,1.0,0.75,0.50,0.25/
 | 
				
			||||||
@ -668,17 +675,17 @@ contains
 | 
				
			|||||||
      signal_bw=4*(12000.0/nsps)*hmod
 | 
					      signal_bw=4*(12000.0/nsps)*hmod
 | 
				
			||||||
      analysis_bw=min(4800.0,fb)-max(100.0,fa)
 | 
					      analysis_bw=min(4800.0,fb)-max(100.0,fa)
 | 
				
			||||||
      xnoise_bw=10.0*signal_bw                  !Is this a good compromise?
 | 
					      xnoise_bw=10.0*signal_bw                  !Is this a good compromise?
 | 
				
			||||||
      if(analysis_bw.gt.xnoise_bw) then
 | 
					      if(xnoise_bw .lt. 400.0) xnoise_bw=400.0  
 | 
				
			||||||
         ina=ia
 | 
					      if(analysis_bw.gt.xnoise_bw) then         !Estimate noise baseline over analysis bw
 | 
				
			||||||
         inb=ib
 | 
					         ina=0.9*ia
 | 
				
			||||||
      else
 | 
					         inb=min(int(1.1*ib),nfft1/2)
 | 
				
			||||||
         fcenter=(fa+fb)/2.0                      !If noise_bw > analysis_bw,
 | 
					      else                                      !Estimate noise baseline over noise bw
 | 
				
			||||||
         fl = max(100.0,fcenter-xnoise_bw/2.)/df2  !we'll search over noise_bw
 | 
					         fcenter=(fa+fb)/2.0                    
 | 
				
			||||||
 | 
					         fl = max(100.0,fcenter-xnoise_bw/2.)/df2  
 | 
				
			||||||
         fh = min(4800.0,fcenter+xnoise_bw/2.)/df2
 | 
					         fh = min(4800.0,fcenter+xnoise_bw/2.)/df2
 | 
				
			||||||
         ina=nint(fl)
 | 
					         ina=nint(fl)
 | 
				
			||||||
         inb=nint(fh)
 | 
					         inb=nint(fh)
 | 
				
			||||||
      endif
 | 
					      endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
      nnw=nint(48000.*nsps*2./fs)
 | 
					      nnw=nint(48000.*nsps*2./fs)
 | 
				
			||||||
      allocate (s(nnw))
 | 
					      allocate (s(nnw))
 | 
				
			||||||
      s=0.                                  !Compute low-resolution power spectrum
 | 
					      s=0.                                  !Compute low-resolution power spectrum
 | 
				
			||||||
@ -692,12 +699,16 @@ contains
 | 
				
			|||||||
      ina=max(ina,1+3*hmod)                       !Don't run off the ends
 | 
					      ina=max(ina,1+3*hmod)                       !Don't run off the ends
 | 
				
			||||||
      inb=min(inb,nnw-3*hmod)
 | 
					      inb=min(inb,nnw-3*hmod)
 | 
				
			||||||
      allocate (s2(nnw))
 | 
					      allocate (s2(nnw))
 | 
				
			||||||
 | 
					      allocate (sbase(nnw))
 | 
				
			||||||
      s2=0.
 | 
					      s2=0.
 | 
				
			||||||
      do i=ina,inb                                !Compute CCF of s() and 4 tones
 | 
					      do i=ina,inb                                !Compute CCF of s() and 4 tones
 | 
				
			||||||
         s2(i)=s(i-hmod*3) + s(i-hmod) +s(i+hmod) +s(i+hmod*3)
 | 
					         s2(i)=s(i-hmod*3) + s(i-hmod) +s(i+hmod) +s(i+hmod*3)
 | 
				
			||||||
      enddo
 | 
					      enddo
 | 
				
			||||||
      call pctile(s2(ina+hmod*3:inb-hmod*3),inb-ina+1-hmod*6,30,base)
 | 
					      npct=30
 | 
				
			||||||
      s2=s2/base                                  !Normalize wrt noise level
 | 
					      call fst4_baseline(s2,nnw,ina+hmod*3,inb-hmod*3,npct,sbase)
 | 
				
			||||||
 | 
					      if(any(sbase(ina:inb).le.0.0)) return
 | 
				
			||||||
 | 
					      s2(ina:inb)=s2(ina:inb)/sbase(ina:inb)             !Normalize wrt noise level
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      ncand=0
 | 
					      ncand=0
 | 
				
			||||||
      candidates=0
 | 
					      candidates=0
 | 
				
			||||||
      if(ia.lt.3) ia=3
 | 
					      if(ia.lt.3) ia=3
 | 
				
			||||||
@ -717,12 +728,11 @@ contains
 | 
				
			|||||||
               s2(k)=max(0.,s2(k)-0.9*pval*xdb(i))
 | 
					               s2(k)=max(0.,s2(k)-0.9*pval*xdb(i))
 | 
				
			||||||
            endif
 | 
					            endif
 | 
				
			||||||
         enddo
 | 
					         enddo
 | 
				
			||||||
!         s2(max(1,iploc-2*hmod*3):min(nnw,iploc+2*hmod*3))=0.0
 | 
					 | 
				
			||||||
         ncand=ncand+1
 | 
					         ncand=ncand+1
 | 
				
			||||||
         candidates(ncand,1)=df2*iploc         !Candidate frequency
 | 
					         candidates(ncand,1)=df2*iploc         !Candidate frequency
 | 
				
			||||||
         candidates(ncand,2)=pval              !Rough estimate of SNR
 | 
					         candidates(ncand,2)=pval              !Rough estimate of SNR
 | 
				
			||||||
 | 
					         candidates(ncand,5)=sbase(iploc)
 | 
				
			||||||
      enddo
 | 
					      enddo
 | 
				
			||||||
 | 
					 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
   end subroutine get_candidates_fst4
 | 
					   end subroutine get_candidates_fst4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user