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)
-------------------------------------
build$ sudo cp ../include/ctb-0.16/kbhit.h /usr/local/include/ctb-0.16
build$ sudo ldconfig
+>>>>>>> .r1094
Build codec2-dev
----------------
[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
Setting up in audio loopback
Explain one and two soundcard modes
+
+Right click drag tabs, new window, tab order
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)
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 \
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
//
//==========================================================================
#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;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
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 --------------------------
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();
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
FilterDlg::~FilterDlg()
{
+ delete m_MicInMagdB;
+ delete m_SpkOutMagdB;
+ sox_biquad_finish();
+
// Disconnect Events
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(FilterDlg::OnInitDialog));
// 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)
{
m_gamma = CODEC2_LPC_PF_GAMMA; setGamma();
m_codec2LPCPostFilterEnable->SetValue(true);
m_codec2LPCPostFilterBassBoost->SetValue(true);
+
+ m_MicInBass.freqHz = 1.0;
+
}
//-------------------------------------------------------------------------
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]);
+ }
+}
wxButton* m_sdbSizer5Cancel;
PlotSpectrum* m_MicInFreqRespPlot;
PlotSpectrum* m_SpkOutFreqRespPlot;
+
+ float *m_MicInMagdB;
+ float *m_SpkOutMagdB;
private:
bool m_running;
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;
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);
}
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(""));
// @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();
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;
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;
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;
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; }
float m_rxFreq;
float m_max_mag_db;
float m_min_mag_db;
+ float *m_magdB;
+ int m_n_magdB;
DECLARE_EVENT_TABLE()
};
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 */
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);