improved speech plots with a better decimation algorithm
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 5 Nov 2012 05:04:49 +0000 (05:04 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 5 Nov 2012 05:04:49 +0000 (05:04 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@930 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/fdmdv2_defines.h
fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_plot.h
fdmdv2/src/fdmdv2_plot_scalar.cpp
fdmdv2/src/fdmdv2_plot_scalar.h

index 64bf8c4010c1e87efc95f3bea024cf48a20cd6cb..94f9a5c5385db8fdddfea58351f0cef75c023ca2 100644 (file)
@@ -54,9 +54,9 @@
 
 // Waveform plotting constants
 
-#define WAVEFORM_PLOT_FS    100                            // sample rate (points/s) of waveform plotted to screen
+#define WAVEFORM_PLOT_FS    400                            // sample rate (points/s) of waveform plotted to screen
 #define WAVEFORM_PLOT_TIME  5                              // length or entire waveform on screen
-#define WAVEFORM_PLOT_BUF   ((int)(DT*WAVEFORM_PLOT_FS))   // number of sample we add per update
+#define WAVEFORM_PLOT_BUF   ((int)(DT*WAVEFORM_PLOT_FS))   // number of new samples we plot per DT
 
 // sample rate I/O & conversion constants
 
index 8d997df649eff81af8b1befd33d2fa7d0549dd3a..5608aac5daa78f52f82245d8c7e45d9b19e16b01 100644 (file)
@@ -39,9 +39,9 @@ struct CODEC2      *g_pCodec2;
 struct FDMDV       *g_pFDMDV;
 
 struct FDMDV_STATS  g_stats;
-short  g_speechIn[WAVEFORM_PLOT_BUF];
-short  g_speechOut[WAVEFORM_PLOT_BUF];
-short  g_demodIn[WAVEFORM_PLOT_BUF];
+struct FIFO  *g_plotDemodInFifo;
+struct FIFO  *g_plotSpeechOutFifo;
+struct FIFO  *g_plotSpeechInFifo;
 
 int g_nSoundCards = 2;
 
@@ -188,7 +188,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     if(wxGetApp().m_show_freq)
     {
         // Add Frequency Offset window
-        m_panelFreqOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -200, 200, 1, 50, "%3fHz");
+        m_panelFreqOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -200, 200, 1, 50, "%3.0fHz");
         m_auiNbookCtrl->AddPage(m_panelFreqOffset, L"Frequency \u0394", true, wxNullBitmap);
     }
 
@@ -198,6 +198,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
 
        m_panelSpeechIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f");
        m_auiNbookCtrl->AddPage(m_panelSpeechIn, _("Speech In"), true, wxNullBitmap);
+       g_plotSpeechInFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
     }
 
     if(wxGetApp().m_show_speech_out)
@@ -206,6 +207,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
 
        m_panelSpeechOut = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f");
        m_auiNbookCtrl->AddPage(m_panelSpeechOut, _("Speech Out"), true, wxNullBitmap);
+       g_plotSpeechOutFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
     }
 
     if(wxGetApp().m_show_demod_in)
@@ -214,6 +216,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
 
        m_panelDemodIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f");
        m_auiNbookCtrl->AddPage(m_panelDemodIn, _("Demod In"), true, wxNullBitmap);
+       g_plotDemodInFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
     }
 
     wxGetApp().m_strRxInAudio       = pConfig->Read(wxT("/Audio/RxIn"),         wxT("<m_strRxInAudio>"));
@@ -348,20 +351,19 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
     m_panelFreqOffset->add_new_sample(g_stats.foff);
     m_panelFreqOffset->Refresh();
 
-    int nsam = DT*WAVEFORM_PLOT_FS;
-    for(int i=0; i<nsam; i++) {
-       m_panelSpeechIn->add_new_sample((float)g_speechIn[i]/32767);
-    }
+    short speechInPlotSamples[WAVEFORM_PLOT_BUF];
+    fifo_read(g_plotSpeechInFifo, speechInPlotSamples, WAVEFORM_PLOT_BUF);
+    m_panelSpeechIn->add_new_short_samples(speechInPlotSamples, WAVEFORM_PLOT_BUF, 32767);
     m_panelSpeechIn->Refresh();
 
-    for(int i=0; i<nsam; i++) {
-       m_panelSpeechOut->add_new_sample((float)g_speechOut[i]/32767);
-    }
+    short speechOutPlotSamples[WAVEFORM_PLOT_BUF];
+    fifo_read(g_plotSpeechOutFifo, speechOutPlotSamples, WAVEFORM_PLOT_BUF);
+    m_panelSpeechOut->add_new_short_samples(speechOutPlotSamples, WAVEFORM_PLOT_BUF, 32767);
     m_panelSpeechOut->Refresh();
 
-    for(int i=0; i<nsam; i++) {
-       m_panelDemodIn->add_new_sample((float)g_demodIn[i]/32767);
-    }
+    short demodInPlotSamples[WAVEFORM_PLOT_BUF];
+    fifo_read(g_plotDemodInFifo, demodInPlotSamples, WAVEFORM_PLOT_BUF);
+    m_panelDemodIn->add_new_short_samples(demodInPlotSamples, WAVEFORM_PLOT_BUF, 32767);
     m_panelDemodIn->Refresh();
 }
 #endif
@@ -1325,6 +1327,37 @@ static int resample(SRC_STATE *src,
 }
 
 
+// Decimates samples using an algorithm that produces nice plots of
+// 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.
+
+static void resample_for_plot(struct FIFO *plotFifo, short buf[], int length)
+{
+    int decimation = FS/WAVEFORM_PLOT_FS;
+    int nSamples, sample;
+    int i, st, en, max, min;
+    short dec_samples[2*N8];
+
+    assert(length <= 2*N8);
+
+    nSamples = length/decimation;
+
+    for(sample=0; sample<nSamples; sample+=2) {
+       st = decimation*sample;
+       en = decimation*(sample+2);
+       max = min = 0;
+       for(i=st; i<en; i++ ) {
+           if (max < buf[i]) max = buf[i];
+           if (min > buf[i]) min = buf[i];
+       }
+       dec_samples[sample] = max;
+       dec_samples[sample+1] = min;            
+    }
+
+    fifo_write(plotFifo, dec_samples, nSamples);
+}
+
 //-------------------------------------------------------------------------
 // rxCallback()
 //-------------------------------------------------------------------------
@@ -1406,8 +1439,7 @@ int MainFrame::rxCallback(
        n8k = resample(cbData->insrc1, in8k_short, in48k_short, FS, g_soundCard1SampleRate, N8, N48);
        fifo_write(cbData->rxinfifo, in8k_short, n8k);
 
-       assert(sizeof(g_demodIn) <= sizeof(in8k_short));
-       memcpy(g_demodIn, in8k_short, sizeof(g_demodIn)); // undersampled buffer for plotting
+       resample_for_plot(g_plotDemodInFifo, in8k_short, n8k);
 
        per_frame_rx_processing(cbData->rxoutfifo, g_CodecBits, cbData->rxinfifo, &g_nRxIn, &g_State, g_pCodec2);
 
@@ -1421,8 +1453,7 @@ int MainFrame::rxCallback(
            fifo_read(cbData->rxoutfifo, out8k_short, N8);          
        }
 
-       assert(sizeof(g_speechOut) <= sizeof(out8k_short));
-       memcpy(g_speechOut, out8k_short, sizeof(g_speechOut)); // undersampled buffer for plotting
+       resample_for_plot(g_plotSpeechOutFifo, out8k_short, N8);
 
        if (g_nSoundCards == 1) {
            nout = resample(cbData->outsrc2, out48k_short, out8k_short, g_soundCard1SampleRate, FS, N48, N8);
@@ -1472,9 +1503,6 @@ int MainFrame::rxCallback(
 
            nout = resample(cbData->insrc2, in8k_short, in48k_short, FS, g_soundCard2SampleRate, 2*N8, nsam);
 
-           assert(sizeof(g_speechIn) <= sizeof(in8k_short));
-           memcpy(g_speechIn, in8k_short, sizeof(g_speechIn)); // undersampled buffer for plotting
-
            if (write_file) {
                fwrite( in8k_short, sizeof(short), nout, g_write_file);
            }
@@ -1486,6 +1514,8 @@ int MainFrame::rxCallback(
                }
            }
            
+           resample_for_plot(g_plotSpeechInFifo, in8k_short, nout);
+
            per_frame_tx_processing(out8k_short, in8k_short, g_pCodec2);
            
            // output 40ms of modem tone
index fb220e492dda0ec2b9f5f110dd059c2fc0e85d1a..a57cd6dd59002498f8f797c3a2a1c3564021b9b8 100644 (file)
 #define wxUSE_PCX           1
 #define wxUSE_LIBTIFF       1
 
-#define PLOT_BORDER         8
+#define PLOT_BORDER         12
 #define XLEFT_OFFSET        30
-#define XLEFT_TEXT_OFFSET   8
-#define YBOTTOM_OFFSET      25
-#define YBOTTOM_TEXT_OFFSET 8
+#define XLEFT_TEXT_OFFSET   6
+#define YBOTTOM_OFFSET      20
+#define YBOTTOM_TEXT_OFFSET 6
 #define GRID_INCREMENT      50
 
 #define BLACK_COLOR         wxColor(0x00, 0x00, 0x00)
index 8bc90afbc30f25b45252eb1175371ce9a32e54d7..49d57e6db01375275e6581d30d689efa425c0425 100644 (file)
@@ -95,6 +95,19 @@ void PlotScalar::add_new_sample(float sample)
     m_mem[m_samples-1] = sample;
 }
 
+//----------------------------------------------------------------
+// add_new_samples()
+//----------------------------------------------------------------
+void  PlotScalar::add_new_short_samples(short samples[], int length, float scale_factor)
+{
+    int i;
+
+    for(i = 0; i < m_samples-length; i++)
+        m_mem[i] = m_mem[i+length];
+    for(; i < m_samples; i++)
+       m_mem[i] = (float)*samples++/scale_factor;
+}
+
 //----------------------------------------------------------------
 // draw()
 //----------------------------------------------------------------
index 1f69b32d8653aa4e97ec72478d97be5f39f13be7..e6b64e6e1b7403f00e44618a9e2d1584b4446b18 100644 (file)
@@ -46,6 +46,7 @@ class PlotScalar: public PlotPanel
               );
         ~PlotScalar();
          void add_new_sample(float sample);
+         void add_new_short_samples(short samples[], int length, float scale_factor);
 
     protected: