real time EQ adjustment working, designing filters on the fly, but still a few GUI...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 3 Dec 2012 01:41:38 +0000 (01:41 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 3 Dec 2012 01:41:38 +0000 (01:41 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1112 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/dlg_filter.cpp
fdmdv2/src/dlg_filter.h
fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_main.h

index e0874527febbba6b6e548166c0f3875ba19dd98a..96528e763852e01c92f7ff1dfd94139de8f45fb9 100644 (file)
@@ -19,7 +19,6 @@
 //
 //==========================================================================
 #include "dlg_filter.h"
-#include "sox_biquad.h"
 
 #define SLIDER_MAX 100
 #define SLIDER_LENGTH 155
@@ -49,9 +48,12 @@ extern struct CODEC2      *g_pCodec2;
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 // Class FilterDlg
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
-FilterDlg::FilterDlg(wxWindow* parent, bool running, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
+FilterDlg::FilterDlg(wxWindow* parent, bool running, bool *newMicInFilter, bool *newSpkOutFilter,
+                     wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
 {
     m_running = running;
+    m_newMicInFilter = newMicInFilter;
+    m_newSpkOutFilter = newSpkOutFilter;
 
     this->SetSizeHints(wxDefaultSize, wxDefaultSize);
 
@@ -206,7 +208,6 @@ FilterDlg::FilterDlg(wxWindow* parent, bool running, wxWindowID id, const wxStri
     m_sdbSizer5Cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnCancel), NULL, this);
     m_sdbSizer5OK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FilterDlg::OnOK), NULL, this);
 
-    sox_biquad_start();
 }
 
 //-------------------------------------------------------------------------
@@ -216,7 +217,6 @@ FilterDlg::~FilterDlg()
 {
     delete m_MicInMagdB;
     delete m_SpkOutMagdB;
-    sox_biquad_finish();
 
     // Disconnect Events
 
@@ -304,7 +304,7 @@ EQ FilterDlg::newEQ(wxSizer *bs, wxString eqName, float maxFreqHz, bool enableQ)
 //-------------------------------------------------------------------------
 // ExchangeData()
 //-------------------------------------------------------------------------
-void FilterDlg::ExchangeData(int inout)
+void FilterDlg::ExchangeData(int inout, bool storePersistent)
 {
     wxConfigBase *pConfig = wxConfigBase::Get();
     if(inout == EXCHANGE_DATA_IN)
@@ -335,7 +335,7 @@ void FilterDlg::ExchangeData(int inout)
         m_MicInMid.Q = wxGetApp().m_MicInMidQ; setQ(&m_MicInMid);
         m_MicInMid.Q = limit(m_MicInMid.Q, pow(10.0,MIN_LOG10_Q), pow(10.0, MAX_LOG10_Q));
 
-        m_MicInEnable->SetValue(wxGetApp().m_MicInEnable);
+        m_MicInEnable->SetValue(wxGetApp().m_MicInEQEnable);
 
         setFreq(&m_MicInBass); setGain(&m_MicInBass); plotMicInFilterSpectrum();
  
@@ -358,7 +358,7 @@ void FilterDlg::ExchangeData(int inout)
         m_SpkOutMid.Q = wxGetApp().m_SpkOutMidQ; setQ(&m_SpkOutMid);
         m_SpkOutMid.Q = limit(m_SpkOutMid.Q, pow(10.0,MIN_LOG10_Q), pow(10.0, MAX_LOG10_Q));
 
-        m_SpkOutEnable->SetValue(wxGetApp().m_SpkOutEnable);
+        m_SpkOutEnable->SetValue(wxGetApp().m_SpkOutEQEnable);
 
         setFreq(&m_SpkOutBass); setGain(&m_SpkOutBass); plotSpkOutFilterSpectrum();
     }
@@ -371,50 +371,54 @@ void FilterDlg::ExchangeData(int inout)
         wxGetApp().m_codec2LPCPostFilterBeta       = m_beta;
         wxGetApp().m_codec2LPCPostFilterGamma      = m_gamma;
 
-        pConfig->Write(wxT("/Filter/codec2LPCPostFilterEnable"),     wxGetApp().m_codec2LPCPostFilterEnable);
-        pConfig->Write(wxT("/Filter/codec2LPCPostFilterBassBoost"),  wxGetApp().m_codec2LPCPostFilterBassBoost);
-        pConfig->Write(wxT("/Filter/codec2LPCPostFilterBeta"),       (int)(m_beta*100.0));
-        pConfig->Write(wxT("/Filter/codec2LPCPostFilterGamma"),      (int)(m_gamma*100.0));
-
         // Mic In Equaliser
 
         wxGetApp().m_MicInBassFreqHz = m_MicInBass.freqHz;
-        pConfig->Write(wxT("/Filter/MicInBassFreqHz"), (int)m_MicInBass.freqHz);
         wxGetApp().m_MicInBassGaindB = m_MicInBass.gaindB;
-        pConfig->Write(wxT("/Filter/MicInBassGaindB"), (int)(10.0*m_MicInBass.gaindB));
 
         wxGetApp().m_MicInTrebleFreqHz = m_MicInTreble.freqHz;
-        pConfig->Write(wxT("/Filter/MicInTrebleFreqHz"), (int)m_MicInTreble.freqHz);
         wxGetApp().m_MicInTrebleGaindB = m_MicInTreble.gaindB;
-        pConfig->Write(wxT("/Filter/MicInTrebleGaindB"), (int)(10.0*m_MicInTreble.gaindB));
 
         wxGetApp().m_MicInMidFreqHz = m_MicInMid.freqHz;
-        pConfig->Write(wxT("/Filter/MicInMidFreqHz"), (int)m_MicInMid.freqHz);
         wxGetApp().m_MicInMidGaindB = m_MicInMid.gaindB;
-        pConfig->Write(wxT("/Filter/MicInMidGaindB"), (int)(10.0*m_MicInMid.gaindB));
         wxGetApp().m_MicInMidQ = m_MicInMid.Q;
-        pConfig->Write(wxT("/Filter/MicInMidQ"), (int)(100.0*m_MicInMid.Q));
 
         // Spk Out Equaliser
 
         wxGetApp().m_SpkOutBassFreqHz = m_SpkOutBass.freqHz;
-        pConfig->Write(wxT("/Filter/SpkOutBassFreqHz"), (int)m_SpkOutBass.freqHz);
         wxGetApp().m_SpkOutBassGaindB = m_SpkOutBass.gaindB;
-        pConfig->Write(wxT("/Filter/SpkOutBassGaindB"), (int)(10.0*m_SpkOutBass.gaindB));
 
         wxGetApp().m_SpkOutTrebleFreqHz = m_SpkOutTreble.freqHz;
-        pConfig->Write(wxT("/Filter/SpkOutTrebleFreqHz"), (int)m_SpkOutTreble.freqHz);
         wxGetApp().m_SpkOutTrebleGaindB = m_SpkOutTreble.gaindB;
-        pConfig->Write(wxT("/Filter/SpkOutTrebleGaindB"), (int)(10.0*m_SpkOutTreble.gaindB));
 
         wxGetApp().m_SpkOutMidFreqHz = m_SpkOutMid.freqHz;
-        pConfig->Write(wxT("/Filter/SpkOutMidFreqHz"), (int)m_SpkOutMid.freqHz);
         wxGetApp().m_SpkOutMidGaindB = m_SpkOutMid.gaindB;
-        pConfig->Write(wxT("/Filter/SpkOutMidGaindB"), (int)(10.0*m_SpkOutMid.gaindB));
         wxGetApp().m_SpkOutMidQ = m_SpkOutMid.Q;
-        pConfig->Write(wxT("/Filter/SpkOutMidQ"), (int)(100.0*m_SpkOutMid.Q));
 
-        pConfig->Flush();
+        if (storePersistent) {
+            pConfig->Write(wxT("/Filter/codec2LPCPostFilterEnable"),     wxGetApp().m_codec2LPCPostFilterEnable);
+            pConfig->Write(wxT("/Filter/codec2LPCPostFilterBassBoost"),  wxGetApp().m_codec2LPCPostFilterBassBoost);
+            pConfig->Write(wxT("/Filter/codec2LPCPostFilterBeta"),       (int)(m_beta*100.0));
+            pConfig->Write(wxT("/Filter/codec2LPCPostFilterGamma"),      (int)(m_gamma*100.0));
+
+            pConfig->Write(wxT("/Filter/MicInBassFreqHz"), (int)m_MicInBass.freqHz);
+            pConfig->Write(wxT("/Filter/MicInBassGaindB"), (int)(10.0*m_MicInBass.gaindB));
+            pConfig->Write(wxT("/Filter/MicInTrebleFreqHz"), (int)m_MicInTreble.freqHz);
+            pConfig->Write(wxT("/Filter/MicInTrebleGaindB"), (int)(10.0*m_MicInTreble.gaindB));
+            pConfig->Write(wxT("/Filter/MicInMidFreqHz"), (int)m_MicInMid.freqHz);
+            pConfig->Write(wxT("/Filter/MicInMidGaindB"), (int)(10.0*m_MicInMid.gaindB));
+            pConfig->Write(wxT("/Filter/MicInMidQ"), (int)(100.0*m_MicInMid.Q));
+
+            pConfig->Write(wxT("/Filter/SpkOutBassFreqHz"), (int)m_SpkOutBass.freqHz);
+            pConfig->Write(wxT("/Filter/SpkOutBassGaindB"), (int)(10.0*m_SpkOutBass.gaindB));
+            pConfig->Write(wxT("/Filter/SpkOutTrebleFreqHz"), (int)m_SpkOutTreble.freqHz);
+            pConfig->Write(wxT("/Filter/SpkOutTrebleGaindB"), (int)(10.0*m_SpkOutTreble.gaindB));
+            pConfig->Write(wxT("/Filter/SpkOutMidQ"), (int)(100.0*m_SpkOutMid.Q));
+            pConfig->Write(wxT("/Filter/SpkOutMidFreqHz"), (int)m_SpkOutMid.freqHz);
+            pConfig->Write(wxT("/Filter/SpkOutMidGaindB"), (int)(10.0*m_SpkOutMid.gaindB));
+
+            pConfig->Flush();
+        }
     }
     delete wxConfigBase::Set((wxConfigBase *) NULL);
 }
@@ -487,7 +491,7 @@ void FilterDlg::OnSpkOutDefault(wxCommandEvent& event)
 void FilterDlg::OnOK(wxCommandEvent& event)
 {
     //printf("FilterDlg::OnOK\n");
-    ExchangeData(EXCHANGE_DATA_OUT);
+    ExchangeData(EXCHANGE_DATA_OUT, true);
     this->EndModal(wxID_OK);
 }
 
@@ -505,7 +509,7 @@ void FilterDlg::OnClose(wxCloseEvent& event)
 void FilterDlg::OnInitDialog(wxInitDialogEvent& event)
 {
     //printf("FilterDlg::OnInitDialog\n");
-    ExchangeData(EXCHANGE_DATA_IN);
+    ExchangeData(EXCHANGE_DATA_IN, false);
     //printf("m_beta: %f\n", m_beta);
 }
 
@@ -555,13 +559,14 @@ void FilterDlg::OnGammaScroll(wxScrollEvent& event) {
     setCodec2();
 }
 
-// immediately change rather using ExchangeData() so we can switch on and off at run time
+// immediately change enable flags rather using ExchangeData() so we can switch on and off at run time
+
 void FilterDlg::OnMicInEnable(wxScrollEvent& event) {
-    wxGetApp().m_MicInEnable = m_MicInEnable->GetValue();
+    wxGetApp().m_MicInEQEnable = m_MicInEnable->GetValue();
 }
 
 void FilterDlg::OnSpkOutEnable(wxScrollEvent& event) {
-    wxGetApp().m_SpkOutEnable = m_SpkOutEnable->GetValue();
+    wxGetApp().m_SpkOutEQEnable = m_SpkOutEnable->GetValue();
 }
 
 void FilterDlg::setFreq(EQ *eq)
@@ -635,10 +640,26 @@ void FilterDlg::sliderToQ(EQ *eq, bool micIn)
 
 void FilterDlg::plotMicInFilterSpectrum(void) {
     plotFilterSpectrum(&m_MicInBass, &m_MicInMid, &m_MicInTreble, m_MicInFreqRespPlot, m_MicInMagdB);
+    
+    // signal an adjustment in running filter coeffs
+
+    if (m_running) {
+        ExchangeData(EXCHANGE_DATA_OUT, false);
+        *m_newMicInFilter = true;
+    }
+        
 }
 
 void FilterDlg::plotSpkOutFilterSpectrum(void) {
     plotFilterSpectrum(&m_SpkOutBass, &m_SpkOutMid, &m_SpkOutTreble, m_SpkOutFreqRespPlot, m_SpkOutMagdB);
+
+    // signal an adjustment in running filter coeffs
+
+    if (m_running) {
+        ExchangeData(EXCHANGE_DATA_OUT, false);
+        *m_newSpkOutFilter = true;
+    }
+        
 }
 
 void FilterDlg::plotFilterSpectrum(EQ *eqBass, EQ *eqMid, EQ *eqTreble, PlotSpectrum* freqRespPlot, float *magdB) {
@@ -709,7 +730,7 @@ void FilterDlg::calcFilterSpectrum(float magdB[], int argc, char *argv[]) {
     //out[0] = IMP_AMP;
 
     // calculate discrete time continous frequency Fourer transform
-    // doing this from basic principles rather than FFT for no good reason
+    // doing this from first 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/(FS/2);
index 4a561e735feee098a937ec35bd9f60933b702d7b..4e7562833a7e57504d84a03e3392efde69a8feb1 100644 (file)
@@ -51,12 +51,13 @@ typedef struct {
 class FilterDlg : public wxDialog
 {
     public:
-        FilterDlg( wxWindow* parent, bool running, wxWindowID id = wxID_ANY, const wxString& title = _("Filter"), 
-                   const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 1000, 700 ), 
-                   long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
+    FilterDlg( wxWindow* parent, bool running, bool *newMicInFilter, bool *newSpkOutFilter,
+               wxWindowID id = wxID_ANY, const wxString& title = _("Filter"), 
+               const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 1000, 700 ), 
+               long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
         ~FilterDlg();
 
-        void    ExchangeData(int inout);
+        void    ExchangeData(int inout, bool storePersistent);
 
     protected:
         // Handlers for events.
@@ -150,6 +151,9 @@ class FilterDlg : public wxDialog
         EQ            m_SpkOutTreble;
 
         float         limit(float value, float min, float max);
+        bool          *m_newMicInFilter;
+        bool          *m_newSpkOutFilter;
 
 };
 
index 90dc50ee807e928b5dc4ea5187ebceb45ad381a4..70d82c80c19ed7cea613f6d8af52812ac16b538e 100644 (file)
@@ -218,6 +218,8 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     wxGetApp().m_show_speech_out    = pConfig->Read(wxT("/MainFrame/show_speech_out"),    1);
     wxGetApp().m_show_demod_in      = pConfig->Read(wxT("/MainFrame/show_demod_in"),    1);
 
+    wxGetApp().m_rxNbookCtrl        = pConfig->Read(wxT("/MainFrame/rxNbookCtrl"),    (long)0);
+
     g_SquelchActive = pConfig->Read(wxT("/Audio/SquelchActive"), 1);
     g_SquelchLevel = pConfig->Read(wxT("/Audio/SquelchLevel"), (int)(SQ_DEFAULT_SNR*2));
     g_SquelchLevel /= 2.0;
@@ -338,7 +340,8 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     wxGetApp().m_MicInMidGaindB = (float)pConfig->Read(wxT("/Filter/MicInMidGaindB"),    (long)0)/10.0;
     wxGetApp().m_MicInMidQ = (float)pConfig->Read(wxT("/Filter/MicInMidQ"),    (long)100)/100.0;
 
-    wxGetApp().m_MicInEnable = (float)pConfig->Read(wxT("/Filter/MicInEnable"), t);
+    bool f = false;
+    wxGetApp().m_MicInEQEnable = (float)pConfig->Read(wxT("/Filter/MicInEQEnable"), f);
 
     wxGetApp().m_SpkOutBassFreqHz = (float)pConfig->Read(wxT("/Filter/SpkOutBassFreqHz"),    1);
     wxGetApp().m_SpkOutBassGaindB = (float)pConfig->Read(wxT("/Filter/SpkOutBassGaindB"),    (long)0)/10.0;
@@ -348,7 +351,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     wxGetApp().m_SpkOutMidGaindB = (float)pConfig->Read(wxT("/Filter/SpkOutMidGaindB"),    (long)0)/10.0;
     wxGetApp().m_SpkOutMidQ = (float)pConfig->Read(wxT("/Filter/SpkOutMidQ"),    (long)100)/100.0;
 
-    wxGetApp().m_SpkOutEnable = (float)pConfig->Read(wxT("/Filter/SpkOutEnable"), t);
+    wxGetApp().m_SpkOutEQEnable = (float)pConfig->Read(wxT("/Filter/SpkOutEQEnable"), f);
 
     wxGetApp().m_callSign = pConfig->Read("/Data/CallSign", wxT(""));
 
@@ -430,6 +433,9 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     g_txDataInFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);   
     g_rxDataOutFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);   
     varicode_decode_init(&g_varicode_dec_states);
+
+    sox_biquad_start();
+
 }
 
 //-------------------------------------------------------------------------
@@ -461,6 +467,8 @@ MainFrame::~MainFrame()
         pConfig->Write(wxT("/MainFrame/show_speech_out"),   wxGetApp().m_show_speech_out);
         pConfig->Write(wxT("/MainFrame/show_demod_in"),     wxGetApp().m_show_demod_in);
 
+        pConfig->Write(wxT("/MainFrame/rxNbookCtrl"), wxGetApp().m_rxNbookCtrl);
+
         pConfig->Write(wxT("/Audio/SquelchActive"),         g_SquelchActive);
         pConfig->Write(wxT("/Audio/SquelchLevel"),          (int)(g_SquelchLevel*2.0));
 
@@ -495,8 +503,8 @@ MainFrame::~MainFrame()
 
         pConfig->Write(wxT("/Data/CallSign"), wxGetApp().m_callSign);
  
-        pConfig->Write(wxT("/Filter/MicInEnable"), wxGetApp().m_MicInEnable);
-        pConfig->Write(wxT("/Filter/SpkOutEnable"), wxGetApp().m_SpkOutEnable);
+        pConfig->Write(wxT("/Filter/MicInEQEnable"), wxGetApp().m_MicInEQEnable);
+        pConfig->Write(wxT("/Filter/SpkOutEQEnable"), wxGetApp().m_SpkOutEQEnable);
     }
 
     //m_togRxID->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(MainFrame::OnTogBtnRxIDUI), NULL, this);
@@ -508,6 +516,7 @@ MainFrame::~MainFrame()
     m_btnTogPTT->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(MainFrame::OnTogBtnTXClickUI), NULL, this);
     
     CloseSerialPort();
+    sox_biquad_finish();
     
     if (m_RxRunning)
     {
@@ -660,7 +669,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
 
     m_maxLevel *= LEVEL_BETA;
 
-    // sync LED (Colours don't work on Windows)
+    // sync LED (Colours don't work on Windows) ------------------------
 
     if (g_State) {
         m_rbSync->SetForegroundColour( wxColour( 0, 255, 0 ) ); // green
@@ -671,7 +680,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
         m_rbSync->SetValue(false);
     }
 
-    // send Callsign
+    // send Callsign ----------------------------------------------------
 
     if (fifo_used(g_txDataInFifo) == 0) {
         char callsign[MAX_CALLSIGN];
@@ -688,7 +697,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
         //printf("Callsign sending: %s nout: %d\n", callsign, nout);
     }
 
-    // See if any callsign info received
+    // See if any Callsign info received --------------------------------
 
     short ashort;
     while (fifo_read(g_rxDataOutFifo, &ashort, 1) == 0) {            
@@ -705,7 +714,20 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
         }
     }
 
+    // Run time upodate of EQ filters -----------------------------------
+
+    if (m_newMicInFilter || m_newSpkOutFilter) {
+        printf("new filter...\n");
+        g_mutexProtectingCallbackData.Lock();
+        deleteEQFilters(g_rxUserdata);
+        designEQFilters(g_rxUserdata);        
+        g_mutexProtectingCallbackData.Unlock();
+        g_rxUserdata->micInEQEnable = wxGetApp().m_MicInEQEnable;
+        g_rxUserdata->spkOutEQEnable = wxGetApp().m_SpkOutEQEnable;
+        m_newMicInFilter = m_newSpkOutFilter = false;
+    }
 }
+
 #endif
 
 #ifdef _USE_ONIDLE
@@ -868,15 +890,19 @@ void MainFrame::OnTogBtnTXClick(wxCommandEvent& event)
 {
     if (g_tx) 
     {
-        // tx-> rx transition, swap to Waterfall
-        m_auiNbookCtrl->ChangeSelection(0); 
+        // tx-> rx transition, swap to the page we were on for last rx
+        m_auiNbookCtrl->ChangeSelection(wxGetApp().m_rxNbookCtrl); 
     }
     else 
     {
         // rx-> tx transition, swap to Mic In page to monitor speech
+
+        wxGetApp().m_rxNbookCtrl = m_auiNbookCtrl->GetSelection();
         m_auiNbookCtrl->ChangeSelection(4); // is there a way to avoid hard coding this?
+        
     }
     g_tx = m_btnTogPTT->GetValue();
+
     // The following sets and clears may be exactly inverted.  
     // I don't know and I'm not set up to tell yet.
     // If so, one just needs to invert the polarity selection
@@ -931,7 +957,7 @@ void MainFrame::OnTogBtnTXClick(wxCommandEvent& event)
             }
         }
     } 
-    
+
     // reset level gauge
     m_maxLevel = 0;
     m_textLevel->SetLabel(wxT(""));
@@ -1355,7 +1381,7 @@ void MainFrame::OnToolsAudio(wxCommandEvent& event)
 void MainFrame::OnToolsFilter(wxCommandEvent& event)
 {
     wxUnusedVar(event);
-    FilterDlg *dlg = new FilterDlg(NULL, m_RxRunning);
+    FilterDlg *dlg = new FilterDlg(NULL, m_RxRunning, &m_newMicInFilter, &m_newSpkOutFilter);
     dlg->ShowModal();
     delete dlg;
 }
@@ -1476,7 +1502,7 @@ void MainFrame::OnHelpAbout(wxCommandEvent& event)
             //printf("In OK\n");
             wxStringOutputStream html_stream(&htmldata);
             in->Read(html_stream);
-            wxLogDebug(htmldata);
+            //wxLogDebug(htmldata);
  
             wxString s("<h2>freetel - Revision ");
             int startIndex = htmldata.find(s) + s.Length();
@@ -1511,6 +1537,10 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
 
     if (startStop.IsSameAs("Start")) 
     {
+        // 
+        // Start Running -------------------------------------------------
+        //
+
         m_togBtnSplit->Enable();
         //m_togRxID->Enable();
         //m_togTxID->Enable();
@@ -1561,6 +1591,10 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
 
     if (startStop.IsSameAs("Stop") || !m_RxRunning ) {
 
+        // 
+        // Stop Running -------------------------------------------------
+        //
+
         #ifdef _USE_TIMER
         m_plotTimer.Stop();
         #endif // _USE_TIMER
@@ -1628,34 +1662,6 @@ void MainFrame::destroy_src(void)
     src_delete(g_rxUserdata->outsrc2);
 }
 
-void MainFrame::autoDetectSoundCards(PortAudioWrap *pa)
-{
-    const   PaDeviceInfo *deviceInfo;
-    int     i;
-
-    // trap zero sound devices
-
-    if (pa->getDeviceCount() == 0) {
-        wxMessageBox(wxT("No sound devices found"), wxT("Error"), wxOK);
-        return;
-    }
-
-    for(i=0; i<pa->getDeviceCount(); i++) {
-        deviceInfo = Pa_GetDeviceInfo( i );
-
-    // supports full duplex and 44800 and 44100
-    // is there something unique so we know it's a hw device?
-    // does this work on Linux & Windows?
-
-    printf( "--------------------------------------- device #%d\n", i );
-        printf( "Name                        = %s\n", deviceInfo->name );
-        printf( "Host API                    = %s\n",  Pa_GetHostApiInfo( deviceInfo->hostApi )->name );
-        printf( "Max inputs = %d", deviceInfo->maxInputChannels  );
-        printf( ", Max outputs = %d\n", deviceInfo->maxOutputChannels  );
-        printf( "Default sample rate         = %8.2f\n", deviceInfo->defaultSampleRate );
-    }
-}
-
 void  MainFrame::initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevice, 
                                      int soundCard, int sampleRate, int inputChannels)
 {
@@ -1812,6 +1818,12 @@ void MainFrame::startRxStream()
         g_rxUserdata->rxinfifo = fifo_create(3 * FDMDV_NOM_SAMPLES_PER_FRAME);
         g_rxUserdata->rxoutfifo = fifo_create(2 * codec2_samples_per_frame(g_pCodec2));
         
+        // Init Equaliser Filters ------------------------------------------------------
+
+        designEQFilters(g_rxUserdata);
+        g_rxUserdata->micInEQEnable = wxGetApp().m_MicInEQEnable;
+        g_rxUserdata->spkOutEQEnable = wxGetApp().m_SpkOutEQEnable;
+
         // Start sound card 1 ----------------------------------------------------------
 
         m_rxPa->setUserData(g_rxUserdata);
@@ -1897,11 +1909,88 @@ void MainFrame::startRxStream()
         {
             wxLogError(wxT("Can't start thread!"));
         }
-   }
+    }
  
 }
 
 
+#define SBQ_MAX_ARGS 4
+
+void *MainFrame::designAnEQFilter(const char filterType[], float freqHz, float gaindB, float Q)
+{
+    char  *arg[SBQ_MAX_ARGS];
+    char   argstorage[SBQ_MAX_ARGS][80];
+    void  *sbq;
+    int    i, argc;
+
+    assert((strcmp(filterType, "bass") == 0)   || 
+           (strcmp(filterType, "treble") == 0) ||
+           (strcmp(filterType, "equalizer") == 0));
+
+    for(i=0; i<SBQ_MAX_ARGS; i++) {
+        arg[i] = &argstorage[i][0];
+        arg[i] = &argstorage[i][0];
+        arg[i] = &argstorage[i][0];
+    }
+
+    argc = 0;
+
+    if ((strcmp(filterType, "bass") == 0) || (strcmp(filterType, "treble") == 0)) {
+        sprintf(arg[argc++], "%s", filterType);                
+        sprintf(arg[argc++], "%f", gaindB+1E-6);
+        sprintf(arg[argc++], "%f", freqHz);      
+    }
+
+    if (strcmp(filterType, "equalizer") == 0) {
+        sprintf(arg[argc++], "%s", filterType);                
+        sprintf(arg[argc++], "%f", freqHz);      
+        sprintf(arg[argc++], "%f", Q);      
+        sprintf(arg[argc++], "%f", gaindB+1E-6);
+    }
+
+    assert(argc <= SBQ_MAX_ARGS);
+
+    sbq = sox_biquad_create(argc-1, (const char **)arg);
+
+    return sbq;
+}
+
+void  MainFrame::designEQFilters(paCallBackData *cb)
+{
+    // init Mic In Equaliser Filters
+
+    if (m_newMicInFilter) {
+        printf("designing new Min In filters\n");
+        cb->sbqMicInBass   = designAnEQFilter("bass", wxGetApp().m_MicInBassFreqHz, wxGetApp().m_MicInBassGaindB);
+        cb->sbqMicInTreble = designAnEQFilter("treble", wxGetApp().m_MicInTrebleFreqHz, wxGetApp().m_MicInTrebleGaindB);
+        cb->sbqMicInMid    = designAnEQFilter("equalizer", wxGetApp().m_MicInMidFreqHz, wxGetApp().m_MicInMidGaindB, wxGetApp().m_MicInMidQ);
+    }
+
+    // init Spk Out Equaliser Filters
+
+    if (m_newSpkOutFilter) {
+        printf("designing new Spk Out filters\n");
+        cb->sbqSpkOutBass   = designAnEQFilter("bass", wxGetApp().m_SpkOutBassFreqHz, wxGetApp().m_SpkOutBassGaindB);
+        cb->sbqSpkOutTreble = designAnEQFilter("treble", wxGetApp().m_SpkOutTrebleFreqHz, wxGetApp().m_SpkOutTrebleGaindB);
+        cb->sbqSpkOutMid    = designAnEQFilter("equalizer", wxGetApp().m_SpkOutMidFreqHz, wxGetApp().m_SpkOutMidGaindB, wxGetApp().m_SpkOutMidQ);
+    }
+
+}
+
+void  MainFrame::deleteEQFilters(paCallBackData *cb)
+{
+    if (m_newMicInFilter) {
+        sox_biquad_destroy(cb->sbqMicInBass);
+        sox_biquad_destroy(cb->sbqMicInTreble);
+        sox_biquad_destroy(cb->sbqMicInMid);
+    }
+    if (m_newSpkOutFilter) {
+        sox_biquad_destroy(cb->sbqSpkOutBass);
+        sox_biquad_destroy(cb->sbqSpkOutTreble);
+        sox_biquad_destroy(cb->sbqSpkOutMid);
+    }
+}
+
 // returns number of output samples generated by resampling
 
 int resample(SRC_STATE *src,
@@ -2030,7 +2119,7 @@ void txRxProcessing()
 
         g_mutexProtectingCallbackData.Lock();
         if (g_playFileFromRadio && (g_sfPlayFileFromRadio != NULL)) {
-            int n = sf_read_short(g_sfPlayFileFromRadio, in8k_short, N8);
+            int n = sf_read_short(g_sfPlayFileFromRadio, in8k_short, n8k);
             if (n != N8) {
                 if (g_loopPlayFileFromRadio)
                     sf_seek(g_sfPlayFileFromRadio, 0, SEEK_SET);
@@ -2043,7 +2132,7 @@ void txRxProcessing()
             }
         }
         g_mutexProtectingCallbackData.Unlock();
-
+        
         fifo_write(cbData->rxinfifo, in8k_short, n8k);
         resample_for_plot(g_plotDemodInFifo, in8k_short, n8k);
 
@@ -2059,6 +2148,15 @@ void txRxProcessing()
             fifo_read(cbData->rxoutfifo, out8k_short, N8);
         }
         
+        // Opional Spk Out EQ Filtering, need mutex as filter can change at run time
+        g_mutexProtectingCallbackData.Lock();
+        if (cbData->spkOutEQEnable) {
+            sox_biquad_filter(cbData->sbqSpkOutBass,   out8k_short, out8k_short, N8);
+            sox_biquad_filter(cbData->sbqSpkOutTreble, out8k_short, out8k_short, N8);
+            sox_biquad_filter(cbData->sbqSpkOutMid,    out8k_short, out8k_short, N8);
+        }
+        g_mutexProtectingCallbackData.Unlock();
+
         if (g_SquelchActive && (g_SquelchLevel > g_snr)) {
             //printf("g_SquelchLevel: %f g_snr: %f\n", g_SquelchLevel, g_snr);
             memset(out8k_short, 0, sizeof(short)*N8);
@@ -2113,8 +2211,8 @@ void txRxProcessing()
             // optionally use file for mic input signal
             g_mutexProtectingCallbackData.Lock();
             if (g_playFileToMicIn && (g_sfPlayFile != NULL)) {
-                int n = sf_read_short(g_sfPlayFile, in8k_short, 2*N8);
-                if (n != 2*N8) {
+                int n = sf_read_short(g_sfPlayFile, in8k_short, nout);
+                if (n != nout) {
                     if (g_loopPlayFileToMicIn)
                         sf_seek(g_sfPlayFile, 0, SEEK_SET);
                     else {
@@ -2126,6 +2224,15 @@ void txRxProcessing()
             }
             g_mutexProtectingCallbackData.Unlock();
 
+            // Opional Mic In EQ Filtering, need mutex as filter can change at run time
+            g_mutexProtectingCallbackData.Lock();
+            if (cbData->micInEQEnable) {
+                sox_biquad_filter(cbData->sbqMicInBass, in8k_short, in8k_short, nout);
+                sox_biquad_filter(cbData->sbqMicInTreble, in8k_short, in8k_short, nout);
+                sox_biquad_filter(cbData->sbqMicInMid, in8k_short, in8k_short, nout);
+            }
+            g_mutexProtectingCallbackData.Unlock();
+
             resample_for_plot(g_plotSpeechInFifo, in8k_short, nout);
 
             if (g_analog)
index 694df2bf41a0701f16b6c612d186f71c3bc77d80..8de702ae82af3a2d6416abb69158d943386e2578 100644 (file)
@@ -69,6 +69,7 @@
 #include "dlg_audiooptions.h"
 #include "dlg_filter.h"
 #include "varicode.h"
+#include "sox_biquad.h"
 
 #define _USE_TIMER              1
 #define _USE_ONIDLE             1
@@ -160,7 +161,7 @@ class MainApp : public wxApp
         float               m_MicInMidFreqHz;
         float               m_MicInMidGaindB;
         float               m_MicInMidQ;
-        bool                m_MicInEnable;
+        bool                m_MicInEQEnable;
 
         // Spk Out Equaliser
         float               m_SpkOutBassFreqHz;
@@ -170,7 +171,7 @@ class MainApp : public wxApp
         float               m_SpkOutMidFreqHz;
         float               m_SpkOutMidGaindB;
         float               m_SpkOutMidQ;
-        bool                m_SpkOutEnable;
+        bool                m_SpkOutEQEnable;
 
         // Flags for displaying windows
         int                 m_show_wf;
@@ -182,6 +183,9 @@ class MainApp : public wxApp
         int                 m_show_speech_out;
         int                 m_show_demod_in;
 
+        // notebook display after tx->rxtransition
+        int                 m_rxNbookCtrl;
+
         wxRect              m_rTopWindow;
 
         int                 m_framesPerBuffer;
@@ -223,6 +227,19 @@ typedef struct
     struct FIFO    *rxoutfifo;
 
     int             inputChannels1, inputChannels2;
+
+    // EQ filter states
+
+    void           *sbqMicInBass;
+    void           *sbqMicInTreble;
+    void           *sbqMicInMid;
+    void           *sbqSpkOutBass;
+    void           *sbqSpkOutTreble;
+    void           *sbqSpkOutMid;
+
+    bool            micInEQEnable;
+    bool            spkOutEQEnable;
+
 } paCallBackData;
 
 // panel with custom loop checkbox for play file dialog
@@ -396,6 +413,16 @@ class MainFrame : public TopFrame
 
         // level Gauge
         float       m_maxLevel;
+        // flags to indicate when new EQ filters need to be designed
+
+        bool        m_newMicInFilter;
+        bool        m_newSpkOutFilter;
+
+        void*       designAnEQFilter(const char filterType[], float freqHz, float gaindB, float Q = 0.0);
+        void        designEQFilters(paCallBackData *cb);
+        void        deleteEQFilters(paCallBackData *cb);
+
 };
 
 void resample_for_plot(struct FIFO *plotFifo, short buf[], int length);