fixed spectrum, waterfall, and time domain plots for 7500 Fs in FreeDV 700 mode
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 18 Jun 2015 02:28:02 +0000 (02:28 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 18 Jun 2015 02:28:02 +0000 (02:28 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2205 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2-dev/README.txt
fdmdv2-dev/src/dlg_audiooptions.cpp
fdmdv2-dev/src/fdmdv2_main.cpp
fdmdv2-dev/src/fdmdv2_main.h
fdmdv2-dev/src/fdmdv2_plot_spectrum.h
fdmdv2-dev/src/fdmdv2_plot_waterfall.cpp
fdmdv2-dev/src/fdmdv2_plot_waterfall.h

index 5261705c21e2ea9a380089160e4a1635d5c034c0..c53e106a8e01ace74a9576f9a808463d1dcfe6e7 100644 (file)
@@ -163,22 +163,29 @@ TODO
         [X] tx works in full duplex
         [X] clipper a check box, so we can see difference in spectrum
             + adjustable at run time
-        [ ] analog mode
+        [X] analog mode
             + complicated by sample rate change
+        [X] from radio plot broken
+        [X] support for both varicodes
         [ ] squelch
-        [ ] from radio plot broken
-    [ ] freedv api
         [ ] normalise output pwr across modes?
             + or maybe peak output?
             + option?
-        [X] support for both varicodes
     [ ] test mode
         [ ] get error patterns working again, both 700 and 1600
         [ ] how to plot error histogram
     [ ] file sample replay at 7500Hz work OK?
     [ ] interp 7500 to 8k for spectrum plotting
-    [ ] bpf filter after clipping
-        [ ] tcohpsk first
+
+[ ] FreeDV 700 improvements
+    [ ] bpf filter after clipping to remove clicks
+        [ ] tcohpsk first, measure PAPR, impl loss
+    [ ] error masking
+
+[ ] win32 X-compile
+    [ ] installer
+    [ ] works
 [ ] Small fixes
     [X] Playfile bug
     [X] running again
@@ -186,13 +193,10 @@ TODO
     [X] long varicode default
     [X] option to _not_ require checksum, on by default
     [X] default squelch 2dB
-    [ ] win32 X-compile
-        [ ] installer
-        [ ] works
     [ ] cmd line file decode
     [ ] Waterfall direction
     [ ] test mode on 1600 with freedv api
         + maybe calc stats, hist
-    [ ] from radio display breaking up
-[ ] Presence/spotting hooks
+
+[ ] Web support for Presence/spotting hooks
 
index 1c312ef78cf623a93045fe822c46a260f09b15da..7d23a08f1a7890394c0a116b491cf19a5d500deb 100644 (file)
@@ -1003,7 +1003,7 @@ void AudioOptsDialog::plotDeviceInputForAFewSecs(int devNum, PlotScalar *plotSca
                 in48k_short[j] = in48k_stereo_short[j]; 
         }
         int n8k = resample(src, in8k_short, in48k_short, 8000, TEST_FS, TEST_BUF_SIZE, TEST_BUF_SIZE);
-        resample_for_plot(fifo, in8k_short, n8k);
+        resample_for_plot(fifo, in8k_short, n8k, FS);
 
         // every TEST_DT seconds update plot, unfortunately plot
         // doesnt get updated to end as we are blocking events in this
@@ -1117,7 +1117,7 @@ void AudioOptsDialog::plotDeviceOutputForAFewSecs(int devNum, PlotScalar *plotSc
 
         // convert back to 8kHz just for plotting
         int n8k = resample(src, out8k_short, out48k_short, 8000, TEST_FS, TEST_BUF_SIZE, TEST_BUF_SIZE);
-        resample_for_plot(fifo, out8k_short, n8k);
+        resample_for_plot(fifo, out8k_short, n8k, FS);
 
         // every TEST_DT seconds update plot
 
index 304d11c8f0c4bef0a843102bbbad397b0777a024..a699b3053456b14546d35317912e47a3beccae88 100644 (file)
@@ -268,7 +268,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
         // Add Speech Input window
         m_panelSpeechIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, 1, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f", 0);
         m_auiNbookCtrl->AddPage(m_panelSpeechIn, _("Frm Mic"), true, wxNullBitmap);
-        g_plotSpeechInFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
+        g_plotSpeechInFifo = fifo_create(4*WAVEFORM_PLOT_BUF);
     }
 
     if(wxGetApp().m_show_speech_out)
@@ -835,8 +835,10 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
     // Oscilliscope type speech plots -------------------------------------------------------
 
     short speechInPlotSamples[WAVEFORM_PLOT_BUF];
-    if (fifo_read(g_plotSpeechInFifo, speechInPlotSamples, WAVEFORM_PLOT_BUF))
+    if (fifo_read(g_plotSpeechInFifo, speechInPlotSamples, WAVEFORM_PLOT_BUF)) {
         memset(speechInPlotSamples, 0, WAVEFORM_PLOT_BUF*sizeof(short));
+        fprintf(stderr, "empty!\n");
+    }
     m_panelSpeechIn->add_new_short_samples(0, speechInPlotSamples, WAVEFORM_PLOT_BUF, 32767);
     m_panelSpeechIn->Refresh();
 
@@ -847,8 +849,9 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
     m_panelSpeechOut->Refresh();
 
     short demodInPlotSamples[WAVEFORM_PLOT_BUF];
-    if (fifo_read(g_plotDemodInFifo, demodInPlotSamples, WAVEFORM_PLOT_BUF))
+    if (fifo_read(g_plotDemodInFifo, demodInPlotSamples, WAVEFORM_PLOT_BUF)) {
         memset(demodInPlotSamples, 0, WAVEFORM_PLOT_BUF*sizeof(short));
+    }
     m_panelDemodIn->add_new_short_samples(0,demodInPlotSamples, WAVEFORM_PLOT_BUF, 32767);
     m_panelDemodIn->Refresh();
 
@@ -951,7 +954,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
     if ((unsigned)fifo_used(g_txDataInFifo) < strlen(callsign)) {
         unsigned int  i;
 
-        printf("callsign: %s\n", callsign);
+        //printf("callsign: %s\n", callsign);
 
         /* optionally append checksum */
 
@@ -1005,7 +1008,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
                 }
                 unsigned int checksum_tx;
                 int ret = sscanf(&m_callsign[strlen(m_callsign)-2], "%2x", &checksum_tx);
-                printf("m_callsign: %s checksums: %2x %2x\n", m_callsign, checksum_tx, checksum_rx);
+                //printf("m_callsign: %s checksums: %2x %2x\n", m_callsign, checksum_tx, checksum_rx);
 
                 wxString s;
                 if (ret && (checksum_tx == checksum_rx)) {
@@ -1028,13 +1031,13 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
                 }
             }
 
-            fprintf(stderr,"resetting callsign %s %d\n", m_callsign, m_pcallsign-m_callsign);
+            //fprintf(stderr,"resetting callsign %s %d\n", m_callsign, m_pcallsign-m_callsign);
             // reset ptr to start of string
             m_pcallsign = m_callsign;
         }
         else
         {
-            printf("new char %d %c\n", ashort, (char)ashort);
+            //printf("new char %d %c\n", ashort, (char)ashort);
             *m_pcallsign++ = (char)ashort;
             m_txtCtrlCallSign->SetValue(m_callsign);
         }
@@ -1307,16 +1310,16 @@ void MainFrame::togglePTT(void) {
         if (wxGetApp().m_boolUseRTS) {
             printf("g_tx: %d m_boolRTSPos: %d serialLine: %d\n", g_tx, wxGetApp().m_boolRTSPos, g_tx == wxGetApp().m_boolRTSPos);
             if (g_tx == wxGetApp().m_boolRTSPos)
-                               raiseRTS();
+                raiseRTS();
             else
-                               lowerRTS();
+                lowerRTS();
         }
         if (wxGetApp().m_boolUseDTR) {
             printf("g_tx: %d m_boolDTRPos: %d serialLine: %d\n", g_tx, wxGetApp().m_boolDTRPos, g_tx == wxGetApp().m_boolDTRPos);
             if (g_tx == wxGetApp().m_boolDTRPos)
-                               raiseDTR();
+                raiseDTR();
             else
-                               lowerDTR();
+                lowerDTR();
         }
  
     }
@@ -1365,6 +1368,9 @@ void MainFrame::OnTogBtnAnalogClick (wxCommandEvent& event)
     else
         g_analog = 0;
 
+    g_State = 0;
+    g_stats.snr_est = 0;
+
     event.Skip();
 }
 
@@ -1963,8 +1969,8 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
             g_mode = FREEDV_MODE_700;
             g_Nc = 14;
         }
-
-        // init freedv states
+   
+       // init freedv states
 
         g_pfreedv = freedv_open(g_mode);
         g_pfreedv->callback_state = NULL;
@@ -1986,8 +1992,14 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
 
         assert(g_error_pattern != NULL);
 
-        // adjust scatter diagram for Number of FDM carriers
 #endif
+        // adjust spectrum and waterfall freq scaling base on mode
+
+        m_panelSpectrum->setFreqScale(MODEM_STATS_NSPEC*((float)MAX_F_HZ/(g_pfreedv->modem_sample_rate/2)));
+        m_panelWaterfall->setFs(g_pfreedv->modem_sample_rate);
+
+        // adjust scatter diagram for Number of FDM carriers
+
         g_errorFifo = fifo_create(2*g_sz_error_pattern);
 
         m_panelScatter->setNc(g_Nc);
@@ -2594,8 +2606,8 @@ void MainFrame::startRxStream()
 void MainFrame::processTxtEvent(char event[]) {
     int rule = 0;
 
-    printf("processTxtEvent:\n");
-    printf("  event: %s\n", event);
+    //printf("processTxtEvent:\n");
+    //printf("  event: %s\n", event);
 
     // process with regexp and issue system command
 
@@ -2620,14 +2632,14 @@ void MainFrame::processTxtEvent(char event[]) {
             wxString regexp_replace = regexp_replace_list.SubString(0, replace_end-1);
             //printf("match: %s replace: %s\n", (const char *)regexp_match.c_str(), (const char *)regexp_replace.c_str());
             wxRegEx re(regexp_match);
-            printf("  checking for match against: %s\n", (const char *)regexp_match.c_str());
+            //printf("  checking for match against: %s\n", (const char *)regexp_match.c_str());
 
             // if we found a match, lets run the replace regexp and issue the system command
 
             wxString event_str_rep = event_str;
 
             if (re.Replace(&event_str_rep, regexp_replace) != 0) {
-                printf("  found match!\n");
+                //printf("  found match!\n");
                 found_match = true;
 
                 bool enableSystem = false;
@@ -2638,7 +2650,7 @@ void MainFrame::processTxtEvent(char event[]) {
 
                 if (spamTimer[rule].IsRunning()) {
                     enableSystem = false;
-                    printf("  spam timer running\n");
+                    //printf("  spam timer running\n");
                 }
 
                 const char *event_out = event_str_rep.ToUTF8();
@@ -2790,9 +2802,9 @@ int resample(SRC_STATE *src,
 // speech signals at a low sample rate.  We want a low sample rate so
 // we don't hammer the graphics system too hard.  Saves decimated data
 // to a fifo for plotting on screen.
-void resample_for_plot(struct FIFO *plotFifo, short buf[], int length)
+void resample_for_plot(struct FIFO *plotFifo, short buf[], int length, int fs)
 {
-    int decimation = FS/WAVEFORM_PLOT_FS;
+    int decimation = fs/WAVEFORM_PLOT_FS;
     int nSamples, sample;
     int i, st, en, max, min;
     short dec_samples[length];
@@ -2827,10 +2839,17 @@ void txRxProcessing()
     short           in48k_short[4*N48];
     short           out8k_short[4*N8];
     short           out48k_short[4*N48];
-    int             nout;
+    int             nout, samplerate, n_samples;
 
     //wxLogDebug("start infifo1: %5d outfifo1: %5d\n", fifo_n(cbData->infifo1), fifo_n(cbData->outfifo1));
 
+    // FreeDV 700 uses a modem sample rate of 7500 Hz which requires some special treatment
+
+    if (g_analog) 
+        samplerate = FS;
+    else
+        samplerate = g_pfreedv->modem_sample_rate;
+
     //
     //  RX side processing --------------------------------------------
     //
@@ -2845,7 +2864,7 @@ void txRxProcessing()
         g_mutexProtectingCallbackData.Unlock();
         unsigned int n8k;
 
-        n8k = resample(cbData->insrc1, in8k_short, in48k_short, g_pfreedv->modem_sample_rate, g_soundCard1SampleRate, N8, nsam);
+        n8k = resample(cbData->insrc1, in8k_short, in48k_short, samplerate, g_soundCard1SampleRate, N8, nsam);
         assert(n8k <= N8);
 
         // optionally save "from radio" signal (write demod input to file)
@@ -2888,26 +2907,22 @@ void txRxProcessing()
         }
         g_mutexProtectingCallbackData.Unlock();
 
-        fifo_write(cbData->rxinfifo, in8k_short, n8k);
-        resample_for_plot(g_plotDemodInFifo, in8k_short, n8k);
+        resample_for_plot(g_plotDemodInFifo, in8k_short, n8k, samplerate);
 
-        per_frame_rx_processing(cbData->rxoutfifo, cbData->rxinfifo);
-
-#ifdef TMPa
         // Get some audio to send to headphones/speaker.  If out of
         // sync or in analog mode we pass thru the "from radio" audio
         // to the headphones/speaker.  When out of sync it's useful to
         // hear the audio from the channel, e.g. as a tuning aid
         
-        if ((g_State == 0) || g_analog) {
+        if (g_analog) {
             memcpy(out8k_short, in8k_short, sizeof(short)*n8k);
         }
         else {
-            // we are in sync so use decoded audio
+            fifo_write(cbData->rxinfifo, in8k_short, n8k);
+            per_frame_rx_processing(cbData->rxoutfifo, cbData->rxinfifo);
+            memset(out8k_short, 0, sizeof(short)*N8);
+            fifo_read(cbData->rxoutfifo, out8k_short, N8);
         }
-#endif
-        memset(out8k_short, 0, sizeof(short)*N8);
-        fifo_read(cbData->rxoutfifo, out8k_short, N8);
 
         // Optional Spk Out EQ Filtering, need mutex as filter can change at run time
         g_mutexProtectingCallbackData.Lock();
@@ -2925,7 +2940,7 @@ void txRxProcessing()
             memset(out8k_short, 0, sizeof(short)*N8);
         }
 
-        resample_for_plot(g_plotSpeechOutFifo, out8k_short, N8);
+        resample_for_plot(g_plotSpeechOutFifo, out8k_short, N8, FS);
 
         g_mutexProtectingCallbackData.Lock();
         if (g_nSoundCards == 1) {
@@ -3006,9 +3021,12 @@ void txRxProcessing()
             }
             g_mutexProtectingCallbackData.Unlock();
 
-            resample_for_plot(g_plotSpeechInFifo, in8k_short, nout);
+            resample_for_plot(g_plotSpeechInFifo, in8k_short, nout, FS);
+
+            n_samples = g_pfreedv->n_nom_modem_samples;
 
             if (g_analog) {
+                n_samples = g_pfreedv->n_speech_samples;
 
                 // Boost the "from mic" -> "to radio" audio in analog
                 // mode.  The need for the gain was found by
@@ -3018,7 +3036,7 @@ void txRxProcessing()
                 // of the peak level for normal SSB voice. So we
                 // introduce 6dB gain to make analog SSB sound the
                 // same level as the digital.  Watch out for clipping.
-                for(int i=0; i<g_pfreedv->n_nom_modem_samples; i++) {
+                for(int i=0; i<n_samples; i++) {
                     float out = (float)in8k_short[i]*2.0;
                     if (out > 32767) out = 32767.0;
                     if (out < -32767) out = -32767.0;
@@ -3038,7 +3056,7 @@ void txRxProcessing()
             }
 
             // output one frame of modem signal
-            nout = resample(cbData->outsrc1, out48k_short, out8k_short, g_soundCard1SampleRate, g_pfreedv->modem_sample_rate, N48*4, g_pfreedv->n_nom_modem_samples);
+            nout = resample(cbData->outsrc1, out48k_short, out8k_short, g_soundCard1SampleRate, samplerate, N48*4, n_samples);
             g_mutexProtectingCallbackData.Lock();
             ret = fifo_write(cbData->outfifo1, out48k_short, nout);
             //fprintf(stderr,"nout: %d ret: %d N48*4: %d\n", nout, ret, N48*4);
index 72e3e270a2a9f1ba205e38e6d535317c8fb33e63..21543b8640bb8b02d747880281ba4ee709c037f0 100644 (file)
@@ -582,7 +582,7 @@ public:
     bool                    m_run;
 };
 
-void resample_for_plot(struct FIFO *plotFifo, short buf[], int length);
+void resample_for_plot(struct FIFO *plotFifo, short buf[], int length, int fs);
 
 int resample(SRC_STATE *src,
              short      output_short[],
index d3d579c56f69f90701033f60b3c715a6e79a5474..353f3127e885e3ed4455ae7c239f3b0638e14bf5 100644 (file)
@@ -34,6 +34,7 @@ class PlotSpectrum : public PlotPanel
                  float min_mag_db=MIN_MAG_DB, float max_mag_db=MAX_MAG_DB, bool clickTune=true);
         ~PlotSpectrum();
         void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; }
+        void setFreqScale(int n_magdB) { m_n_magdB = n_magdB; }
 
     protected:
         void        OnPaint(wxPaintEvent& event);
index 7037f866df9bb5bbdc697c85773d6e1bb540d94b..d3a29abdb0f0622e5366a5e01695435be86b969d 100644 (file)
@@ -59,6 +59,8 @@ PlotWaterfall::PlotWaterfall(wxFrame* parent, bool graticule, int colour): PlotP
     m_newdata       = false;
     m_firstPass     = true;
     m_line_color    = 0;
+    m_modem_stats_max_f_hz = MODEM_STATS_MAX_F_HZ;
+
     SetLabelSize(10.0);
 
     m_pBmp = NULL;
@@ -340,8 +342,8 @@ void PlotWaterfall::plotPixelData()
     // update min and max amplitude estimates
     float max_mag = MIN_MAG_DB;
 
-    int min_fft_bin=((float)200/MODEM_STATS_MAX_F_HZ)*MODEM_STATS_NSPEC;
-    int max_fft_bin=((float)2800/MODEM_STATS_MAX_F_HZ)*MODEM_STATS_NSPEC;
+    int min_fft_bin=((float)200/m_modem_stats_max_f_hz)*MODEM_STATS_NSPEC;
+    int max_fft_bin=((float)2800/m_modem_stats_max_f_hz)*MODEM_STATS_NSPEC;
 
     for(int i=min_fft_bin; i<max_fft_bin; i++) 
     {
@@ -356,7 +358,7 @@ void PlotWaterfall::plotPixelData()
     //printf("max_mag: %f m_max_mag: %f\n", max_mag, m_max_mag);
     //intensity_per_dB  = (float)256 /(MAX_MAG_DB - MIN_MAG_DB);
     intensity_per_dB  = (float)256 /(m_max_mag - m_min_mag);
-    spec_index_per_px = ((float)(MAX_F_HZ)/(float)MODEM_STATS_MAX_F_HZ)*(float)MODEM_STATS_NSPEC / (float) m_rGrid.GetWidth();
+    spec_index_per_px = ((float)(MAX_F_HZ)/(float)m_modem_stats_max_f_hz)*(float)MODEM_STATS_NSPEC / (float) m_rGrid.GetWidth();
 
     /*
     printf("h %d w %d px_per_sec %d dy %d dy_blocks %d spec_index_per_px: %f\n", 
index e5c0e836f9cd395892674193a69290e7ad5720bc..77058fdaf12f2fc6f61fddfaf9ea85a5ecb140f2 100644 (file)
@@ -42,6 +42,7 @@ class PlotWaterfall : public PlotPanel
         bool checkDT(void);
         void setGreyscale(bool greyscale) { m_greyscale = greyscale; }
         void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; }
+        void setFs(int fs) { m_modem_stats_max_f_hz = fs/2; }
 
     protected:
         unsigned    m_heatmap_lut[256];
@@ -64,6 +65,7 @@ class PlotWaterfall : public PlotPanel
         float       m_min_mag;
         float       m_max_mag;
         int         m_colour;
+        int         m_modem_stats_max_f_hz;
 
         DECLARE_EVENT_TABLE()
 };