From b843894061a1f4950285d3152e7bd465a087b7ee Mon Sep 17 00:00:00 2001 From: Joe Taylor Date: Mon, 11 Apr 2016 20:53:54 +0000 Subject: [PATCH] First working code offering optional computation and use of a reference spectrum. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6608 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- commons.h | 1 + lib/refspectrum.f90 | 128 ++++++++++++++++++++++++++++++++++---------- lib/symspec.f90 | 2 +- mainwindow.cpp | 13 +++-- mainwindow.h | 1 + plotter.cpp | 4 +- widegraph.cpp | 21 ++++++++ widegraph.h | 3 ++ widegraph.ui | 4 +- 9 files changed, 141 insertions(+), 36 deletions(-) diff --git a/commons.h b/commons.h index 03af550a8..71efe693e 100644 --- a/commons.h +++ b/commons.h @@ -62,6 +62,7 @@ extern struct dec_data { extern struct { float syellow[NSMAX]; float ref[3457]; + float filter[3457]; } spectra_; extern struct { diff --git a/lib/refspectrum.f90 b/lib/refspectrum.f90 index 73f13acc3..a3b356a7d 100644 --- a/lib/refspectrum.f90 +++ b/lib/refspectrum.f90 @@ -1,4 +1,4 @@ -subroutine refspectrum(id2,brefspec) +subroutine refspectrum(id2,brefspec,buseref,fname) ! Input: ! id2 i*2 Raw 16-bit integer data, 12000 Hz sample rate @@ -6,24 +6,41 @@ subroutine refspectrum(id2,brefspec) parameter (NFFT=6912,NH=NFFT/2) integer*2 id2(NH) - logical brefspec,brefspec0 - real x(NFFT) - real s(0:NH) - complex cx(0:NH) - common/spectra/syellow(6827),ref(0:NH) + logical*1 brefspec,buseref + + real x0(0:NH-1) !Input samples + real x1(0:NH-1) !Output samples (delayed by one block) + real x0s(0:NH-1) !Saved upper half of input samples + real x1s(0:NH-1) !Saved upper half of output samples + 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) + logical first,firstuse + complex cx(0:NH) !Complex frequency-domain work array + character*(*) fname + common/spectra/syellow(6827),ref(0:NH),filter(0:NH) equivalence(x,cx) - data nsave/0/,brefspec0/.false./ -! save brefspec0,nsave,ref + data first/.true./,firstuse/.true./ 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 + x0s=0. + x1s=0. + first=.false. + endif + if(brefspec) then - if(.not.brefspec0) then - nsave=0 - s=0. - endif - - x(1:NH)=0.001*id2 - x(NH+1:)=0.0 + x(0:NH-1)=0.001*id2 + x(NH:NFFT-1)=0.0 call four2a(x,NFFT,1,-1,0) !r2c FFT do i=1,NH @@ -31,27 +48,80 @@ subroutine refspectrum(id2,brefspec) enddo nsave=nsave+1 - if(mod(nsave,34).eq.0) then !About 9.8 sec + fac0=0.9 + if(mod(nsave,4).eq.0) then df=12000.0/NFFT - ia=nint(500.0/df) - ib=nint(2500.0/df) - call pctile(s(ia),ib-ia+1,50,xmed) - db0=db(xmed) -! nhadd=10 - open(16,file='refspec.dat',status='unknown') + 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. + filter(i)=-60.0 + if(s(i).gt.0.0) then + fil(i)=sqrt(avemid/s(i)) + endif + enddo + + ia=nint(240.0/df) + fac=fac0 + do i=ia,1,-1 + fac=fac*fac0 + fil(i)=fac*fil(i) + enddo + + ib=nint(4000.0/df) + fac=fac0 + do i=ib,NH + fac=fac*fac0 + fil(i)=fac*fil(i) + enddo + + do iter=1,1000 !### ??? ### + 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 + +! open(16,file='refspec.dat',status='unknown') + open(16,file=fname,status='unknown') do i=1,NH freq=i*df -! ia=max(1,i-nhadd) -! ib=min(NH,i+nhadd) -! smo=sum(s(ia:ib))/(ib-ia+1) - ref(i)=db(s(i)) - db0 - write(16,1000) freq,s(i),ref(i) -1000 format(f10.3,e12.3,f12.6) + ref(i)=db(s(i)/avemid) + write(16,1000) freq,s(i),ref(i),fil(i),filter(i) +1000 format(f10.3,e12.3,f12.6,e12.3,f12.6) enddo close(16) endif + return endif - brefspec0=brefspec + + if(buseref) then + if(firstuse) then +! open(16,file='refspec.dat',status='unknown') + fil=1.0 + open(16,file=fname,status='old',err=10) + do i=1,NH + read(16,1000,err=10,end=10) freq,s(i),ref(i),fil(i),filter(i) + enddo +10 close(16) + firstuse=.false. + endif + x0=id2 + x(0:NH-1)=x0s !Previous 2nd half to new 1st half + x(NH:NFFT-1)=x0 !New 2nd half + x0s=x0 !Save the new 2nd half + x=w*x !Apply window + call four2a(x,NFFT,1,-1,0) !r2c FFT (to frequency domain) + cx=fil*cx + call four2a(cx,NFFT,1,1,-1) !c2r FFT (back to time domain) + x1=x1s + x(0:NH-1) !Add previous segment's 2nd half + id2=nint(x1) + x1s=x(NH:NFFT-1) !Save the new 2nd half + endif + return end subroutine refspectrum diff --git a/lib/symspec.f90 b/lib/symspec.f90 index d7f015953..ba5cc28af 100644 --- a/lib/symspec.f90 +++ b/lib/symspec.f90 @@ -30,7 +30,7 @@ subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, & complex cx(0:MAXFFT3/2) integer nch(7) - common/spectra/syellow(NSMAX),ref(0:3456) + common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456) data rms/999.0/,k0/99999999/,nfft3z/0/ data nch/1,2,4,9,18,36,72/ equivalence (xc,cx) diff --git a/mainwindow.cpp b/mainwindow.cpp index 89451cd68..2aaf1a997 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -99,7 +99,8 @@ extern "C" { void hash_calls_(char calls[], int* ih9, int len); void degrade_snr_(short d2[], int* n, float* db, float* bandwidth); void wav12_(short d2[], short d1[], int* nbytes, short* nbitsam2); - void refspectrum_(short int d2[], bool* brefspec); + void refspectrum_(short int d2[], bool* brefspec, bool* buseref, + const char* c_fname, int len); } int volatile itone[NUM_ISCAT_SYMBOLS]; //Audio tones for all Tx symbols @@ -874,7 +875,12 @@ void MainWindow::dataSink(qint64 frames) static float df3; int k (frames); - if(m_bRefSpec) refspectrum_(&dec_data.d2[k-3456],&m_bRefSpec); + QString fname {QDir::toNativeSeparators(m_dataDir.absoluteFilePath ("refspec.dat"))}; + QByteArray bafname = fname.toLatin1(); + const char *c_fname = bafname.data(); + int len=fname.length(); + m_bUseRef=m_wideGraph->useRef(); + refspectrum_(&dec_data.d2[k-3456],&m_bRefSpec,&m_bUseRef,c_fname,len); if(m_diskData) { dec_data.params.ndiskdat=1; @@ -4043,7 +4049,7 @@ void MainWindow::band_changed (Frequency f) if (f + m_wideGraph->nStartFreq () > m_freqNominal + ui->TxFreqSpinBox->value () || f + m_wideGraph->nStartFreq () + m_wideGraph->fSpan () <= m_freqNominal + ui->TxFreqSpinBox->value ()) { - qDebug () << "start f:" << m_wideGraph->nStartFreq () << "span:" << m_wideGraph->fSpan () << "DF:" << ui->TxFreqSpinBox->value (); +// qDebug () << "start f:" << m_wideGraph->nStartFreq () << "span:" << m_wideGraph->fSpan () << "DF:" << ui->TxFreqSpinBox->value (); // disable auto Tx if "blind" QSY outside of waterfall ui->stopTxButton->click (); // halt any transmission auto_tx_mode (false); // disable auto Tx @@ -5344,6 +5350,7 @@ void MainWindow::fastPick(int x0, int x1, int y) void MainWindow::on_actionSave_reference_spectrum_triggered() { + if(!m_monitoring) on_monitorButton_clicked (true); m_bRefSpec=true; } diff --git a/mainwindow.h b/mainwindow.h index c92e14f30..626436587 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -426,6 +426,7 @@ private: bool m_bFastDecodeCalled; bool m_bDoubleClickAfterCQnnn; bool m_bRefSpec; + bool m_bUseRef; float m_pctZap; char m_msg[100][80]; diff --git a/plotter.cpp b/plotter.cpp index 7518aee00..282c8cd37 100644 --- a/plotter.cpp +++ b/plotter.cpp @@ -176,7 +176,9 @@ void CPlotter::draw(float swide[], bool bScroll) //dr if(m_bReference) { //Reference (red) float df_ref=12000.0/6912.0; int j=FreqfromX(i)/df_ref + 0.5; - y2=gain2d*spectra_.ref[j] + m_plot2dZero; + y2=spectra_.ref[j] + m_plot2dZero; + if(gain2d>1.5) y2=spectra_.filter[j] + m_plot2dZero; + } if(i==iz-1) painter2D.drawPolyline(LineBuf,j); diff --git a/widegraph.cpp b/widegraph.cpp index 43a5c536d..546804239 100644 --- a/widegraph.cpp +++ b/widegraph.cpp @@ -51,6 +51,8 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) : m_bFlatten=m_settings->value("Flatten",true).toBool(); ui->cbFlatten->setChecked(m_bFlatten); ui->widePlot->setFlatten(m_bFlatten); + m_bRef=m_settings->value("UseRef",false).toBool(); + ui->cbRef->setChecked(m_bRef); ui->widePlot->setBreadth(m_settings->value("PlotWidth",1000).toInt()); ui->bppSpinBox->setValue(n); m_nsmo=m_settings->value("SmoothYellow",1).toInt(); @@ -130,6 +132,7 @@ void WideGraph::saveSettings() //saveS m_settings->setValue ("UserPalette", QVariant::fromValue (m_userPalette.colours ())); m_settings->setValue ("Fmin", m_fMin); m_settings->setValue("Flatten",m_bFlatten); + m_settings->setValue("UseRef",m_bRef); m_settings->endGroup (); } @@ -377,9 +380,22 @@ void WideGraph::on_paletteComboBox_activated (QString const& palette) //palet void WideGraph::on_cbFlatten_toggled(bool b) //Flatten On/Off { m_bFlatten=b; + if(m_bRef and m_bFlatten) { + m_bRef=false; + ui->cbRef->setChecked(false); + } ui->widePlot->setFlatten(m_bFlatten); } +void WideGraph::on_cbRef_toggled(bool b) +{ + m_bRef=b; + if(m_bRef and m_bFlatten) { + m_bFlatten=false; + ui->cbFlatten->setChecked(false); + } +} + void WideGraph::on_adjust_palette_push_button_clicked (bool) //Adjust Palette { try @@ -404,6 +420,11 @@ bool WideGraph::flatten() //Flatten return m_bFlatten; } +bool WideGraph::useRef() //Flatten +{ + return m_bRef; +} + void WideGraph::on_gainSlider_valueChanged(int value) //Gain { ui->widePlot->setPlotGain(value); diff --git a/widegraph.h b/widegraph.h index 3cfa6783f..4fdce40ed 100644 --- a/widegraph.h +++ b/widegraph.h @@ -40,6 +40,7 @@ public: void setModeTx(QString modeTx); void setLockTxFreq(bool b); bool flatten(); + bool useRef(); void setTol(int n); int smoothYellow(); void setRxBand(QString band); @@ -68,6 +69,7 @@ private slots: void on_fStartSpinBox_valueChanged(int n); void on_paletteComboBox_activated(const QString &palette); void on_cbFlatten_toggled(bool b); + void on_cbRef_toggled(bool b); void on_adjust_palette_push_button_clicked (bool); void on_gainSlider_valueChanged(int value); void on_zeroSlider_valueChanged(int value); @@ -99,6 +101,7 @@ private: bool m_lockTxFreq; bool m_bFlatten; + bool m_bRef; bool m_bHaveTransmitted; //Set true at end of a WSPR transmission QString m_mode; diff --git a/widegraph.ui b/widegraph.ui index dd31f7a24..d3433792a 100644 --- a/widegraph.ui +++ b/widegraph.ui @@ -562,14 +562,14 @@ - Flat + Flatten - Ref + Ref Spec