git-svn-id: https://svn.code.sf.net/p/freetel/code@667 01035d8c-6547-0410-b346-abe4f9...
authorwittend99 <wittend99@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 10 Sep 2012 16:45:37 +0000 (16:45 +0000)
committerwittend99 <wittend99@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 10 Sep 2012 16:45:37 +0000 (16:45 +0000)
16 files changed:
fdmdv2/build/fdmdv2.mk
fdmdv2/build/fdmdv2.project
fdmdv2/build/fdmdv2.txt
fdmdv2/src/fdmdv2_defines.h
fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_main.h
fdmdv2/src/fdmdv2_pa_wrapper.cpp
fdmdv2/src/fdmdv2_pa_wrapper.h
fdmdv2/src/fdmdv2_plot.cpp
fdmdv2/src/fdmdv2_plot.h
fdmdv2/src/fdmdv2_plot_scalar.cpp
fdmdv2/src/fdmdv2_plot_scalar.h
fdmdv2/src/fdmdv2_plot_spectrum.cpp
fdmdv2/src/fdmdv2_plot_waterfall.cpp
fdmdv2/src/fdmdv2_plot_waterfall.h
fdmdv2/src/fdmdv2_process_audio.cpp [deleted file]

index 734f6ed3ed76e394c88c45a64a5473e9e633b19b..b230f0b672bc7f1dc218ff3cb8abd42ecd4d1c68 100644 (file)
@@ -13,7 +13,7 @@ CurrentFileName        :=
 CurrentFilePath        :=\r
 CurrentFileFullPath    :=\r
 User                   :=OFA-Staff\r
-Date                   :=9/4/2012\r
+Date                   :=9/9/2012\r
 CodeLitePath           :="C:\bin\CodeLite"\r
 LinkerName             :=g++\r
 SharedObjectLinkerName :=g++ -shared -fPIC\r
@@ -63,7 +63,7 @@ PATH:=$(WXWIN)\lib\gcc_dll;$(PATH)
 WXCFG:=gcc_dll\mswu\r
 UNIT_TEST_PP_SRC_DIR:=C:\bin\UnitTest++-1.3\r
 Objects=$(IntermediateDirectory)/src_dlg_about$(ObjectSuffix) $(IntermediateDirectory)/src_dlg_audio$(ObjectSuffix) $(IntermediateDirectory)/src_dlg_comports$(ObjectSuffix) $(IntermediateDirectory)/src_dlg_options$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_main$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_plot$(ObjectSuffix) $(IntermediateDirectory)/src_topFrame$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_plot_scatter$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_plot_waterfall$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_plot_spectrum$(ObjectSuffix) \\r
-       $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_process_audio$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(ObjectSuffix) \r
+       $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(ObjectSuffix) $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(ObjectSuffix) \r
 \r
 ##\r
 ## Main Build Targets \r
@@ -174,14 +174,6 @@ $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(DependSuffix): ../src/fdmdv2_pa_
 $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(PreprocessSuffix): ../src/fdmdv2_pa_wrapper.cpp\r
        @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(PreprocessSuffix) "C:/bin/Projects/Radio/fdmdv2/src/fdmdv2_pa_wrapper.cpp"\r
 \r
-$(IntermediateDirectory)/src_fdmdv2_process_audio$(ObjectSuffix): ../src/fdmdv2_process_audio.cpp $(IntermediateDirectory)/src_fdmdv2_process_audio$(DependSuffix)\r
-       $(CXX) $(IncludePCH) $(SourceSwitch) "C:/bin/Projects/Radio/fdmdv2/src/fdmdv2_process_audio.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_fdmdv2_process_audio$(ObjectSuffix) $(IncludePath)\r
-$(IntermediateDirectory)/src_fdmdv2_process_audio$(DependSuffix): ../src/fdmdv2_process_audio.cpp\r
-       @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_fdmdv2_process_audio$(ObjectSuffix) -MF$(IntermediateDirectory)/src_fdmdv2_process_audio$(DependSuffix) -MM "C:/bin/Projects/Radio/fdmdv2/src/fdmdv2_process_audio.cpp"\r
-\r
-$(IntermediateDirectory)/src_fdmdv2_process_audio$(PreprocessSuffix): ../src/fdmdv2_process_audio.cpp\r
-       @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_fdmdv2_process_audio$(PreprocessSuffix) "C:/bin/Projects/Radio/fdmdv2/src/fdmdv2_process_audio.cpp"\r
-\r
 $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(ObjectSuffix): ../src/fdmdv2_plot_scalar.cpp $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(DependSuffix)\r
        $(CXX) $(IncludePCH) $(SourceSwitch) "C:/bin/Projects/Radio/fdmdv2/src/fdmdv2_plot_scalar.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_fdmdv2_plot_scalar$(ObjectSuffix) $(IncludePath)\r
 $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(DependSuffix): ../src/fdmdv2_plot_scalar.cpp\r
@@ -229,9 +221,6 @@ clean:
        $(RM) $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(ObjectSuffix)\r
        $(RM) $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(DependSuffix)\r
        $(RM) $(IntermediateDirectory)/src_fdmdv2_pa_wrapper$(PreprocessSuffix)\r
-       $(RM) $(IntermediateDirectory)/src_fdmdv2_process_audio$(ObjectSuffix)\r
-       $(RM) $(IntermediateDirectory)/src_fdmdv2_process_audio$(DependSuffix)\r
-       $(RM) $(IntermediateDirectory)/src_fdmdv2_process_audio$(PreprocessSuffix)\r
        $(RM) $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(ObjectSuffix)\r
        $(RM) $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(DependSuffix)\r
        $(RM) $(IntermediateDirectory)/src_fdmdv2_plot_scalar$(PreprocessSuffix)\r
index 5e984cbb0aecfb68fa5aea9fa89148be2989e98a..c84814c0e1e83a8d8065a4ffbbf10e46f071f8d6 100644 (file)
@@ -19,7 +19,6 @@
     <File Name="../src/fdmdv2_plot_waterfall.cpp"/>
     <File Name="../src/fdmdv2_plot_spectrum.cpp"/>
     <File Name="../src/fdmdv2_pa_wrapper.cpp"/>
-    <File Name="../src/fdmdv2_process_audio.cpp"/>
     <File Name="../src/fdmdv2_plot_scalar.cpp"/>
   </VirtualDirectory>
   <VirtualDirectory Name="include">
index 8abe5d122c04c62f41518e2eb8f3c6526431b488..444adc7e0b44e4afd8e35a82c6ca84447879d29b 100644 (file)
@@ -1 +1 @@
-./Release/src_dlg_about.o ./Release/src_dlg_audio.o ./Release/src_dlg_comports.o ./Release/src_dlg_options.o ./Release/src_fdmdv2_main.o ./Release/src_fdmdv2_plot.o ./Release/src_topFrame.o ./Release/src_fdmdv2_plot_scatter.o ./Release/src_fdmdv2_plot_waterfall.o ./Release/src_fdmdv2_plot_spectrum.o  ./Release/src_fdmdv2_pa_wrapper.o ./Release/src_fdmdv2_process_audio.o ./Release/src_fdmdv2_plot_scalar.o  \r
+./Release/src_dlg_about.o ./Release/src_dlg_audio.o ./Release/src_dlg_comports.o ./Release/src_dlg_options.o ./Release/src_fdmdv2_main.o ./Release/src_fdmdv2_plot.o ./Release/src_topFrame.o ./Release/src_fdmdv2_plot_scatter.o ./Release/src_fdmdv2_plot_waterfall.o ./Release/src_fdmdv2_plot_spectrum.o  ./Release/src_fdmdv2_pa_wrapper.o ./Release/src_fdmdv2_plot_scalar.o  \r
index 39c236585428358348295fb9039e8f5d27d6f63c..f4fd7bc53d87e5f2eba1b6b678d9c3410b891b2b 100644 (file)
@@ -24,7 +24,7 @@
 //==========================================================================\r
 #ifndef __FDMDV2_DEFINES__
 #define __FDMDV2_DEFINES__
-
+#include "wx/wx.h"
 /* FFT points */
 #define FDMDV_NSPEC         512
 \r
@@ -71,8 +71,8 @@
 #define N48                 (N8*FDMDV_OS)                  // processing buffer size at 48 kHz
 #define NUM_CHANNELS        2                              // I think most sound cards prefer stereo we will convert to mono
 
-#define BITS_PER_CODEC_FRAME (2*FDMDV_BITS_PER_FRAME)
-#define BYTES_PER_CODEC_FRAME (BITS_PER_CODEC_FRAME/8)
+#define BITS_PER_CODEC_FRAME  (2 * FDMDV_BITS_PER_FRAME)
+#define BYTES_PER_CODEC_FRAME (BITS_PER_CODEC_FRAME / 8)
 
 /* 8 to 48 kHz sample rate conversion */
 #define FDMDV_OS                 6         /* oversampling rate           */
index 4cbd0f3eeaaf2c0463db35b127d631dfc54b2af7..c8264bfb362b341116818c28bd7831b202e9454c 100644 (file)
 #define wxUSE_PCX       1\r
 #define wxUSE_LIBTIFF   1\r
 \r
-static int rxCallback(\r
-                        const void *inBuffer,\r
-                        void *outBuffer,\r
-                        unsigned long framesPerBuffer,\r
-                        const PaStreamCallbackTimeInfo *outTime,\r
-                        PaStreamCallbackFlags statusFlags,\r
-                        void *userData\r
-                     );\r
-static int txCallback(\r
-                        const void *inBuffer,\r
-                        void *outBuffer,\r
-                        unsigned long framesPerBuffer,\r
-                        const PaStreamCallbackTimeInfo *outTime,\r
-                        PaStreamCallbackFlags statusFlags,\r
-                        void *userData\r
-                     );\r
-\r
-float  av_mag[FDMDV_NSPEC];                  // shared between a few classes
+//float  av_mag[FDMDV_NSPEC];                  // shared between a few classes
 \r
 // initialize the application\r
 IMPLEMENT_APP(MainApp);\r
@@ -65,29 +48,15 @@ bool MainApp::OnInit()
     // Create the main application window\r
     MainFrame *frame = new MainFrame(NULL);\r
 \r
-    frame->m_panelDefaultA = new PlotPanel((wxFrame*) frame->m_auiNbookCtrl );\r
-    frame->m_auiNbookCtrl->AddPage(frame->m_panelDefaultA, _("Test A"), true, wxNullBitmap );\r
-\r
-//    frame->m_panelDefaultB = new PlotPanel((wxFrame*) frame->m_auiNbookCtrl );\r
-//    frame->m_auiNbookCtrl->AddPage(frame->m_panelDefaultB, _("Test B"), true, wxNullBitmap );\r
-\r
-    frame->m_panelSpectrum = new PlotSpectrum((wxFrame*) frame->m_auiNbookCtrl );\r
-    frame->m_auiNbookCtrl->AddPage(frame->m_panelSpectrum, _("Spectrum"), true, wxNullBitmap );\r
-\r
-    frame->m_panelWaterfall = new PlotWaterfall((wxFrame*) frame->m_auiNbookCtrl );\r
-    frame->m_auiNbookCtrl->AddPage(frame->m_panelWaterfall, _("Waterfall"), true, wxNullBitmap );\r
-\r
-//    frame->m_panelScatter = new PlotScatter((wxFrame*) frame->m_auiNbookCtrl );\r
-//    frame->m_auiNbookCtrl->AddPage(frame->m_panelWaterfall, _("Scatter"), true, wxNullBitmap );\r
-\r
-//    frame->m_panelScalar = new PlotScalar((wxFrame*) frame->m_auiNbookCtrl, 500, 500);\r
-//    frame->m_auiNbookCtrl->AddPage(frame->m_panelWaterfall, _("Scalar"), true, wxNullBitmap );\r
+    SetTopWindow(frame);\r
 \r
+    // Should guarantee that the first plot tab defined is the one\r
+    // displayed. But it doesn't when built from command line.  Why?\r
     frame->m_auiNbookCtrl->ChangeSelection(0);\r
 \r
-    SetTopWindow(frame);\r
     frame->Layout();\r
     frame->Show();\r
+\r
     return true;\r
 }\r
 \r
@@ -104,6 +73,23 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     {\r
         wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK);\r
     }\r
+    // Add Waterfall Plot window\r
+    m_panelWaterfall = new PlotWaterfall((wxFrame*) m_auiNbookCtrl );\r
+    m_auiNbookCtrl->AddPage(m_panelWaterfall, _("Waterfall"), true, wxNullBitmap );\r
+\r
+    // Add Spectrum Plot window\r
+    m_panelSpectrum = new PlotSpectrum((wxFrame*) m_auiNbookCtrl );\r
+    m_auiNbookCtrl->AddPage(m_panelSpectrum, _("Spectrum"), true, wxNullBitmap );\r
+\r
+//    m_panelScatter = new PlotScatter((wxFrame*) m_auiNbookCtrl );\r
+//    m_auiNbookCtrl->AddPage(m_panelWaterfall, _("Scatter"), true, wxNullBitmap );\r
+\r
+//    m_panelScalar = new PlotScalar((wxFrame*) m_auiNbookCtrl, 500, 500);\r
+//    m_auiNbookCtrl->AddPage(m_panelWaterfall, _("Scalar"), true, wxNullBitmap );\r
+\r
+    // Add generic plot window\r
+    m_panelDefaultA = new PlotPanel((wxFrame*) m_auiNbookCtrl );\r
+    m_auiNbookCtrl->AddPage(m_panelDefaultA, _("Test A"), true, wxNullBitmap );\r
 }\r
 \r
 //-------------------------------------------------------------------------\r
@@ -144,7 +130,7 @@ void MainFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
     }\r
     dc.SetUserScale(m_zoom, m_zoom);\r
     const wxSize size = GetClientSize();\r
-    dc.DrawBitmap(m_bitmap, dc.DeviceToLogicalX((size.x - m_zoom * m_bitmap.GetWidth()) / 2), dc.DeviceToLogicalY((size.y - m_zoom * m_bitmap.GetHeight()) / 2), true);\r
+//    dc.DrawBitmap(m_bitmap, dc.DeviceToLogicalX((size.x - m_zoom * m_bitmap.GetWidth()) / 2), dc.DeviceToLogicalY((size.y - m_zoom * m_bitmap.GetHeight()) / 2), true);\r
 }\r
 \r
 //-------------------------------------------------------------------------\r
@@ -251,11 +237,12 @@ void MainFrame::OnTogBtnALCClick(wxCommandEvent& event)
     wxMessageBox(wxT("Got Click!"), wxT("OnTogBtnALCClick"), wxOK);\r
     event.Skip();\r
 }\r
+/*\r
 \r
 //-------------------------------------------------------------------------\r
 // rxCallback()\r
 //-------------------------------------------------------------------------\r
-static int rxCallback(\r
+int  MainFrame::rxCallback(\r
                         const void *inBuffer,\r
                         void *outBuffer,\r
                         unsigned long framesPerBuffer,\r
@@ -283,12 +270,13 @@ static int rxCallback(
         *out++  = 0.5f * (leftIn + rightIn);        // mixing\r
     }\r
     return paContinue;                              // 0;\r
-}
-\r
+}\r
+ * */
+/*\r
 //-------------------------------------------------------------------------\r
 // txCallback()\r
 //-------------------------------------------------------------------------\r
-static int txCallback(\r
+int  MainFrame::txCallback(\r
                         const void *inBuffer,\r
                         void *outBuffer,\r
                         unsigned long framesPerBuffer,\r
@@ -317,6 +305,7 @@ static int txCallback(
     }\r
     return paContinue;                              // 0;\r
 }
+*/\r
 \r
 //-------------------------------------------------------------------------\r
 // OnTogBtnOnOff()\r
@@ -529,14 +518,12 @@ void MainFrame::OnClose( wxCommandEvent& event )
 {\r
     if(m_sound != NULL)\r
     {\r
-        //if(m_sound->IsOk()IsPlaying())\r
-        //{\r
+        if(m_sound->IsOk())\r
+        {\r
             m_sound->Stop();\r
             m_sound = NULL;\r
-        //}\r
+        }\r
     }\r
-//    wxMessageBox("Got Click!", "OnClose", wxOK);\r
-//    event.Skip();\r
 }\r
 \r
 //-------------------------------------------------------------------------\r
index 986743ccb736f9b8df2626bad9dbd02a7a54044b..5c2b059ed079d6ddd05f7b85ecd69c6138d115c3 100644 (file)
@@ -63,7 +63,7 @@ class MainApp : public wxApp
 DECLARE_APP(MainApp)
 
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
-// Class MainApp\r
+// Class MainFrame\r
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
 class MainFrame : public TopFrame
 {
@@ -91,15 +91,32 @@ class MainFrame : public TopFrame
         PaError         m_rxErr;
         PaError         m_txErr;
         wxSound         *m_sound;
-        float           av_mag[FDMDV_NSPEC];\r
-
-        void DoStartThread();\r
-        void DoPauseThread();\r
+//        static int (*rxCallback(void const*, void*, unsigned long, PaStreamCallbackTimeInfo const*, unsigned long, void*));
+/*\r
+        static int rxCallback(\r
+                                const void *inBuffer,\r
+                                void *outBuffer,\r
+                                unsigned long framesPerBuffer,\r
+                                const PaStreamCallbackTimeInfo *outTime,\r
+                                PaStreamCallbackFlags statusFlags,\r
+                                void *userData\r
+                             );\r
+        static int txCallback(\r
+                                const void *inBuffer,\r
+                                void *outBuffer,\r
+                                unsigned long framesPerBuffer,\r
+                                const PaStreamCallbackTimeInfo *outTime,\r
+                                PaStreamCallbackFlags statusFlags,\r
+                                void *userData\r
+                             );\r
+*/\r
+//        void DoStartThread();\r
+//        void DoPauseThread();\r
 \r
         //void DoResumeThread() { ... }\r
 \r
-        void OnThreadUpdate(wxThreadEvent&);\r
-        void OnThreadCompletion(wxThreadEvent&);\r
+//        void OnThreadUpdate(wxThreadEvent&);\r
+//        void OnThreadCompletion(wxThreadEvent&);\r
 \r
     protected:\r
 //        Fdmdv2ThreadAudio *m_pThread;\r
@@ -169,13 +186,30 @@ class MainFrame : public TopFrame
         bool        m_useMemory;
 
         wxTextCtrl* m_tc;
-        wxBitmap    m_bitmap;
-        wxBitmap    m_alphaBitmap;
+//        wxBitmap    m_bitmap;
+//        wxBitmap    m_alphaBitmap;
         int         m_zoom;
 
         // any class wishing to process wxWidgets events must use this macro
 //    DECLARE_EVENT_TABLE()
 };
 
-
+/*\r
+typedef int (ClassName::*CallbackType)(float);\r
+\r
+void DoWork(CallbackType callback)\r
+{\r
+  //Class instance to invoke it through\r
+  ClassName instance;\r
+\r
+  //Invocation\r
+  int result = instance->*callback(1.0f);\r
+}\r
+\r
+int main(int argc, char ** argv)\r
+{\r
+  //Pass in SomeCallback to the DoWork\r
+  DoWork(&ClassName::Method);\r
+}\r
+*/
 #endif //__FDMDV2_MAIN__
index fb4610bc81186032af0d389242e4ac8c7b784599..35121f6b26ed70c57890732d7605048b1c8e7e6d 100644 (file)
@@ -32,7 +32,8 @@ PortAudioWrap::PortAudioWrap()
     statusFlags             = 0;\r
     streamCallback          = NULL;\r
     streamFinishedCallback  = NULL;\r
-    timeInfo                = 0;
+    timeInfo                = 0;\r
+    loadData();\r
 }
 
 PortAudioWrap::~PortAudioWrap()
@@ -68,7 +69,6 @@ PaError PortAudioWrap::streamClose()
     if(isOpen())
     {
         PaError rv = Pa_CloseStream(stream);
-//        stream = NULL;
         return rv;
     }
     else
@@ -216,14 +216,12 @@ PaError PortAudioWrap::setStreamFlags(PaStreamFlags flags)
 
 PaError PortAudioWrap::setInputDevice(PaDeviceIndex index)\r
 {
-//    inputDevice = index;
     inputBuffer.device = index;
     return paNoError;
 }
 
 PaError PortAudioWrap::setOutputDevice(PaDeviceIndex index)\r
 {
-//    outputDevice = index;
     outputBuffer.device = index;
     return paNoError;
 }
@@ -233,3 +231,192 @@ PaError PortAudioWrap::setCallback(PaStreamCallback *callback)
     streamCallback = callback;
     return paNoError;
 }
+\r
+typedef struct
+{
+    float               in48k[FDMDV_OS_TAPS + N48];
+    float               in8k[MEM8 + N8];
+} paCallBackData;
+\r
+
+//----------------------------------------------------------------
+// per_frame_rx_processing()
+//----------------------------------------------------------------
+void  PortAudioWrap::per_frame_rx_processing(
+                                short   output_buf[],  /* output buf of decoded speech samples          */
+                                int     *n_output_buf, /* how many samples currently in output_buf[]    */
+                                int     codec_bits[],  /* current frame of bits for decoder             */
+                                short   input_buf[],   /* input buf of modem samples input to demod     */
+                                int     *n_input_buf,  /* how many samples currently in input_buf[]     */
+                                int     *nin,          /* amount of samples demod needs for next call   */
+                                int     *state,        /* used to collect codec_bits[] halves           */
+                                struct  CODEC2 *c2     /* Codec 2 states                                */
+                            )
+{
+    struct FDMDV_STATS  stats;
+    int                 sync_bit;
+    float               rx_fdm[FDMDV_MAX_SAMPLES_PER_FRAME];
+    int                 rx_bits[FDMDV_BITS_PER_FRAME];
+    unsigned char       packed_bits[BYTES_PER_CODEC_FRAME];
+    float               rx_spec[FDMDV_NSPEC];
+    int                 i;\r
+    int                 nin_prev;\r
+    int                 bit;\r
+    int                 byte;
+    int                 next_state;
+
+    assert(*n_input_buf <= (2 * FDMDV_NOM_SAMPLES_PER_FRAME));
+
+    /*
+      This while loop will run the demod 0, 1 (nominal) or 2 times:
+
+      0: when tx sample clock runs faster than rx, occasionally we
+         will run out of samples
+
+      1: normal, run decoder once, every 2nd frame output a frame of
+         speech samples to D/A
+
+      2: when tx sample clock runs slower than rx, occasionally we will
+         have enough samples to run demod twice.
+
+      With a +/- 10 Hz sample clock difference at FS=8000Hz (+/- 1250
+      ppm), case 0 or 1 occured about once every 30 seconds.  This is
+      no problem for the decoded audio.
+    */
+    while(*n_input_buf >= *nin)
+    {
+        // demod per frame processing
+        for(i = 0; i < *nin; i++)
+        {
+            rx_fdm[i] = (float)input_buf[i]/FDMDV_SCALE;
+        }
+        nin_prev = *nin;
+        fdmdv_demod(fdmdv_state, rx_bits, &sync_bit, rx_fdm, nin);
+        *n_input_buf -= nin_prev;
+        assert(*n_input_buf >= 0);
+
+        // shift input buffer
+        for(i=0; i<*n_input_buf; i++)
+        {
+            input_buf[i] = input_buf[i+nin_prev];
+        }
+
+        // compute rx spectrum & get demod stats, and update GUI plot data
+        fdmdv_get_rx_spectrum(fdmdv_state, rx_spec, rx_fdm, nin_prev);
+        fdmdv_get_demod_stats(fdmdv_state, &stats);
+        averageData(rx_spec);
+//        aScatter->add_new_samples(stats.rx_symbols);
+//        aTimingEst->add_new_sample(stats.rx_timing);
+//        aFreqEst->add_new_sample(stats.foff);
+//        aSNR->add_new_sample(stats.snr_est);
+        /*
+           State machine to:
+
+           + Mute decoded audio when out of sync.  The demod is synced
+             when we are using the fine freq estimate and SNR is above
+             a thresh.
+
+           + Decode codec bits only if we have a 0,1 sync bit
+             sequence.  Collects two frames of demod bits to decode
+             one frame of codec bits.
+        */
+        next_state = *state;
+        switch(*state)
+        {
+            case 0:
+                // mute output audio when out of sync
+                if(*n_output_buf < 2 * codec2_samples_per_frame(c2) - N8)
+                {
+                    for(i=0; i<N8; i++)\r
+                    {
+                        output_buf[*n_output_buf + i] = 0;
+                    }
+                    *n_output_buf += N8;
+                }
+                assert(*n_output_buf <= (2 * codec2_samples_per_frame(c2)));
+                if((stats.fest_coarse_fine == 1) && (stats.snr_est > 3.0))
+                {
+                    next_state = 1;
+                }
+                break;
+
+            case 1:
+                if(sync_bit == 0)
+                {
+                    next_state = 2;
+                    // first half of frame of codec bits
+                    memcpy(codec_bits, rx_bits, FDMDV_BITS_PER_FRAME * sizeof(int));
+                }
+                else
+                {
+                    next_state = 1;
+                }
+                if(stats.fest_coarse_fine == 0)
+                {
+                    next_state = 0;
+                }
+                break;
+
+            case 2:
+                next_state = 1;
+                if(stats.fest_coarse_fine == 0)
+                {
+                    next_state = 0;
+                }
+                if(sync_bit == 1)
+                {
+                    // second half of frame of codec bits
+                    memcpy(&codec_bits[FDMDV_BITS_PER_FRAME], rx_bits, FDMDV_BITS_PER_FRAME*sizeof(int));
+                    // pack bits, MSB received first
+                    bit  = 7;
+                    byte = 0;
+                    memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
+                    for(i = 0; i < BITS_PER_CODEC_FRAME; i++)
+                    {
+                        packed_bits[byte] |= (codec_bits[i] << bit);
+                        bit--;
+                        if(bit < 0)
+                        {
+                            bit = 7;
+                            byte++;
+                        }
+                    }
+                    assert(byte == BYTES_PER_CODEC_FRAME);
+                    // add decoded speech to end of output buffer
+                    if(*n_output_buf <= codec2_samples_per_frame(c2))
+                    {
+                        codec2_decode(c2, &output_buf[*n_output_buf], packed_bits);
+                        *n_output_buf += codec2_samples_per_frame(c2);
+                    }
+                    assert(*n_output_buf <= (2 * codec2_samples_per_frame(c2)));
+                }
+                break;
+        }
+        *state = next_state;
+    }
+}\r
+\r
+//----------------------------------------------------------------
+// update average of each spectrum point
+//----------------------------------------------------------------
+void PortAudioWrap::averageData(float mag_dB[])
+{
+    int i;
+
+    for(i = 0; i < FDMDV_NSPEC; i++)
+    {
+        m_av_mag[i] = (1.0 - BETA) * m_av_mag[i] + BETA * mag_dB[i];
+    }
+}\r
+\r
+//----------------------------------------------------------------
+// create Dummy Data
+//----------------------------------------------------------------
+void PortAudioWrap::loadData()\r
+{\r
+    int i;\r
+    for(i = 0; i < FDMDV_NSPEC; i++)\r
+    {\r
+        m_av_mag[i] = i;\r
+    }\r
+}
index 0076f5b48c6ab5deb977bd31fbce23a1c1c6b24d..657baa055887e25a4fa68449df4c0333ca58974c 100644 (file)
@@ -1,14 +1,14 @@
 //==========================================================================\r
 // Name:            fdmdv2_pa_wrapper.h\r
 // Purpose:         Defines a wrapper class around PortAudio\r
-// Created:         August 12, 2012
+// Created:         August 12, 2012\r
 // Initial author:  David Witten\r
 // License:\r
 //\r
-//  Copyright (C) 2012 David Witten
-//
-//  All rights reserved.
-//
+//  Copyright (C) 2012 David Witten\r
+//\r
+//  All rights reserved.\r
+//\r
 //  This program is free software; you can redistribute it and/or modify
 //  it under the terms of the GNU Lesser General Public License version 2.1,
 //  as published by the Free Software Foundation.  This program is
 //  You should have received a copy of the GNU Lesser General Public License
 //  along with this program; if not, see <http://www.gnu.org/licenses/>.
 //
-//==========================================================================\r
+//==========================================================================
 #include <stdio.h>
 #include <math.h>
+#include "fdmdv2_defines.h"
+#include "fdmdv.h"
+#include "codec2.h"
 #include "portaudio.h"
-\r
+
 // Note that many of the older ISA sound cards on PCs do NOT support
 // full duplex audio (simultaneous record and playback).
 // And some only support full duplex at lower sample rates.
 //#define SAMPLE_RATE         (44100)
+//
 #define PA_SAMPLE_TYPE      paFloat32       //paInt16
 #define FRAMES_PER_BUFFER   (64)
 
 typedef float SAMPLE;
 
-float CubicAmplifier(float input);
-
-class PortAudioWrap\r
-{\r
-    public:\r
-        PortAudioWrap();\r
+class PortAudioWrap
+{
+    public:
+        PortAudioWrap();
         ~PortAudioWrap();\r
+
+        float                           m_av_mag[FDMDV_NSPEC];
 \r
-    private:\r
-        PaStream                        *stream;\r
+    private:
+        PaStream                        *stream;
         PaStreamParameters              inputBuffer;
         PaStreamParameters              outputBuffer;
-        void                            *userData;\r
-        int                             samplerate;\r
+        void                            *userData;
+        int                             samplerate;
         unsigned long                   framesPerBuffer;
-        PaStreamCallbackFlags           statusFlags;\r
-        PaStreamCallback                *streamCallback;\r
-        PaStreamFinishedCallback        *streamFinishedCallback;\r
+        PaStreamCallbackFlags           statusFlags;
+        PaStreamCallback                *streamCallback;
+        PaStreamFinishedCallback        *streamFinishedCallback;
         const PaStreamCallbackTimeInfo  *timeInfo;
-//        PaDeviceIndex                   inputDevice;
-//        PaDeviceIndex                   outputDevice;
+        struct FDMDV                    *fdmdv_state;\r
 \r
     public:\r
-
-        PaError streamOpen();\r
+        void per_frame_rx_processing(\r
+            short   output_buf[],  /* output buf of decoded speech samples          */\r
+            int     *n_output_buf, /* how many samples currently in output_buf[]    */\r
+            int     codec_bits[],  /* current frame of bits for decoder             */\r
+            short   input_buf[],   /* input buf of modem samples input to demod     */\r
+            int     *n_input_buf,  /* how many samples currently in input_buf[]     */\r
+            int     *nin,          /* amount of samples demod needs for next call   */\r
+            int     *state,        /* used to collect codec_bits[] halves           */\r
+            struct  CODEC2 *c2     /* Codec 2 states                                */\r
+        );\r
 \r
-        PaDeviceIndex getDefaultInputDevice();
-        PaDeviceIndex getDefaultOutputDevice();\r
+        /*\r
+                static int Callback(\r
+                                        const void *inBuffer,\r
+                                        void *outBuffer,\r
+                                        unsigned long framesPerBuffer,\r
+                                        const PaStreamCallbackTimeInfo *outTime,\r
+                                        PaStreamCallbackFlags statusFlags,\r
+                                        void *userData\r
+                                   );\r
+                static int txCallback(\r
+                                        const void *inBuffer,\r
+                                        void *outBuffer,\r
+                                        unsigned long framesPerBuffer,\r
+                                        const PaStreamCallbackTimeInfo *outTime,\r
+                                        PaStreamCallbackFlags statusFlags,\r
+                                        void *userData\r
+                                     );\r
+        */\r
 \r
-        PaStreamParameters *getDeviceInfo(PaDeviceIndex idx);\r
-        PaError     setFramesPerBuffer(unsigned long size);\r
-        PaError     setSampleRate(unsigned long size);\r
-        PaError     setStreamFlags(PaStreamFlags flags);\r
-        PaError     setCallback(PaStreamCallback *streamCallback);\r
-        PaError     setStreamCallback(PaStream *stream, PaStreamCallback* callback ) { streamCallback = callback; return 0;}
-        PaError     setStreamFinishedCallback(PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback );
-
-        PaError     setInputDevice(PaDeviceIndex dev);\r
-        PaError     setInputChannelCount(int count);
-        int         getInputChannelCount();
-        PaError     setInputSampleFormat(PaSampleFormat format);
-        PaError     setInputSampleRate(PaSampleFormat format);
-        PaError     setInputLatency(PaTime latency);\r
-        void        setInputHostApiStreamInfo(void *info = NULL);\r
-        PaTime      getInputDefaultLowLatency();
-        const char  *getDeviceName(PaDeviceIndex dev);
-
-        PaError     setOutputDevice(PaDeviceIndex dev);\r
-        PaError     setOutputChannelCount(int count);
-        const int   getOutputChannelCount();
-        PaError     setOutputSampleFormat(PaSampleFormat format);
-        PaError     setOutputLatency(PaTime latency);
-        void        setOutputHostApiStreamInfo(void *info = NULL);
-        PaTime      getOutputDefaultLowLatency();
+        PaDeviceIndex       getDefaultInputDevice();\r
+        PaDeviceIndex       getDefaultOutputDevice();\r
+        PaStreamParameters  *getDeviceInfo(PaDeviceIndex idx);\r
+\r
+        PaError             setFramesPerBuffer(unsigned long size);\r
+        PaError             setSampleRate(unsigned long size);\r
+        PaError             setStreamFlags(PaStreamFlags flags);\r
+        PaError             setCallback(PaStreamCallback *streamCallback);\r
+        PaError             setStreamCallback(PaStream *stream, PaStreamCallback* callback) { streamCallback = callback; return 0;}\r
+        PaError             setStreamFinishedCallback(PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback);\r
+        PaError             streamOpen();\r
+\r
+        PaError             setInputDevice(PaDeviceIndex dev);\r
+        PaError             setInputChannelCount(int count);\r
+        int                 getInputChannelCount();\r
+        PaError             setInputSampleFormat(PaSampleFormat format);\r
+        PaError             setInputSampleRate(PaSampleFormat format);\r
+        PaError             setInputLatency(PaTime latency);\r
+        void                setInputHostApiStreamInfo(void *info = NULL);\r
+        PaTime              getInputDefaultLowLatency();\r
+        const char          *getDeviceName(PaDeviceIndex dev);\r
+\r
+        PaError             setOutputDevice(PaDeviceIndex dev);\r
+        PaError             setOutputChannelCount(int count);\r
+        const int           getOutputChannelCount();\r
+        PaError             setOutputSampleFormat(PaSampleFormat format);\r
+        PaError             setOutputLatency(PaTime latency);\r
+        PaError             streamStart();\r
+        PaError             streamClose();\r
+        void                setOutputHostApiStreamInfo(void *info = NULL);\r
+        PaTime              getOutputDefaultLowLatency();\r
+        void                averageData(float mag_dB[]);\r
+\r
+        void                setFdmdvState(FDMDV* fdmdv_state)                       {this->fdmdv_state = fdmdv_state;}
+//        void                setFramesPerBuffer(unsigned long framesPerBuffer)       {this->framesPerBuffer = framesPerBuffer;}
+        void                setInputBuffer(const PaStreamParameters& inputBuffer)   {this->inputBuffer = inputBuffer;}
+//        void                setAvMag(float av_mag)                                  {this->m_av_mag = av_mag;}
+        void                setOutputBuffer(const PaStreamParameters& outputBuffer) {this->outputBuffer = outputBuffer;}
+        void                setSamplerate(int samplerate)                           {this->samplerate = samplerate;}
+        void                setStatusFlags(const PaStreamCallbackFlags& statusFlags) {this->statusFlags = statusFlags;}
+        void                setStream(PaStream* stream)                             {this->stream = stream;}
+//        void                setStreamCallback(PaStreamCallback* streamCallback)     {this->streamCallback = streamCallback;}
+        void                setStreamFinishedCallback(PaStreamFinishedCallback* streamFinishedCallback) {this->streamFinishedCallback = streamFinishedCallback;}\r
+        void                setTimeInfo(PaStreamCallbackTimeInfo* timeInfo)         {this->timeInfo = timeInfo;}\r
+        void                setUserData(void* userData)                             {this->userData = userData;}\r
+        FDMDV*              getFdmdvState()                                         {return fdmdv_state;}\r
+        unsigned long       getFramesPerBuffer() const                              {return framesPerBuffer;}\r
+        const               PaStreamParameters& getInputBuffer() const              {return inputBuffer;}\r
+//        const float         *getAvMag(int idx) const                                 {return (float *)&m_av_mag[idx];}\r
+        const               PaStreamParameters& getOutputBuffer() const             {return outputBuffer;}\r
+        int                 getSamplerate() const                                   {return samplerate;}\r
+        const PaStreamCallbackFlags& getStatusFlags() const                         {return statusFlags;}\r
+        PaStream*           getStream()                                             {return stream;}\r
+//        PaStreamCallback*  getStreamCallback()                                       {return streamCallback;}\r
+//        PaStreamFinishedCallback* getStreamFinishedCallback()                       {return streamFinishedCallback;}\r
+//        PaStreamCallbackTimeInfo* getTimeInfo()                                     {return timeInfo;}\r
+        void                *getUserData()                                          {return userData;}\r
 \r
-//        PaError     init();\r
-        PaError     streamStart();\r
-        PaError     streamClose();\r
-        void        terminate();\r
-        bool        isOpen() const;\r
-        void        stop();
-        void        abort();
-        bool        isStopped() const;
-        bool        isActive() const;
+        void                terminate();\r
+        void                stop();\r
+        void                abort();\r
+        bool                isOpen() const;\r
+        bool                isStopped() const;\r
+        bool                isActive() const;\r
+        void                loadData();\r
 };\r
index a1d4e9c9794eec4c0f8746e8a5b48e6ac0594d02..dfabe00a3bab2666ebc5a96d9fbfc8b030682d3d 100644 (file)
@@ -8,8 +8,6 @@
 //                  components of this project)\r
 //==========================================================================\r
 #include <string.h>\r
-#include "wx/wx.h"\r
-#include "fdmdv2_main.h"\r
 #include "fdmdv2_plot.h"\r
 \r
 BEGIN_EVENT_TABLE(PlotPanel, wxPanel)\r
@@ -27,13 +25,31 @@ END_EVENT_TABLE()
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
 PlotPanel::PlotPanel(wxFrame* parent) : wxPanel(parent)\r
 {\r
+    m_pNoteBook         = (wxAuiNotebook *) parent;\r
+    m_pTopFrame         = (MainFrame *)m_pNoteBook->GetParent();\r
+    m_bmp               = new wxBitmap(MAX_BMP_X, MAX_BMP_Y, wxBITMAP_SCREEN_DEPTH);
+    wxNativePixelData m_pBmp(*m_bmp);\r
+    if ( !m_pBmp )\r
+    {\r
+        // ... raw access to bitmap data unavailable, do something else ...\r
+        return;\r
+    }\r
+\r
+    if ( m_pBmp.GetWidth() < 20 || m_pBmp.GetHeight() < 20 )\r
+    {\r
+        // ... complain: the bitmap it too small ...\r
+        return;\r
+    }\r
+\r
+    m_zoomFactor        = 1.0;\r
     m_clip              = false;\r
     m_use_bitmap        = true;\r
-    m_zoomFactor        = 1.0;\r
+    m_newdata           = false;\r
     m_rubberBand        = false;\r
     m_mouseDown         = false;\r
     m_penShortDash      = wxPen(wxColor(0xA0, 0xA0, 0xA0), 1, wxPENSTYLE_SHORT_DASH);\r
     m_penDotDash        = wxPen(wxColor(0xD0, 0xD0, 0xD0), 1, wxPENSTYLE_DOT_DASH);\r
+    m_penSolid          = wxPen(wxColor(0x00, 0x00, 0x00), 1, wxPENSTYLE_SOLID);\r
 //    m_gridLeftOffset    = 20;\r
 //    m_gridRightOffset   = 5;\r
 //    m_gridTopOffset     = 5;\r
@@ -42,6 +58,17 @@ PlotPanel::PlotPanel(wxFrame* parent) : wxPanel(parent)
     SetLabelSize(10.0);\r
 }\r
 \r
+//-------------------------------------------------------------------------\r
+// ~PlotPanel()\r
+//-------------------------------------------------------------------------\r
+PlotPanel::~PlotPanel()\r
+{\r
+    if(!m_bmp->IsNull())\r
+    {\r
+        delete m_bmp;\r
+    }
+}\r
+\r
 //-------------------------------------------------------------------------\r
 // GetLabelSize()\r
 //-------------------------------------------------------------------------\r
@@ -150,7 +177,7 @@ void PlotPanel::drawGraticule(wxAutoBufferedPaintDC&  dc)
 \r
     // Vertical gridlines\r
     dc.SetPen(m_penShortDash);\r
-    for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < m_w; p += GRID_INCREMENT)\r
+    for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < ((m_w - XLEFT_OFFSET) + GRID_INCREMENT); p += GRID_INCREMENT)\r
     {\r
         dc.DrawLine(p, (m_h + PLOT_BORDER), p, PLOT_BORDER);\r
     }\r
@@ -197,7 +224,6 @@ void PlotPanel::draw(wxAutoBufferedPaintDC&  dc)
     dc.SetBrush(ltBlueBrush);\r
     dc.SetPen(wxPen(BLACK_COLOR, 1));\r
     dc.DrawRectangle(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_w, m_h);\r
-\r
     drawGraticule(dc);\r
 }\r
 \r
index 48200bfcf2b9be5de1af990ce80e198584bdf763..c608689726242d80e40a4f58fd9a55985b081f31 100644 (file)
@@ -7,14 +7,19 @@
 // License:         BSD License (other licenses may apply to other\r
 //                  components of this project)\r
 //==========================================================================\r
+//#include "fdmdv2_main.h"\r
 #ifndef __FDMDV2_PLOT__
 #define __FDMDV2_PLOT__
-//#include "codec2.h"
-//#include "fdmdv.h"\r
+#include <wx/wx.h>\r
+#include <wx/aui/auibook.h>\r
 #include <wx/rawbmp.h>\r
 #include <wx/image.h>\r
 #include <wx/dcbuffer.h>\r
 \r
+#define MAX_ZOOM    7\r
+#define MAX_BMP_X   (400 * MAX_ZOOM)\r
+#define MAX_BMP_Y   (400 * MAX_ZOOM)\r
+\r
 #define wxUSE_FILEDLG       1\r
 #define wxUSE_LIBPNG        1\r
 #define wxUSE_LIBJPEG       1\r
@@ -24,7 +29,7 @@
 \r
 #define PLOT_BORDER         3\r
 #define XLEFT_OFFSET        30\r
-#define XLEFT_TEXT_OFFSET   7\r
+#define XLEFT_TEXT_OFFSET   8\r
 #define YBOTTOM_OFFSET      25\r
 #define GRID_INCREMENT      50\r
 #define GREY_COLOR          wxColor(0x80, 0x80, 0x80)\r
@@ -62,6 +67,8 @@
     wxWHITE_BRUSH\r
 */\r
 \r
+class MainFrame;\r
+\r
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
 // Class PlotPanel\r
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
@@ -69,56 +76,61 @@ class PlotPanel : public wxPanel
 {\r
     public:\r
         PlotPanel(wxFrame* parent);\r
-        void                paintEvent(wxPaintEvent & evt);\r
-        void                draw(wxAutoBufferedPaintDC& dc);\r
-        void                drawGraticule(wxAutoBufferedPaintDC& dc);\r
+        ~PlotPanel();\r
         wxPen               m_penShortDash;\r
         wxPen               m_penDotDash;\r
+        wxPen               m_penSolid;\r
         wxRect              m_rectCtrl;\r
         wxRect              m_rectGrid;\r
         wxRect              m_rectPlot;\r
-//        int                 m_gridLeftOffset;\r
-//        int                 m_gridRightOffset;\r
-//        int                 m_gridTopOffset;\r
-//        int                 m_gridBottomOffset;\r
+        MainFrame           *m_pTopFrame;\r
+        wxAuiNotebook       *m_pNoteBook;\r
         double              m_label_size;\r
         wxSize              m_Bufsz;\r
+        bool                m_newdata;\r
         wxBitmap            *m_bmp;\r
-        wxImagePixelData    *m_pBmp;\r
-        //wxNativePixelData     *m_pBmp;\r
-        //wxAlphaPixelData      *m_pBmp;\r
+        wxNativePixelData   *m_pBmp;\r
 \r
         // some useful events\r
-        void    OnMouseMove(wxMouseEvent& event);\r
-        void    OnMouseDown(wxMouseEvent& event);\r
-        void    OnMouseUp(wxMouseEvent& event);\r
-        void    OnMouseWheelMoved(wxMouseEvent& event);\r
-        void    OnClose(wxCloseEvent& event ){ event.Skip(); }
-        void    OnSize( wxSizeEvent& event );\r
-        void    OnErase(wxEraseEvent& event);\r
-        void    OnPaint(wxPaintEvent& event);\r
-
-        double  SetZoomFactor(double zf);\r
-        double  GetZoomFactor(double zf);\r
+        void            OnMouseMove(wxMouseEvent& event);\r
+        void            OnMouseDown(wxMouseEvent& event);\r
+        void            OnMouseUp(wxMouseEvent& event);\r
+        void            OnMouseWheelMoved(wxMouseEvent& event);\r
+        void            OnClose(wxCloseEvent& event ){ event.Skip(); }
+        void            OnSize( wxSizeEvent& event );\r
+        void            OnErase(wxEraseEvent& event);\r
+        void            OnPaint(wxPaintEvent& event);\r
         //void OnUpdateUI( wxUpdateUIEvent& event ){ event.Skip(); }\r
-        void    OnShow(wxShowEvent& event);\r
-        double  GetLabelSize();\r
-        void    SetLabelSize(double size);\r
+
+        void            paintEvent(wxPaintEvent & evt);\r
+        virtual void    draw(wxAutoBufferedPaintDC& dc);\r
+        virtual void    drawGraticule(wxAutoBufferedPaintDC& dc);\r
+        virtual double  SetZoomFactor(double zf);\r
+        virtual double  GetZoomFactor(double zf);\r
+        virtual void    OnShow(wxShowEvent& event);\r
+        virtual double  GetLabelSize();\r
+        virtual void    SetLabelSize(double size);\r
 
     protected:\r
-        int     m_x;
-        int     m_y;
-        int     m_w;
-        int     m_h;
-        int     m_prev_w;
-        int     m_prev_h;
-        int     m_prev_x;
-        int     m_prev_y;
-        bool    m_use_bitmap;\r
-        bool    m_clip;\r
-        bool    m_rubberBand;\r
-        bool    m_mouseDown;\r
-        double  m_zoomFactor;\r
+        int         m_x;
+        int         m_y;
+        int         m_w;
+        int         m_h;\r
+        int         m_left;\r
+        int         m_top;
+        int         m_prev_w;
+        int         m_prev_h;
+        int         m_prev_x;
+        int         m_prev_y;
+        bool        m_use_bitmap;\r
+        bool        m_clip;\r
+        bool        m_rubberBand;\r
+        bool        m_mouseDown;\r
+        double      m_zoomFactor;\r
+//        int             m_gridLeftOffset;\r
+//        int             m_gridRightOffset;\r
+//        int             m_gridTopOffset;\r
+//        int             m_gridBottomOffset;\r
     DECLARE_EVENT_TABLE()\r
 };\r
 #endif //__FDMDV2_PLOT__\r
index 3ccfb423d2c60dee9f5fce28a6b3816a490c12e4..4d238b5b89fef33c724b262b38eced255e9f66d1 100644 (file)
@@ -183,17 +183,6 @@ void PlotScalar::draw(wxAutoBufferedPaintDC&  dc)
     //fl_pop_clip();\r
 }
 \r
-// // update average of each spectrum point\r
-// void new_data(float mag_dB[])\r
-// {\r
-//     int i;\r
-//\r
-//     for(i=0; i<FDMDV_NSPEC; i++)
-//     {\r
-//         av_mag[i] = (1.0 - BETA)*av_mag[i] + BETA*mag_dB[i];
-//     }\r
-// }
-\r
 //----------------------------------------------------------------\r
 // OnPaint()\r
 //----------------------------------------------------------------\r
index b107623de01e668d04dbd7731d6da342c12937e2..fe630c34ba13ab95877617a7d564ae265458aba5 100644 (file)
@@ -58,16 +58,5 @@ class PlotScalar: public PlotPanel
         DECLARE_EVENT_TABLE()\r
 };\r
 \r
-//// update average of each spectrum point\r
-//void new_data(float mag_dB[])\r
-//{\r
-//    int i;\r
-//\r
-//    for(i=0; i<FDMDV_NSPEC; i++)\r
-//    {\r
-//        av_mag[i] = (1.0 - BETA)*av_mag[i] + BETA*mag_dB[i];\r
-//    }\r
-//}\r
-\r
 #endif // __FDMDV2_PLOT_SCALAR__
 \r
index fc5de6167aa3177128bbb8f01f56145d24228979..5931a96ce0a8ce2510e0133313947d31401d29f5 100644 (file)
@@ -47,6 +47,8 @@ PlotSpectrum::PlotSpectrum(wxFrame* parent): PlotPanel(parent)
     SetLabelSize(10.0);\r
 }\r
 \r
+#define TEXT_BASELINE_OFFSET_Y  -5\r
+\r
 //-------------------------------------------------------------------------\r
 // drawGraticule()\r
 //-------------------------------------------------------------------------\r
@@ -55,19 +57,37 @@ void PlotSpectrum::drawGraticule(wxAutoBufferedPaintDC&  dc)
     int p;\r
     char buf[15];\r
     wxString s;\r
+    //int h_mod_inc = 0;\r
 \r
     // Vertical gridlines\r
     dc.SetPen(m_penShortDash);\r
-    for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < m_w; p += GRID_INCREMENT)\r
+    for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < ((m_w - XLEFT_OFFSET) + GRID_INCREMENT); p += GRID_INCREMENT)\r
     {\r
         dc.DrawLine(p, (m_h + PLOT_BORDER), p, PLOT_BORDER);\r
     }\r
+\r
+    int y_zero = (m_h - m_top) / 2 ;\r
+    dc.SetPen(m_penSolid);\r
+    dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y_zero, (m_w + PLOT_BORDER + XLEFT_OFFSET), y_zero);\r
+    sprintf(buf, "%6.0f", 0.0);\r
+    dc.DrawText(buf, XLEFT_TEXT_OFFSET, y_zero + TEXT_BASELINE_OFFSET_Y);\r
+\r
     // Horizontal gridlines\r
     dc.SetPen(m_penDotDash);\r
-    for(p = (m_h - GRID_INCREMENT); p > PLOT_BORDER; p -= GRID_INCREMENT)\r
+    for(p = 0; (y_zero + p) < m_h ; p += GRID_INCREMENT)\r
     {\r
-        dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, (p + PLOT_BORDER), (m_w + PLOT_BORDER + XLEFT_OFFSET), (p + PLOT_BORDER));\r
+        if(p > 0)\r
+        {\r
+            dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, (y_zero + p), (m_w + PLOT_BORDER + XLEFT_OFFSET), (y_zero + p));\r
+            sprintf(buf, "%6.0f", (double)(p) * -10);\r
+            dc.DrawText(buf, XLEFT_TEXT_OFFSET, (y_zero + p + TEXT_BASELINE_OFFSET_Y));\r
+\r
+            dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, (y_zero - p), (m_w + PLOT_BORDER + XLEFT_OFFSET), (y_zero - p));\r
+            sprintf(buf, "%6.0f", (double)(p) * 10);\r
+            dc.DrawText(buf, XLEFT_TEXT_OFFSET, (y_zero - p + TEXT_BASELINE_OFFSET_Y));\r
+        }\r
     }\r
+\r
     // Label the X-Axis\r
     dc.SetPen(wxPen(GREY_COLOR, 1));\r
     for(p = GRID_INCREMENT; p < (m_w - YBOTTOM_OFFSET); p += GRID_INCREMENT)\r
@@ -75,19 +95,14 @@ void PlotSpectrum::drawGraticule(wxAutoBufferedPaintDC&  dc)
         sprintf(buf, "%1.1f Hz",(double)(p / 10));\r
         dc.DrawText(buf, p - PLOT_BORDER + XLEFT_OFFSET, m_h + YBOTTOM_OFFSET/2);\r
     }\r
-    // Label the Y-Axis\r
-    for(p = (m_h - GRID_INCREMENT); p > PLOT_BORDER; p -= GRID_INCREMENT)\r
-    {\r
-        sprintf(buf, "%1.0f", (double)((m_h - p) * -10));\r
-        dc.DrawText(buf, XLEFT_TEXT_OFFSET, p);\r
-    }\r
 }\r
 \r
 //----------------------------------------------------------------\r
 // draw()\r
 //----------------------------------------------------------------\r
 void PlotSpectrum::draw(wxAutoBufferedPaintDC&  dc)
-{
+{\r
+/*
     float x_px_per_point = 0.0;
     float y_px_per_dB = 0.0;
     int   i;
@@ -98,7 +113,7 @@ void PlotSpectrum::draw(wxAutoBufferedPaintDC&  dc)
     float mag1, mag2;
     char  label[20];
     float px_per_hz;\r
-\r
+*/\r
     m_rectCtrl  = GetClientRect();\r
     m_rectGrid  = m_rectCtrl;\r
 \r
@@ -114,10 +129,13 @@ void PlotSpectrum::draw(wxAutoBufferedPaintDC&  dc)
     dc.Clear();\r
 \r
     // Draw a filled rectangle with aborder\r
-    wxBrush ltBlueBrush = wxBrush(LIGHT_YELLOW_COLOR);\r
-    dc.SetBrush(ltBlueBrush);\r
-    dc.SetPen(wxPen(BLACK_COLOR, 1));\r
-    dc.DrawRectangle(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_w, m_h);\r
+    wxBrush ltYellowBrush = wxBrush(LIGHT_YELLOW_COLOR);\r
+    dc.SetBrush(ltYellowBrush);\r
+//    dc.SetBrush(BLACK_COLOR);\r
+//    dc.SetPen(wxPen(BLACK_COLOR, 1));\r
+    m_top = PLOT_BORDER;\r
+    m_left = PLOT_BORDER + XLEFT_OFFSET;\r
+    dc.DrawRectangle(m_left, m_top, m_w, m_h);\r
 \r
     drawGraticule(dc);\r
 /*
index 8454cbda4ace17bd82c1e2fc98068087fe133f8b..d799896b9b78445d03d3e810e34c15c948b1d6ee 100644 (file)
 //==========================================================================\r
 #include <string.h>\r
 #include "wx/wx.h"\r
+#include "fdmdv2_main.h"\r
 #include "fdmdv2_plot_waterfall.h"
 \r
-extern float *av_mag;\r
+//extern float *av_mag;\r
+\r
 /*\r
 \r
   Notes:\r
@@ -56,14 +58,16 @@ PlotWaterfall::PlotWaterfall(wxFrame* parent): PlotPanel(parent)
 {
     int   i;
 \r
-    m_bmp = new wxBitmap(MAX_BMP_X, MAX_BMP_Y, wxBITMAP_SCREEN_DEPTH);
+//    m_bmp = new wxBitmap(MAX_BMP_X, MAX_BMP_Y, wxBITMAP_SCREEN_DEPTH);
     for(i = 0; i < 255; i++)
     {
         m_heatmap_lut[i] = heatmap((float)i, 0.0, 255.0);
     }
     m_greyscale = 0;
     SetLabelSize(10.0);\r
-    m_Bufsz = GetMaxClientSize();
+    m_Bufsz = GetMaxClientSize();\r
+//    m_newdata = true;\r
+    m_newdata = false;\r
 };
 
 //----------------------------------------------------------------\r
@@ -71,10 +75,6 @@ PlotWaterfall::PlotWaterfall(wxFrame* parent): PlotPanel(parent)
 //----------------------------------------------------------------\r
 PlotWaterfall::~PlotWaterfall()
 {
-    if(!m_bmp->IsNull())\r
-    {\r
-        delete m_bmp;\r
-    }
 }
 \r
 /*\r
@@ -95,7 +95,7 @@ void PlotWaterfall::new_pixel_buf(int w, int h)
         delete m_bmp;\r
         //m_Bufsz = h * w;\r
 \r
-        //m_img = new wxImage(sz, pdata, alpha,false);\r
+        //m_img = new wxImage(sz, pdata, alpha, false);\r
         m_bmp = new wxBitmap(w, h, wxBITMAP_SCREEN_DEPTH);\r
         //m_pBmp = m_bmp->GetBitmapData();\r
     }
@@ -171,7 +171,7 @@ void PlotWaterfall::drawGraticule(wxAutoBufferedPaintDC&  dc)
 \r
     // Vertical gridlines\r
     dc.SetPen(m_penShortDash);\r
-    for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < m_w; p += GRID_INCREMENT)\r
+    for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < ((m_w - XLEFT_OFFSET) + GRID_INCREMENT); p += GRID_INCREMENT)\r
     {\r
         dc.DrawLine(p, (m_h + PLOT_BORDER), p, PLOT_BORDER);\r
     }\r
@@ -207,9 +207,6 @@ void PlotWaterfall::draw(wxAutoBufferedPaintDC&  dc)
     m_rectGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));\r
     m_rectGrid.Offset(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);\r
 \r
-//    m_rectGrid.Deflate(PLOT_BORDER, (PLOT_BORDER + (YBOTTOM_OFFSET/2)));\r
-//    m_rectGrid.Offset(PLOT_BORDER, PLOT_BORDER);\r
-\r
     m_h = m_rectGrid.GetHeight();\r
     m_w = m_rectGrid.GetWidth();\r
 \r
@@ -223,6 +220,11 @@ void PlotWaterfall::draw(wxAutoBufferedPaintDC&  dc)
 \r
     drawGraticule(dc);\r
     //plotData(dc);\r
+    if(m_newdata)\r
+    {\r
+        m_newdata = false;\r
+        plotPixelData(dc);\r
+    }\r
 }\r
 \r
 //----------------------------------------------------------------\r
@@ -244,6 +246,7 @@ void PlotWaterfall::plotData(wxAutoBufferedPaintDC&  dc)
     unsigned    *last_row;\r
     unsigned    *pdest;\r
     unsigned    *psrc;
+//    float       *av_mag = ((MainFrame *)GetParent())->m_av_mag;\r
     /* detect resizing of window */
 /*\r
     if ((m_h != m_prev_h) || (m_w != m_prev_w))
@@ -262,19 +265,21 @@ void PlotWaterfall::plotData(wxAutoBufferedPaintDC&  dc)
     bytes_in_row_of_blocks = dy * m_w * sizeof(unsigned);
     for(b = 0; b < dy_blocks - 1; b++)
     {
-        pdest = m_pixel_buf + b * m_w * dy;
-        psrc  = m_pixel_buf + (b + 1) * m_w * dy;
+        pdest = (unsigned int *)m_pBmp + b * m_w * dy;
+        psrc  = (unsigned int *)m_pBmp + (b + 1) * m_w * dy;
         memcpy(pdest, psrc, bytes_in_row_of_blocks);
     }
     // create a new row of blocks at bottom
     spec_index_per_px = (float)FDMDV_NSPEC / (float) m_w;
     intensity_per_dB = (float)256 /(MAX_DB - MIN_DB);
-    last_row = m_pixel_buf + dy *(dy_blocks - 1)* m_w;
+    last_row = (unsigned int *)m_pBmp + dy *(dy_blocks - 1)* m_w;
     for(px = 0; px < m_w; px++)
     {
         index = px * spec_index_per_px;
-        intensity = intensity_per_dB * (av_mag[index] - MIN_DB);
-        if (intensity > 255)
+        intensity = intensity_per_dB * (m_pTopFrame->m_rxPa->m_av_mag[index] - MIN_DB);
+        //intensity = intensity_per_dB * m_pTopFrame->m_rxPa->getAvMag(index) - MIN_DB);\r
+
+        if(intensity > 255)
         {
             intensity = 255;
         }
@@ -282,7 +287,7 @@ void PlotWaterfall::plotData(wxAutoBufferedPaintDC&  dc)
         {
             intensity = 0;
         }
-        if (m_greyscale)
+        if(m_greyscale)
         {
             for(py = 0; py < dy; py++)
             {
@@ -297,12 +302,112 @@ void PlotWaterfall::plotData(wxAutoBufferedPaintDC&  dc)
             }
         }
     }\r
-\r
     // update bit map
     //fl_draw_image((unsigned char*)m_pixel_buf, m_x, m_y, m_w, m_h, 4, 0);\r
-    //dc.DrawLines(4, m_pBmp, 0, 0 );
-}
+    //dc.DrawLines(4, m_pBmp, 0, 0 );\r
 
+}\r
+\r
+//-------------------------------------------------------------------------\r
+// plotPixelData()\r
+//-------------------------------------------------------------------------\r
+void PlotWaterfall::plotPixelData(wxAutoBufferedPaintDC&  dc)\r
+{\r
+    float       spec_index_per_px;\r
+    float       intensity_per_dB;
+    int         px_per_sec;
+    int         index;\r
+    int         dy;\r
+    int         dy_blocks;\r
+    int         bytes_in_row_of_blocks;\r
+    int         b;
+    int         px;\r
+    int         py;\r
+    int         intensity;
+    unsigned    *last_row;\r
+    unsigned    *pdest;\r
+    unsigned    *psrc;\r
+\r
+    // determine dy, the height of one "block"
+    px_per_sec = (float)m_h / WATERFALL_SECS_Y;
+    dy = DT * px_per_sec;
+    // number of dy high blocks in spectrogram
+    dy_blocks = m_h / dy;
+    // shift previous bit map
+    bytes_in_row_of_blocks = dy * m_w * sizeof(unsigned);
+    for(b = 0; b < dy_blocks - 1; b++)
+    {
+        pdest = (unsigned int *)m_pBmp + b * m_w * dy;
+        psrc  = (unsigned int *)m_pBmp + (b + 1) * m_w * dy;
+        memcpy(pdest, psrc, bytes_in_row_of_blocks);
+    }
+    // create a new row of blocks at bottom
+    spec_index_per_px = (float)FDMDV_NSPEC / (float) m_w;
+    intensity_per_dB  = (float)256 /(MAX_DB - MIN_DB);
+    last_row = (unsigned int *)m_pBmp + dy *(dy_blocks - 1)* m_w;
+\r
+    wxNativePixelData data(*m_bmp);\r
+    if(!data)\r
+    {\r
+        // ... raw access to bitmap data unavailable, do something else ...\r
+        return;\r
+    }\r
+    if(data.GetWidth() < 20 || data.GetHeight() < 20)\r
+    {\r
+        // ... complain: the bitmap it too small ...\r
+        return;\r
+    }\r
+    wxNativePixelData::Iterator p(data);\r
+    // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b\r
+    p.Offset(data, 10, 10);\r
+    for(px = 0; px < m_w; px++)
+    {
+        index = px * spec_index_per_px;
+        // intensity = intensity_per_dB * (m_av_mag[index] - MIN_DB);
+        intensity = intensity_per_dB * (((MainFrame *)GetParent())->m_rxPa->m_av_mag[index] - MIN_DB);
+        if(intensity > 255)
+        {
+            intensity = 255;
+        }
+        if(intensity > 255)
+        {
+            intensity = 255;
+        }
+        if (intensity < 0)
+        {
+            intensity = 0;
+        }
+        if(m_greyscale)
+        {
+            for(py = 0; py < dy; py++)
+            {
+                last_row[px + py * m_w] = intensity << 8;
+            }
+        }
+        else
+        {
+            for(py = 0; py < dy; py++)
+            {
+                last_row[px + py * m_w] = m_heatmap_lut[intensity];
+            }
+        }
+    }\r
+/*\r
+    for(int y = 0; y < 10; ++y)\r
+    {\r
+        wxNativePixelData::Iterator rowStart = p;\r
+        for(int x = 0; x < 10; ++x, ++p)\r
+        {\r
+            p.Red()     = r;\r
+            p.Green()   = g;\r
+            p.Blue()    = b;\r
+        }\r
+        p = rowStart;\r
+        p.OffsetY(data, 1);\r
+    }\r
+*/\r
+}\r
+\r
 //----------------------------------------------------------------\r
 // paintEvent()\r
 //\r
index be28fcde829b0d2a4b6c3ea68940bfd97ae32157..6337096c2136cb73139cfb4ece6b1c52c3e8b621 100644 (file)
 #include "fdmdv2_plot.h"\r
 #include "fdmdv2_defines.h"\r
 \r
-#define MAX_ZOOM    7\r
-#define MAX_BMP_X   (400 * MAX_ZOOM)\r
-#define MAX_BMP_Y   (400 * MAX_ZOOM)\r
-\r
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
 // Class PlotWaterfall\r
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
@@ -42,7 +38,7 @@ public:
     ~PlotWaterfall();\r
 
 protected:
-    unsigned    *m_pixel_buf;
+//    unsigned    *m_pixel_buf;
     unsigned    m_heatmap_lut[256];
     int         m_greyscale;
 \r
@@ -54,6 +50,7 @@ protected:
     void        drawGraticule(wxAutoBufferedPaintDC&  dc);\r
     void        draw(wxAutoBufferedPaintDC&  dc);\r
     void        plotData(wxAutoBufferedPaintDC&  dc);\r
+    void        plotPixelData(wxAutoBufferedPaintDC&  dc);\r
     DECLARE_EVENT_TABLE()\r
 };\r
 \r
diff --git a/fdmdv2/src/fdmdv2_process_audio.cpp b/fdmdv2/src/fdmdv2_process_audio.cpp
deleted file mode 100644 (file)
index f686644..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-//==========================================================================\r
-// Name:            fdmdv2_process_audio.cpp\r
-// Purpose:         Implements processing of data received from audio interfaces.\r
-// Created:         August 12, 2012
-// Initial author:  David Rowe\r
-// Derived from:    code trivially converted for integration with C++ code
-//                  by Dave Witten\r
-// License:\r
-//\r
-//  Copyright (C) 2012 David Witten
-//
-//  All rights reserved.
-//
-//  This program is free software; you can redistribute it and/or modify
-//  it under the terms of the GNU Lesser General Public License version 2.1,
-//  as published by the Free Software Foundation.  This program is
-//  distributed in the hope that it will be useful, but WITHOUT ANY
-//  WARRANTY; without even the implied warranty of MERCHANTABILITY or
-//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-//  License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public License
-//  along with this program; if not, see <http://www.gnu.org/licenses/>.
-//
-//==========================================================================\r
-/*
-
-  FUNCTION: per_frame_rx_processing()
-  AUTHOR..: David Rowe
-  DATE....: July 2012
-
-  Called every rx frame to take a buffer of input modem samples and
-  convert them to a buffer of output speech samples.
-
-  The sample source could be a sound card or file.  The sample source
-  supplies a fixed number of samples with each call.  However
-  fdmdv_demod requires a variable number of samples for each call.
-  This function will buffer as appropriate and call fdmdv_demod with
-  the correct number of samples.
-
-  The processing sequence is:
-
-  collect demod input samples from sound card 1 A/D
-  while we have enough samples:
-        demod samples into bits
-        decode bits into speech samples
-        output a buffer of speech samples to sound card 2 D/A
-
-  Note that sound card 1 and sound card 2 will have slightly different
-  sample rates, as their sample clocks are not syncronised.  We
-  effectively lock the system to the demod A/D (sound card 1) sample
-  rate. This ensures the demod gets a continuous sequence of samples,
-  maintaining sync. Sample underflow or overflow will instead occur on
-  the sound card 2 D/A.  This is acceptable as a buffer of lost or
-  extra speech samples is unlikely to be noticed.
-
-  The situation is actually a little more complex than that.  Through
-  the demod timing estimation the buffers supplied to sound card D/A 2
-  are effectively clocked at the remote modulator sound card D/A clock
-  rate.  We slip/gain buffers supplied to sound card 2 to compensate.
-
-  The current demod handles varying clock rates by having a variable
-  number of input samples, e.g. 120 160 (nominal) or 200.  However the
-  A/D always delivers a fixed number of samples.
-
-  So we currently need some logic between the A/D and the demod:
-        + A/D delivers fixed number of samples
-        + demod processes a variable number of samples
-        + this means we run demod 0,1 or 2 times, depending
-            on number of buffered A/D samples
-        + demod always outputs 1 frame of bits
-        + so run demod and speech decoder 0, 1 or 2 times
-
-  The ouput of the demod is codec voice data so it's OK if we miss or
-  repeat a frame every now and again.
-
-*/
-#include "fdmdv2_main.h"\r
-#include "portaudio.h"
-
-//#include "fdmdv.h"
-#include "codec2.h"
-
-//-- Globals: Eliminate!! --------------------------------
-//char         *fin_name = NULL;
-//char         *fout_name = NULL;
-//char         *sound_dev_name = NULL;
-//FILE         *fin = NULL;
-//FILE         *fout = NULL;
-struct FDMDV  *fdmdv_state;
-struct CODEC2 *codec2;
-//float         av_mag[FDMDV_NSPEC];                  // shared between a few classes
-extern float *av_mag;\r
-//--------------------------------------------------------
-
-void new_data(float *);
-float  Ts = 0.0;
-short  input_buf[2*FDMDV_NOM_SAMPLES_PER_FRAME];
-int    n_input_buf = 0;
-int    nin = FDMDV_NOM_SAMPLES_PER_FRAME;
-short  *output_buf;
-int    n_output_buf = 0;
-int    codec_bits[2*FDMDV_BITS_PER_FRAME];
-int    state = 0;
-
-// Portaudio states -----------------------------
-
-PaStream *stream = NULL;
-PaError err;
-
-typedef struct
-{
-    float               in48k[FDMDV_OS_TAPS + N48];
-    float               in8k[MEM8 + N8];
-} paCallBackData;
-
-//----------------------------------------------------------------
-// per_frame_rx_processing()
-//----------------------------------------------------------------
-void per_frame_rx_processing(
-                                short   output_buf[],  /* output buf of decoded speech samples          */
-                                int     *n_output_buf, /* how many samples currently in output_buf[]    */
-                                int     codec_bits[],  /* current frame of bits for decoder             */
-                                short   input_buf[],   /* input buf of modem samples input to demod     */
-                                int     *n_input_buf,  /* how many samples currently in input_buf[]     */
-                                int     *nin,          /* amount of samples demod needs for next call   */
-                                int     *state,        /* used to collect codec_bits[] halves           */
-                                struct  CODEC2 *c2     /* Codec 2 states                                */
-                            )
-{
-    struct FDMDV_STATS  stats;
-    int                 sync_bit;
-    float               rx_fdm[FDMDV_MAX_SAMPLES_PER_FRAME];
-    int                 rx_bits[FDMDV_BITS_PER_FRAME];
-    unsigned char       packed_bits[BYTES_PER_CODEC_FRAME];
-    float               rx_spec[FDMDV_NSPEC];
-    int                 i;\r
-    int                 nin_prev;\r
-    int                 bit;\r
-    int                 byte;
-    int                 next_state;
-
-    assert(*n_input_buf <= (2 * FDMDV_NOM_SAMPLES_PER_FRAME));
-
-    /*
-      This while loop will run the demod 0, 1 (nominal) or 2 times:
-
-      0: when tx sample clock runs faster than rx, occasionally we
-         will run out of samples
-
-      1: normal, run decoder once, every 2nd frame output a frame of
-         speech samples to D/A
-
-      2: when tx sample clock runs slower than rx, occasionally we will
-         have enough samples to run demod twice.
-
-      With a +/- 10 Hz sample clock difference at FS=8000Hz (+/- 1250
-      ppm), case 0 or 1 occured about once every 30 seconds.  This is
-      no problem for the decoded audio.
-    */
-    while(*n_input_buf >= *nin)
-    {
-        // demod per frame processing
-        for(i = 0; i < *nin; i++)
-        {
-            rx_fdm[i] = (float)input_buf[i]/FDMDV_SCALE;
-        }
-        nin_prev = *nin;
-        fdmdv_demod(fdmdv_state, rx_bits, &sync_bit, rx_fdm, nin);
-        *n_input_buf -= nin_prev;
-        assert(*n_input_buf >= 0);
-
-        // shift input buffer
-        for(i=0; i<*n_input_buf; i++)
-        {
-            input_buf[i] = input_buf[i+nin_prev];
-        }
-
-        // compute rx spectrum & get demod stats, and update GUI plot data
-        fdmdv_get_rx_spectrum(fdmdv_state, rx_spec, rx_fdm, nin_prev);
-        fdmdv_get_demod_stats(fdmdv_state, &stats);
-        new_data(rx_spec);
-//        aScatter->add_new_samples(stats.rx_symbols);
-//        aTimingEst->add_new_sample(stats.rx_timing);
-//        aFreqEst->add_new_sample(stats.foff);
-//        aSNR->add_new_sample(stats.snr_est);
-        /*
-           State machine to:
-
-           + Mute decoded audio when out of sync.  The demod is synced
-             when we are using the fine freq estimate and SNR is above
-             a thresh.
-
-           + Decode codec bits only if we have a 0,1 sync bit
-             sequence.  Collects two frames of demod bits to decode
-             one frame of codec bits.
-        */
-        next_state = *state;
-        switch(*state)
-        {
-            case 0:
-                // mute output audio when out of sync
-                if(*n_output_buf < 2 * codec2_samples_per_frame(c2) - N8)
-                {
-                    for(i=0; i<N8; i++)\r
-                    {
-                        output_buf[*n_output_buf + i] = 0;
-                    }
-                    *n_output_buf += N8;
-                }
-                assert(*n_output_buf <= (2 * codec2_samples_per_frame(c2)));
-                if((stats.fest_coarse_fine == 1) && (stats.snr_est > 3.0))
-                {
-                    next_state = 1;
-                }
-                break;
-
-            case 1:
-                if(sync_bit == 0)
-                {
-                    next_state = 2;
-                    // first half of frame of codec bits
-                    memcpy(codec_bits, rx_bits, FDMDV_BITS_PER_FRAME * sizeof(int));
-                }
-                else
-                {
-                    next_state = 1;
-                }
-                if(stats.fest_coarse_fine == 0)
-                {
-                    next_state = 0;
-                }
-                break;
-
-            case 2:
-                next_state = 1;
-                if(stats.fest_coarse_fine == 0)
-                {
-                    next_state = 0;
-                }
-                if(sync_bit == 1)
-                {
-                    // second half of frame of codec bits
-                    memcpy(&codec_bits[FDMDV_BITS_PER_FRAME], rx_bits, FDMDV_BITS_PER_FRAME*sizeof(int));
-                    // pack bits, MSB received first
-                    bit  = 7;
-                    byte = 0;
-                    memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
-                    for(i = 0; i < BITS_PER_CODEC_FRAME; i++)
-                    {
-                        packed_bits[byte] |= (codec_bits[i] << bit);
-                        bit--;
-                        if(bit < 0)
-                        {
-                            bit = 7;
-                            byte++;
-                        }
-                    }
-                    assert(byte == BYTES_PER_CODEC_FRAME);
-                    // add decoded speech to end of output buffer
-                    if(*n_output_buf <= codec2_samples_per_frame(c2))
-                    {
-                        codec2_decode(c2, &output_buf[*n_output_buf], packed_bits);
-                        *n_output_buf += codec2_samples_per_frame(c2);
-                    }
-                    assert(*n_output_buf <= (2 * codec2_samples_per_frame(c2)));
-                }
-                break;
-        }
-        *state = next_state;
-    }
-}
-
-//----------------------------------------------------------------
-// update average of each spectrum point
-//----------------------------------------------------------------
-void new_data(float mag_dB[])
-{
-    int i;
-
-    for(i = 0; i < FDMDV_NSPEC; i++)
-    {
-        av_mag[i] = (1.0 - BETA) * av_mag[i] + BETA * mag_dB[i];
-    }
-}
-
-//----------------------------------------------------------------
-// Redraw windows every DT seconds.
-//----------------------------------------------------------------
-void update_gui(int nin, float *Ts)
-{
-    *Ts += (float)nin/FS;
-    *Ts += (float)nin/FS;
-    if(*Ts >= DT)
-    {
-/*
-        *Ts -= DT;
-        if(!zoomSpectrumWindow->shown() && !zoomWaterfallWindow->shown())
-        {
-            aSpectrum->redraw();
-            aWaterfall->redraw();
-            aScatter->redraw();
-            aTimingEst->redraw();
-            aFreqEst->redraw();
-            aSNR->redraw();
-        }
-        if(zoomSpectrumWindow->shown())
-        {
-            aZoomedSpectrum->redraw();
-        }
-        if(zoomWaterfallWindow->shown())
-        {
-            aZoomedWaterfall->redraw();
-        }
-*/
-    }
-}
-
-//----------------------------------------------------------------
-//  idle() is the FLTK function that gets continusouly called when FLTK
-//  is not doing GUI work.  We use this function for providing file
-//  input to update the GUI when simulating real time operation.
-//----------------------------------------------------------------
-/*
-void idle(void*)
-{
-    int ret, i;
-    if(fin_name != NULL)
-    {
-        ret = fread(&input_buf[n_input_buf], sizeof(short), FDMDV_NOM_SAMPLES_PER_FRAME, fin);
-        n_input_buf += FDMDV_NOM_SAMPLES_PER_FRAME;
-        per_frame_rx_processing(output_buf, &n_output_buf, codec_bits, input_buf, &n_input_buf, &nin, &state, codec2);
-        if(fout_name != NULL)
-        {
-            if(n_output_buf >= N8)
-            {
-                ret = fwrite(output_buf, sizeof(short), N8, fout);
-                n_output_buf -= N8;
-                assert(n_output_buf >= 0);
-                // shift speech sample output buffer
-                for(i=0; i<n_output_buf; i++)
-                {
-                    output_buf[i] = output_buf[i+N8];
-                }
-            }
-        }
-    }
-    update_gui(nin, &Ts);
-    // simulate time delay from real world A/D input, and pause betwen
-    // screen updates
-    usleep(20000);
-}
-*/
-\r
-/*
-//----------------------------------------------------------------
-// This routine will be called by the PortAudio engine when audio
-//  is available.
-//----------------------------------------------------------------
-static int callback(\r
-                        const void *inputBuffer,\r
-                        void *outputBuffer,
-                        unsigned long framesPerBuffer,
-                        const PaStreamCallbackTimeInfo* timeInfo,
-                        PaStreamCallbackFlags statusFlags,
-                        void *userData\r
-                    )
-{
-    paCallBackData *cbData = (paCallBackData*)userData;
-    unsigned int    i;
-    short           *rptr = (short*)inputBuffer;
-    short           *wptr = (short*)outputBuffer;
-    float           *in8k = cbData->in8k;
-    float           *in48k = cbData->in48k;
-    float           out8k[N8];
-    float           out48k[N48];
-    short           out48k_short[N48];
-
-    (void) timeInfo;
-    (void) statusFlags;
-
-    assert(inputBuffer != NULL);
-    // Convert input model samples from 48 to 8 kHz
-    // just use left channel
-    for(i = 0; i < framesPerBuffer; i++, rptr += 2)
-    {
-        in48k[i + FDMDV_OS_TAPS] = *rptr;
-    }
-    // downsample and update filter memory
-    fdmdv_48_to_8(out8k, &in48k[FDMDV_OS_TAPS], N8);
-    for(i = 0; i < FDMDV_OS_TAPS; i++)
-    {
-        in48k[i] = in48k[i+framesPerBuffer];
-    }
-    // run demod, decoder and update GUI info
-    for(i=0; i<N8; i++)
-    {
-        input_buf[n_input_buf + i] = (short)out8k[i];
-    }
-    n_input_buf += FDMDV_NOM_SAMPLES_PER_FRAME;
-    per_frame_rx_processing(output_buf, &n_output_buf, codec_bits, input_buf, &n_input_buf, &nin, &state, codec2);
-
-    // if demod out of sync copy input audio from A/D to aid in tuning
-    if(n_output_buf >= N8)
-    {
-        if(state == 0)
-        {
-            for(i=0; i<N8; i++)
-            {
-                in8k[MEM8 + i] = out8k[i];       // A/D signal
-            }
-        }
-        else
-        {
-            for(i=0; i < N8; i++)
-            {
-                in8k[MEM8+i] = output_buf[i];   // decoded speech
-            }
-        }
-        n_output_buf -= N8;
-    }
-    assert(n_output_buf >= 0);
-    // shift speech samples in output buffer
-    for(i = 0; i < (unsigned int)n_output_buf; i++)
-    {
-        output_buf[i] = output_buf[i+N8];
-    }
-    // Convert output speech to 48 kHz sample rate
-    // upsample and update filter memory
-    fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
-    for(i = 0; i < MEM8; i++)
-    {
-        in8k[i] = in8k[i+N8];
-    }
-    assert(outputBuffer != NULL);
-    // write signal to both channels
-    for(i = 0; i < N48; i++)
-    {
-        out48k_short[i] = (short)out48k[i];
-    }
-    for(i=0; i<framesPerBuffer; i++, wptr+=2)
-    {
-        wptr[0] = out48k_short[i];
-        wptr[1] = out48k_short[i];
-    }
-    return paContinue;
-}\r
-*/
-/*
-//----------------------------------------------------------------
-// arg_callback()
-//----------------------------------------------------------------
-int arg_callback(int argc, char **argv, int &i)
-{
-    if(argv[i][1] == 'i')
-    {
-        if((i+1) >= argc)
-        {
-            return 0;
-        }
-        fin_name = argv[i+1];
-        i += 2;
-        return 2;
-    }
-    if(argv[i][1] == 'o')
-    {
-        if((i+1) >= argc)
-        {
-            return 0;
-        }
-        fout_name = argv[i+1];
-        i += 2;
-        return 2;
-    }
-    if(argv[i][1] == 's')
-    {
-        if((i+1) >= argc)
-        {
-            return 0;
-        }
-        sound_dev_name = argv[i+1];
-        i += 2;
-        return 2;
-    }
-    return 0;
-}
-*/\r