From be8c837d851c8cdb26fffbaf5ffc56079abc4c9e Mon Sep 17 00:00:00 2001 From: Joe Taylor Date: Wed, 25 Apr 2018 17:24:58 +0000 Subject: [PATCH] New simulator jt49sim, replaces both jt4sim and jt9sim. Fix the S/N estimates made for slow/wide JT9 submodes. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@8639 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- CMakeLists.txt | 4 +- lib/decode9w.f90 | 34 +++++++-- lib/jt49sim.f90 | 190 ++++++++++++++++++++++++++++++++++++++++++++++ lib/softsym9w.f90 | 15 ++-- 4 files changed, 225 insertions(+), 18 deletions(-) create mode 100644 lib/jt49sim.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index e35fa2fce..03b5dca3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1174,8 +1174,8 @@ target_link_libraries (jt65sim wsjt_fort wsjt_cxx) add_executable (qra64sim lib/qra/qra64/qra64sim.f90 wsjtx.rc) target_link_libraries (qra64sim wsjt_fort wsjt_cxx) -add_executable (jt9sim lib/jt9sim.f90 wsjtx.rc) -target_link_libraries (jt9sim wsjt_fort wsjt_cxx) +add_executable (jt49sim lib/jt49sim.f90 wsjtx.rc) +target_link_libraries (jt49sim wsjt_fort wsjt_cxx) add_executable (allsim lib/allsim.f90 wsjtx.rc) target_link_libraries (allsim wsjt_fort wsjt_cxx) diff --git a/lib/decode9w.f90 b/lib/decode9w.f90 index 54c227222..2c043c726 100644 --- a/lib/decode9w.f90 +++ b/lib/decode9w.f90 @@ -29,21 +29,39 @@ subroutine decode9w(nfqso,ntol,nsubmode,ss,id2,sync,nsnr,xdt1,f0,decoded) nadd=3 if(iter.eq.2) nadd=2*nint(0.375*a(4)) + 1 call sync9w(ss,nhsym,lag1,lag2,ia,ib,ccfred,ccfblue,ipk,lagpk,nadd) - sum1=sum(ccfblue) - ccfblue(lagpk-1)-ccfblue(lagpk) -ccfblue(lagpk+1) - sq=dot_product(ccfblue,ccfblue) - ccfblue(lagpk-1)**2 - & - ccfblue(lagpk)**2 - ccfblue(lagpk+1)**2 - base=sum1/25.0 - rms=sqrt(sq/24.0) + s=0. + sq=0. + ns=0 + do i=-9,18 + if(abs(i-lagpk).gt.3) then + s=s+ccfblue(i) + sq=sq+ccfblue(i)**2 + ns=ns+1 + endif + enddo + base=s/ns + rms=sqrt(sq/ns - base**2) sync=(ccfblue(lagpk)-base)/rms - nsnr=nint(db(sync)-29.7) xdt0=lagpk*tstep call lorentzian(ccfred(ia),ib-ia+1,a) f0=(ia+a(3))*df - ccfblue=(ccfblue-base)/rms enddo + ccfblue=(ccfblue-base)/rms - call softsym9w(id2,npts,xdt0,f0,a(4)*df,nsubmode,xdt1-1.05,i1softsymbols) + call softsym9w(id2,npts,xdt0,f0,a(4)*df,nsubmode,xdt1-1.05,snrdb,i1softsymbols) + nsnr=nint(snrdb) call jt9fano(i1softsymbols,limit,nlim,decoded) +!### +! do i=-9,18 +! write(81,3081) i,ccfblue(i) +!3081 format(i3,f10.3) +! enddo +! do i=1,NSMAX +! write(82,3082) i*df,ccfred(i) +!3082 format(f10.1,e12.3) +! enddo +!### + return end subroutine decode9w diff --git a/lib/jt49sim.f90 b/lib/jt49sim.f90 new file mode 100644 index 000000000..7ee0a168f --- /dev/null +++ b/lib/jt49sim.f90 @@ -0,0 +1,190 @@ +program jt49sim + +! Generate simulated data for testing JT4 and JT9 + + use wavhdr + use packjt + use jt4 + parameter (NMAX=60*12000) ! = 648,000 + parameter (NFFT=10*65536,NH=NFFT/2) + type(hdr) h !Header for .wav file + integer*2 iwave(NMAX) !Generated waveform + integer*4 itone(206) !Channel symbols (values 0-8) + real*4 xnoise(NMAX) !Generated random noise + real*4 dat(NMAX) !Generated real data + complex cdat(NMAX) !Generated complex waveform + complex cspread(0:NFFT-1) !Complex amplitude for Rayleigh fading + complex z + real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq,dnsps + character message*22,fname*11,csubmode*2,arg*12 + character msgsent*22 + + nargs=iargc() + if(nargs.ne. 7) then + print *, 'Usage: jt49sim "msg" nA-nE Nsigs fDop DT Nfiles SNR' + print *, 'Example jt49sim "K1ABC W9XYZ EN37" 4G 10 0.2 0.0 1 0' + print *, 'Example jt49sim "K1ABC W9XYZ EN37" 9A 1 0.0 0.0 1 -20' + go to 999 + endif + call getarg(1,message) + call fmtmsg(message, iz) + call getarg(2,csubmode) + imode=ichar(csubmode(1:1)) - ichar('0') + nsubmode=ichar(csubmode(2:2)) - ichar('A') + if(imode.ne.4 .and. imode.ne.9) go to 999 + if(nsubmode.lt.0 .or. nsubmode.gt.7) go to 999 + call getarg(3,arg) + read(arg,*) nsigs + call getarg(4,arg) + read(arg,*) fspread + call getarg(5,arg) + read(arg,*) xdt + call getarg(6,arg) + read(arg,*) nfiles + call getarg(7,arg) + read(arg,*) snrdb + + rms=100. + fsample=12000.d0 !Sample rate (Hz) + dt=1.d0/fsample !Sample interval (s) + twopi=8.d0*atan(1.d0) + npts=60*12000 !Total samples in .wav file + h=default_header(12000,npts) + dfsig=2000.0/nsigs !Freq spacing between sigs in file (Hz) + ichk=0 + + imode=9 + if(imode.eq.4) then + nsym=206 !Number of channel symbols (JT4) + dnsps=12000.d0/4.375d0 + baud=12000.d0/dnsps !Keying rate = 1.7361111111 + else if(imode.eq.9) then + nsym=85 !Number of channel symbols (JT9) + dnsps=6912.d0 !Samples per symbol + baud=12000.d0/dnsps !Keying rate = 1.736... + endif + + write(*,1000) +1000 format('File Sig Freq Mode S/N DT Dop Message'/60('-')) + + do ifile=1,nfiles !Loop over requested number of files + write(fname,1002) ifile !Output filename +1002 format('000000_',i4.4) + open(10,file=fname//'.wav',access='stream',status='unknown') + xnoise=0. + cdat=0. + if(snrdb.lt.90) then + do i=1,npts + xnoise(i)=gran() !Generate gaussian noise + enddo + endif + + do isig=1,nsigs !Generate requested number of sigs + if(mod(nsigs,2).eq.0) f0=1500.0 + dfsig*(isig-0.5-nsigs/2) + if(mod(nsigs,2).eq.1) f0=1500.0 + dfsig*(isig-(nsigs+1)/2) + if(nsigs.eq.1) f0=1000.0 + xsnr=snrdb + if(snrdb.eq.0.0) xsnr=-20 - isig + + if(imode.eq.4) call gen4(message,ichk,msgsent,itone,itype) + if(imode.eq.9) call gen9(message,ichk,msgsent,itone,itype) + + bandwidth_ratio=2500.0/6000.0 + sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr) + if(xsnr.gt.90.0) sig=1.0 + write(*,1020) ifile,isig,f0,csubmode,xsnr,xdt,fspread,message +1020 format(i4,i4,f10.3,2x,a2,2x,f5.1,f6.2,f6.1,1x,a22) + + phi=0.d0 + dphi=0.d0 + k=(xdt+1.0)*12000 !Start audio at t = xdt + 1.0 s + isym0=-99 + + do i=1,npts !Add this signal into cdat() + isym=i/dnsps + 1 + if(isym.gt.nsym) exit + if(isym.ne.isym0) then + if(message(1:1).eq.'@') then + read(message(2:),*) freq + else + if(imode.eq.4) freq=f0 + itone(isym)*baud*nch(1+nsubmode) !JT4 + if(imode.eq.9) freq=f0 + itone(isym)*baud*(2**nsubmode) !JT9 + endif + dphi=twopi*freq*dt + isym0=isym + endif + phi=phi + dphi + if(phi.gt.twopi) phi=phi-twopi + xphi=phi + z=cmplx(cos(xphi),sin(xphi)) + k=k+1 + if(k.ge.1) cdat(k)=cdat(k) + sig*z + enddo + enddo + + if(fspread.ne.0) then !Apply specified Doppler spread + df=12000.0/nfft + twopi=8*atan(1.0) + cspread(0)=1.0 + cspread(NH)=0. + b=6.0 !Lorenzian 3/28 onward + do i=1,NH + f=i*df + x=b*f/fspread + z=0. + a=0. + if(x.lt.3.0) then !Cutoff beyond x=3 + a=sqrt(1.111/(1.0+x*x)-0.1) !Lorentzian + call random_number(r1) + phi1=twopi*r1 + z=a*cmplx(cos(phi1),sin(phi1)) + endif + cspread(i)=z + z=0. + if(x.lt.50.0) then + call random_number(r2) + phi2=twopi*r2 + z=a*cmplx(cos(phi2),sin(phi2)) + endif + cspread(NFFT-i)=z + enddo + + do i=0,NFFT-1 + f=i*df + if(i.gt.NH) f=(i-nfft)*df + s=real(cspread(i))**2 + aimag(cspread(i))**2 +! write(13,3000) i,f,s,cspread(i) +!3000 format(i5,f10.3,3f12.6) + enddo +! s=real(cspread(0))**2 + aimag(cspread(0))**2 +! write(13,3000) 1024,0.0,s,cspread(0) + + call four2a(cspread,NFFT,1,1,1) !Transform to time domain + + sum=0. + do i=0,NFFT-1 + p=real(cspread(i))**2 + aimag(cspread(i))**2 + sum=sum+p + enddo + avep=sum/NFFT + fac=sqrt(1.0/avep) + cspread=fac*cspread !Normalize to constant avg power + cdat(1:NFFT)=cspread*cdat(1:NFFT) !Apply Rayleigh fading + +! do i=0,NFFT-1 +! p=real(cspread(i))**2 + aimag(cspread(i))**2 +! write(14,3010) i,p,cspread(i) +!3010 format(i8,3f12.6) +! enddo + + endif + + dat=aimag(cdat) + xnoise !Add the generated noise + fac=32767.0/nsigs + if(snrdb.ge.90.0) iwave(1:npts)=nint(fac*dat(1:npts)) + if(snrdb.lt.90.0) iwave(1:npts)=nint(rms*dat(1:npts)) + write(10) h,iwave(1:npts) !Save the .wav file + close(10) + enddo + +999 end program jt49sim diff --git a/lib/softsym9w.f90 b/lib/softsym9w.f90 index 4465e0ead..c9b1d0a84 100644 --- a/lib/softsym9w.f90 +++ b/lib/softsym9w.f90 @@ -1,4 +1,4 @@ -subroutine softsym9w(id2,npts,xdt0,f0,width,nsubmode,xdt1,i1softsymbols) +subroutine softsym9w(id2,npts,xdt0,f0,width,nsubmode,xdt1,snrdb,i1softsymbols) parameter (NFFT=6912,NH=NFFT/2,NQ=NH/2) real s(NQ) @@ -88,17 +88,16 @@ subroutine softsym9w(id2,npts,xdt0,f0,width,nsubmode,xdt1,i1softsymbols) call pctile(s2,9*85,35,xmed) s3=s3/ave sig=sig/69. !Signal - t=max(1.0,sig - 1.0) - snrdb=db(t) + snrdb=db(sig/xmed) - 28.0 m0=3 k=0 do j=1,69 - smax=0. - do i=0,7 - if(s3(i,j).gt.smax) smax=s3(i,j) - enddo - + smax=0. + do i=0,7 + if(s3(i,j).gt.smax) smax=s3(i,j) + enddo + do m=m0-1,0,-1 !Get bit-wise soft symbols if(m.eq.2) then r1=max(s3(4,j),s3(5,j),s3(6,j),s3(7,j))