first pass at real time update of MicIn spectrum in response to slider
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 1 Dec 2012 04:06:23 +0000 (04:06 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 1 Dec 2012 04:06:23 +0000 (04:06 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1102 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/README.linux
fdmdv2/src/Makefile.linux
fdmdv2/src/dlg_filter.cpp
fdmdv2/src/dlg_filter.h
fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_plot_spectrum.cpp
fdmdv2/src/fdmdv2_plot_spectrum.h
fdmdv2/src/sox_biquad.c
fdmdv2/src/sox_biquad.h

index 4233bc92941f40572c2e827cbde2910f00efbf32..90a6fa6624bdd8ae2bf6a162a3df0f56de1afa73 100644 (file)
@@ -73,6 +73,24 @@ Build portaudio
    possible to build fdmdv2 without "make install", by passing
    --prefix to the ./configure stage.
 
+<<<<<<< .mine
+Build libsox
+------------
+
+We use some of the internal sox functions for the equaliser feature.
+
+wget http://sourceforge.net/projects/sox/files/sox/14.4.0/sox-14.4.0.tar.gz/download
+tar xvzf sox-14.4.0.tar.gz
+cd sox-14.4.0
+
+Now we only want to use a few internal functions of sox.  This
+configure line mkes sure we don't build in unneeded depednancies:
+
+sox-14.4.0$ ./configure --enable-shared=no --without-id3tag --without-png --disable-gomp --with-oggvorbis=no --with-oss=no --with-flac=no --disable-dl-sndfile
+
+sox-14.4.0$ make
+
+=======
 Build libctb (Communications Toolbox)
 -------------------------------------
 
@@ -87,6 +105,7 @@ I found the "sudo make DEBUG=0 GPIB=0 install" didn't install the kbhit.h file:
 build$ sudo cp ../include/ctb-0.16/kbhit.h /usr/local/include/ctb-0.16
 build$ sudo ldconfig
 
+>>>>>>> .r1094
 Build codec2-dev
 ----------------
 
@@ -125,34 +144,44 @@ TODO
     [X] remove anything that doesn't work (menus, buttons) from GUI
     [X] about
     [X] src file credits
-    [ ] decide on web site
+    [X] decide on web site
         + need edit by at least three of us
-    [ ] help about with URL (hyperlink?) to web site
-    [ ] if you press start and headphones unplugged (ie one sound card missing), it
+    [X] if you press start and headphones unplugged (ie one sound card missing), it
         shouldn't crash
-    [ ] do we keep/put effort into getting working ./configure && Makefile?
+    [X] hook up squelch
+    [X] version number on GUI?  How to connect SVN verev to version?
+    [X] click tune and split
+    [X] rm loopback buttons
+
+    [ ] bug in record file on Win32
+    [ ] svn version tag?
+        + i.e. 1.0 etc rather than number
+    [ ] waterfall
+        + is graticule useful
+        + peaks showing
+        + showing fades properly
+    [ ] record/play dialogs layout
     [ ] remove/comment out debug printfs
-    [ ] hook up squelch
-    [ ] test with simulated AWGN/burst error channels
+    [ ] Credits: Mel, Tapr, Bruce,  Peter M, cesco, Dave W
+    [ ] rig control
+    [ ] data feature
+    [ ] always on top option
+    [ ] linux version
+
+    [ ] help about with URL (hyperlink?) to web site
+    [ ] do we keep/put effort into getting working ./configure && Makefile?
+    [-] test with simulated AWGN/burst error channels
         + see if sync needs tuning to not fall over too quickly
         + nasty noises
-    [ ] version number on GUI?  How to connect SVN verev to version?
     [ ] buffer sizes, maybe make a config number
     [ ] read comments and make sure they are still valid
-    [ ] rig control
-    [ ] click tune and split
     [ ] tool tip help for audio config dialog
-    [ ] rm loopback buttons
     [ ] something sensible with disabling rx when tx button is pressed?        
     [ ] wire up level guage
         + I think it has relevance for analog speech, demod can handle wide input ranges
-    [ ] data feature
-        + 11 or 00 sync with good inst snr
-        + way to measure inst snr
-        + drag text to "hopper".  Set thresh for sending (time or mic level)
     [ ] tx/rx muting for half duplex
         + dont want funny sounds during tx
-    [ ] setup Readme
+    [ ] setup doc
     [ ] Donate button with hyperlink from about dialog or help menu?
 
 IDEAS
@@ -206,3 +235,5 @@ What a good scatter diagram/spectrum looks like
 Setting up in audio loopback
 
 Explain one and two soundcard modes
+
+Right click drag tabs, new window, tab order
index e9c7c3a8a41ebea1cfc9065d64efdaa3c4509117..f04e1748455449e52361d0f4490288a9b093723f 100644 (file)
@@ -7,6 +7,7 @@
 
 WX_GTK_PATH=/home/david/Desktop/wxWidgets-2.9.4/build_gtk
 CODEC2_PATH=/home/david/codec2-dev
+SOX_LIB_PATH=/home/david/tmp/sox-14.4.0/src/.libs
 
 WX_CONFIG=$(WX_GTK_PATH)/wx-config
 WX_CPPFLAGS = $(shell $(WX_CONFIG) --cxxflags)
@@ -14,9 +15,10 @@ WX_LIBS = $(shell $(WX_CONFIG) --libs core, base, aui, adv, net)
 SVN_REVISION=$(shell svnversion)
 CODEC2_INC=-I$(CODEC2_PATH)/src
 CODEC2_LIB=$(CODEC2_PATH)/src/.libs/libcodec2.a
+SOX_LIB=$(SOX_LIB_PATH)/libsox.a
 
 CPP_FLAGS = $(WX_CPPFLAGS) $(CODEC2_INC) -I. -g -Wall -O3 -DSVN_REVISION=\"$(SVN_REVISION)\"
-LIBS = $(WX_LIBS) $(CODEC2_LIB) -lm -lportaudiocpp -lpthread -lsndfile /usr/lib/libsamplerate.so.0 -lctb-0.16
+LIBS = $(WX_LIBS) $(CODEC2_LIB) -lm -lportaudiocpp -lpthread -lsndfile /usr/lib/libsamplerate.so.0 -lctb-0.16 $(SOX_LIB)
 
 OBJS = topFrame.o \
 fdmdv2_main.o \
@@ -29,7 +31,9 @@ fdmdv2_pa_wrapper.o \
 dlg_audiooptions.o \
 dlg_comports.o \
 dlg_filter.o \
-varicode.o
+varicode.o \
+sox_biquad.o
+
 
 HDRS = dlg_audiooptions.h dlg_comports.h dlg_filter.h fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h varicode.h
 
index d92590606daab0c9de37e8bcf019b6a02652999d..088fecf6f40ed0a09d83bd31ed325057a8888773 100644 (file)
@@ -19,6 +19,7 @@
 //
 //==========================================================================
 #include "dlg_filter.h"
+#include "sox_biquad.h"
 
 #define SLIDER_MAX 100
 #define SLIDER_LENGTH 155
 #define MAX_FREQ_BASS      600.00
 #define MAX_FREQ_DEF      3000.00
 
+#define IMP_AMP           2000.0
+#define F_STEP_DFT        50.0
+#define F_MAG_N           (int)(MAX_F_HZ/F_STEP_DFT)
+
 extern struct CODEC2      *g_pCodec2;
 
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
@@ -89,10 +94,16 @@ FilterDlg::FilterDlg(wxWindow* parent, bool running, wxWindowID id, const wxStri
 
     bSizer30->Add(m_auiNotebook, 0, wxEXPAND|wxALL, 3);
     
-    m_MicInFreqRespPlot = new PlotSpectrum((wxFrame*) m_auiNotebook, FILTER_MIN_MAG_DB, FILTER_MAX_MAG_DB);
+    m_MicInMagdB = new float[F_MAG_N];
+    for(int i=0; i<F_MAG_N; i++)
+        m_MicInMagdB[i] = 0.0;
+    m_MicInFreqRespPlot = new PlotSpectrum((wxFrame*) m_auiNotebook, m_MicInMagdB, F_MAG_N, FILTER_MIN_MAG_DB, FILTER_MAX_MAG_DB);
     m_auiNotebook->AddPage(m_MicInFreqRespPlot, _("Microphone In Equaliser"));
 
-    m_SpkOutFreqRespPlot = new PlotSpectrum((wxFrame*)m_auiNotebook, FILTER_MIN_MAG_DB, FILTER_MAX_MAG_DB);
+    m_SpkOutMagdB = new float[F_MAG_N];
+    for(int i=0; i<F_MAG_N; i++)
+        m_SpkOutMagdB[i] = 0.0;
+    m_SpkOutFreqRespPlot = new PlotSpectrum((wxFrame*)m_auiNotebook, m_SpkOutMagdB, F_MAG_N, FILTER_MIN_MAG_DB, FILTER_MAX_MAG_DB);
     m_auiNotebook->AddPage(m_SpkOutFreqRespPlot, _("Speaker Out Equaliser"));
 
     // OK - Cancel - Default Buttons at the bottom --------------------------
@@ -126,6 +137,8 @@ FilterDlg::FilterDlg(wxWindow* parent, bool running, wxWindowID id, const wxStri
     m_sdbSizer5Cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnCancel), NULL, this);
     m_sdbSizer5Default->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnDefault), NULL, this);
     m_sdbSizer5OK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnOK), NULL, this);
+
+    sox_biquad_start();
 }
 
 //-------------------------------------------------------------------------
@@ -133,6 +146,10 @@ FilterDlg::FilterDlg(wxWindow* parent, bool running, wxWindowID id, const wxStri
 //-------------------------------------------------------------------------
 FilterDlg::~FilterDlg()
 {
+    delete m_MicInMagdB;
+    delete m_SpkOutMagdB;
+    sox_biquad_finish();
+
     // Disconnect Events
 
     this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(FilterDlg::OnInitDialog));
@@ -216,6 +233,10 @@ void FilterDlg::ExchangeData(int inout)
         // Mic In Equaliser
 
         m_MicInBass.freqHz = wxGetApp().m_MicInBassFreqHz; setFreq(&m_MicInBass);
+
+        m_MicInFreqRespPlot->m_newdata = true;
+        m_MicInFreqRespPlot->Refresh();
+        calcFilterSpectrum(&m_MicInBass, m_MicInMagdB);
     }
     if(inout == EXCHANGE_DATA_OUT)
     {
@@ -258,6 +279,9 @@ void FilterDlg::OnDefault(wxCommandEvent& event)
     m_gamma = CODEC2_LPC_PF_GAMMA; setGamma();
     m_codec2LPCPostFilterEnable->SetValue(true);
     m_codec2LPCPostFilterBassBoost->SetValue(true);
+
+    m_MicInBass.freqHz = 1.0;
+
 }
 
 //-------------------------------------------------------------------------
@@ -343,10 +367,67 @@ void FilterDlg::setFreq(EQ *eq)
     eq->sliderFreq->SetValue(slider);
 }
 
-void FilterDlg::OnMicInBassFreqScroll(wxScrollEvent& event)
+void FilterDlg::sliderToFreq(EQ *eq)
 {
-    m_MicInBass.freqHz = ((float)m_MicInBass.sliderFreq->GetValue()/SLIDER_MAX)*m_MicInBass.maxFreqHz;
-    printf("FilterDlg::OnMicInBassFreqScroll m_MicInBass.freqHz: %f\n", m_MicInBass.freqHz);
+    eq->freqHz = ((float)eq->sliderFreq->GetValue()/SLIDER_MAX)*eq->maxFreqHz;
+    if (eq->freqHz < 1.0) eq->freqHz = 1.0; // sox deosn't like 0 Hz;
     setFreq(&m_MicInBass);
+    calcFilterSpectrum(eq, m_MicInMagdB);
+    m_MicInFreqRespPlot->m_newdata = true;
+    m_MicInFreqRespPlot->Refresh();
 }
 
+void FilterDlg::OnMicInBassFreqScroll(wxScrollEvent& event)
+{
+    sliderToFreq(&m_MicInBass);
+}
+
+#define NIMP 50
+
+void FilterDlg::calcFilterSpectrum(EQ *eq, float magdB[]) {
+    void       *sbq;
+    const char *argv[10];
+    char        highpass[80];
+    char        freq[80];
+    short       in[NIMP];
+    short       out[NIMP];
+    COMP        X[(int)(MAX_F_HZ/F_STEP_DFT)];
+    float       f,w;
+    int         i, k, argc;
+
+    // find impulse response -----------------------------------
+
+    for(i=0; i<NIMP; i++)
+        in[i] = 0;
+    in[0] = IMP_AMP;
+
+    sprintf(highpass, "highpass"); argv[0] = highpass;
+    sprintf(freq, "%f", eq->freqHz); argv[1] = freq;
+    argc=1;
+    //printf("argv[0]: %s argv[1]: %s\n", argv[0], argv[1]);
+    sbq = sox_biquad_create(argc, argv);
+
+    sox_biquad_filter(sbq, out, in, NIMP);
+    //for(i=0; i<NIMP; i++)
+    //    printf("%d\n", out[i]);
+   
+    sox_biquad_destroy(sbq);
+
+    //for(i=0; i<NIMP; i++)
+    //    out[i] = 0.0;
+    //out[0] = IMP_AMP;
+
+    // calculate discrete time continous frequency Fourer transform
+    // doing this from basic principles rather than FFT for no good reason
+
+    for(f=0,i=0; f<MAX_F_HZ; f+=F_STEP_DFT,i++) {
+        w = M_PI*f/MAX_F_HZ;
+        X[i].real = 0.0; X[i].imag = 0.0;
+        for(k=0; k<NIMP; k++) {
+            X[i].real += ((float)out[k]/IMP_AMP) * cos(w*k);
+            X[i].imag -= ((float)out[k]/IMP_AMP) * sin(w*k);
+        }
+        magdB[i] = 10.0*log10(X[i].real* X[i].real + X[i].imag*X[i].imag + 1E-12);
+        //printf("f: %f X[%d] = %f %f magdB = %f\n", f, i, X[i].real, X[i].imag,  magdB[i]);
+    }
+}
index 384031e898524790ad24c25cc654278d1fd66224..bb61279f47dad935dcffa83f136076097aad8a9d 100644 (file)
@@ -91,6 +91,9 @@ class FilterDlg : public wxDialog
         wxButton*     m_sdbSizer5Cancel;
         PlotSpectrum* m_MicInFreqRespPlot;
         PlotSpectrum* m_SpkOutFreqRespPlot;
+    
+        float        *m_MicInMagdB;
+        float        *m_SpkOutMagdB;
 
      private:
         bool          m_running;
@@ -105,6 +108,8 @@ class FilterDlg : public wxDialog
         void          newLPCPFControl(wxSlider **slider, wxStaticText **stValue, wxSizer *sbs, wxString controlName);
         wxAuiNotebook *m_auiNotebook;
         void          setFreq(EQ *eq);
+        void          sliderToFreq(EQ *eq);
+        void          calcFilterSpectrum(EQ *eq, float magdB[]);
 
         EQ            m_MicInBass;
         EQ            m_MicInMid;
index c5ddaa040b20e67c9041f46b6b9dc045d2112459..9dd3b3b5cf5f7dff6f3dedf8dadfb8a62a4ce719 100644 (file)
@@ -236,7 +236,8 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     if(wxGetApp().m_show_spect)
     {
         // Add Spectrum Plot window
-        m_panelSpectrum = new PlotSpectrum((wxFrame*) m_auiNbookCtrl);
+        m_panelSpectrum = new PlotSpectrum((wxFrame*) m_auiNbookCtrl, g_avmag, 
+                                           FDMDV_NSPEC*((float)MAX_F_HZ/FDMDV_MAX_F_HZ));
         m_panelSpectrum->SetToolTip(_("Left click to tune"));
         m_auiNbookCtrl->AddPage(m_panelSpectrum, _("Spectrum"), true, wxNullBitmap);
     }
@@ -329,7 +330,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     wxGetApp().m_codec2LPCPostFilterBeta       = (float)pConfig->Read(wxT("/Filter/codec2LPCPostFilterBeta"),      CODEC2_LPC_PF_BETA*100)/100.0;
     //printf("main(): m_codec2LPCPostFilterBeta: %f\n", wxGetApp().m_codec2LPCPostFilterBeta);
 
-    wxGetApp().m_MicInBassFreqHz = pConfig->Read(wxT("/Filter/MicInBassFreqHz"),    0.0);
+    wxGetApp().m_MicInBassFreqHz = pConfig->Read(wxT("/Filter/MicInBassFreqHz"),    1.0);
 
     wxGetApp().m_callSign = pConfig->Read("/Data/CallSign", wxT(""));
 
index 705cded44730a3059fcc8ffc0eb897256acd3511..2ea8a7cef87ca2c1b8042aee08395d2328aa7423 100644 (file)
@@ -45,7 +45,7 @@ END_EVENT_TABLE()
 // @brief
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
-PlotSpectrum::PlotSpectrum(wxFrame* parent, float min_mag_db, float max_mag_db): PlotPanel(parent)
+PlotSpectrum::PlotSpectrum(wxFrame* parent, float *magdB, int n_magdB, float min_mag_db, float max_mag_db): PlotPanel(parent)
 {
     m_greyscale     = 0;
     m_Bufsz         = GetMaxClientSize();
@@ -53,6 +53,9 @@ PlotSpectrum::PlotSpectrum(wxFrame* parent, float min_mag_db, float max_mag_db):
     m_firstPass     = true;
     m_line_color    = 0;
     SetLabelSize(10.0);
+
+    m_magdB         = magdB;
+    m_n_magdB       = n_magdB;     // number of points in magdB that covers 0 ... MAX_F_HZ of spectrum
     m_max_mag_db    = max_mag_db;
     m_min_mag_db    = min_mag_db;
     m_rxFreq        = 0.0;
@@ -126,7 +129,8 @@ void PlotSpectrum::draw(wxAutoBufferedPaintDC& dc)
         pen.SetWidth(1);
         dc.SetPen(pen);
 
-        index_to_px = ((float)FDMDV_MAX_F_HZ/(float)MAX_F_HZ)*(float)m_rGrid.GetWidth()/FDMDV_NSPEC;
+        //index_to_px = ((float)FDMDV_MAX_F_HZ/(float)MAX_F_HZ)*(float)m_rGrid.GetWidth()/FDMDV_NSPEC;
+        index_to_px = (float)m_rGrid.GetWidth()/m_n_magdB;
        mag_dB_to_py = (float)m_rGrid.GetHeight()/(m_max_mag_db - m_min_mag_db);
         int last_index = ((float)MAX_F_HZ/(float)FDMDV_MAX_F_HZ)*FDMDV_NSPEC;
 
@@ -135,7 +139,7 @@ void PlotSpectrum::draw(wxAutoBufferedPaintDC& dc)
         for(index = 0; index < last_index; index++)
         {
             x = index*index_to_px;
-           mag = g_avmag[index];
+           mag = m_magdB[index];
            if (mag > m_max_mag_db) mag = m_max_mag_db;
            if (mag < m_min_mag_db) mag = m_min_mag_db;
            y = -(mag - m_max_mag_db) * mag_dB_to_py;
index 1a53fd4c7b101234c290b41b7d3ec70c2864e7c7..94a04ce015c5881e2dd603b1ed722035d1d9d709 100644 (file)
@@ -30,7 +30,7 @@
 class PlotSpectrum : public PlotPanel
 {
     public:
-    PlotSpectrum(wxFrame* parent, float min_mag_db=MIN_MAG_DB, float max_mag_db=MAX_MAG_DB);
+    PlotSpectrum(wxFrame* parent, float *magdB, int n_magdB, float min_mag_db=MIN_MAG_DB, float max_mag_db=MAX_MAG_DB);
         ~PlotSpectrum();
         void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; }
 
@@ -46,6 +46,8 @@ class PlotSpectrum : public PlotPanel
         float       m_rxFreq;
         float       m_max_mag_db;
         float       m_min_mag_db;
+        float      *m_magdB;
+        int         m_n_magdB;   
 
         DECLARE_EVENT_TABLE()
 };
index 0a3ff857753574e9dcb02179a33fd8d209a8f1aa..5687d8f8185519e928bfe18e6ca49dbcc263313c 100644 (file)
@@ -55,14 +55,14 @@ void sox_biquad_finish(void)
   argv[0] = "highpass"; argv[1]="1000"; argc=1;
 */
 
-void *sox_biquad_create(int argc, char *argv[])
+void *sox_biquad_create(int argc, const char *argv[])
 {
     int ret;
     sox_effect_t *e;
     int (*start)(sox_effect_t *); /* function pointer to effect start func */
     
     e = sox_create_effect(sox_find_effect(argv[0])); assert(e != NULL);
-    assert(sox_effect_options(e, argc, &argv[1]) == SOX_SUCCESS);
+    assert(sox_effect_options(e, argc, (char * const*)&argv[1]) == SOX_SUCCESS);
 
     start = e->handler.start;
     e->in_signal.rate = 8000;     /* locked at FS=8000 Hz */
index 5ec70bed20a36ab1011bc7ad0a09e723c3b44a23..f38de642f841da0419e5b5b06262bd58590cb1de 100644 (file)
@@ -29,7 +29,7 @@ extern "C" {
 
 void sox_biquad_start(void);
 void sox_biquad_finish(void);
-void *sox_biquad_create(int argc, char *argv[]);
+void *sox_biquad_create(int argc, const char *argv[]);
 void sox_biquad_destroy(void *sbq);
 void sox_biquad_filter(void *sbq, short out[], short in[], int n);