1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-01 16:19:43 +02:00

Merge pull request #40 from lllucius/FreqWindow

Freq window
This commit is contained in:
Leland Lucius 2015-05-04 06:58:52 -05:00
commit 4d06c4e6c0
6 changed files with 1232 additions and 941 deletions

View File

@ -484,32 +484,32 @@ void PowerSpectrum(int NumSamples, float *In, float *Out)
int NumWindowFuncs() int NumWindowFuncs()
{ {
return 10; return eWinFuncCount;
} }
const wxChar *WindowFuncName(int whichFunction) const wxChar *WindowFuncName(int whichFunction)
{ {
switch (whichFunction) { switch (whichFunction) {
default: default:
case 0: case eWinFuncRectangular:
return _("Rectangular"); return _("Rectangular");
case 1: case eWinFuncBartlett:
return wxT("Bartlett"); return wxT("Bartlett");
case 2: case eWinFuncHamming:
return wxT("Hamming"); return wxT("Hamming");
case 3: case eWinFuncHanning:
return wxT("Hanning"); return wxT("Hanning");
case 4: case eWinFuncBlackman:
return wxT("Blackman"); return wxT("Blackman");
case 5: case eWinFuncBlackmanHarris:
return wxT("Blackman-Harris"); return wxT("Blackman-Harris");
case 6: case eWinFuncWelch:
return wxT("Welch"); return wxT("Welch");
case 7: case eWinFuncGaussian25:
return wxT("Gaussian(a=2.5)"); return wxT("Gaussian(a=2.5)");
case 8: case eWinFuncGaussian35:
return wxT("Gaussian(a=3.5)"); return wxT("Gaussian(a=3.5)");
case 9: case eWinFuncGaussian45:
return wxT("Gaussian(a=4.5)"); return wxT("Gaussian(a=4.5)");
} }
} }
@ -521,7 +521,12 @@ void WindowFunc(int whichFunction, int NumSamples, float *in)
switch( whichFunction ) switch( whichFunction )
{ {
case 1: default:
fprintf(stderr,"FFT::WindowFunc - Invalid window function: %d\n",whichFunction);
break;
case eWinFuncRectangular:
break;
case eWinFuncBartlett:
// Bartlett (triangular) window // Bartlett (triangular) window
for (i = 0; i < NumSamples / 2; i++) { for (i = 0; i < NumSamples / 2; i++) {
in[i] *= (i / (float) (NumSamples / 2)); in[i] *= (i / (float) (NumSamples / 2));
@ -529,35 +534,35 @@ void WindowFunc(int whichFunction, int NumSamples, float *in)
(1.0 - (i / (float) (NumSamples / 2))); (1.0 - (i / (float) (NumSamples / 2)));
} }
break; break;
case 2: case eWinFuncHamming:
// Hamming // Hamming
for (i = 0; i < NumSamples; i++) for (i = 0; i < NumSamples; i++)
in[i] *= 0.54 - 0.46 * cos(2 * M_PI * i / (NumSamples - 1)); in[i] *= 0.54 - 0.46 * cos(2 * M_PI * i / (NumSamples - 1));
break; break;
case 3: case eWinFuncHanning:
// Hanning // Hanning
for (i = 0; i < NumSamples; i++) for (i = 0; i < NumSamples; i++)
in[i] *= 0.50 - 0.50 * cos(2 * M_PI * i / (NumSamples - 1)); in[i] *= 0.50 - 0.50 * cos(2 * M_PI * i / (NumSamples - 1));
break; break;
case 4: case eWinFuncBlackman:
// Blackman // Blackman
for (i = 0; i < NumSamples; i++) { for (i = 0; i < NumSamples; i++) {
in[i] *= 0.42 - 0.5 * cos (2 * M_PI * i / (NumSamples - 1)) + 0.08 * cos (4 * M_PI * i / (NumSamples - 1)); in[i] *= 0.42 - 0.5 * cos (2 * M_PI * i / (NumSamples - 1)) + 0.08 * cos (4 * M_PI * i / (NumSamples - 1));
} }
break; break;
case 5: case eWinFuncBlackmanHarris:
// Blackman-Harris // Blackman-Harris
for (i = 0; i < NumSamples; i++) { for (i = 0; i < NumSamples; i++) {
in[i] *= 0.35875 - 0.48829 * cos(2 * M_PI * i /(NumSamples-1)) + 0.14128 * cos(4 * M_PI * i/(NumSamples-1)) - 0.01168 * cos(6 * M_PI * i/(NumSamples-1)); in[i] *= 0.35875 - 0.48829 * cos(2 * M_PI * i /(NumSamples-1)) + 0.14128 * cos(4 * M_PI * i/(NumSamples-1)) - 0.01168 * cos(6 * M_PI * i/(NumSamples-1));
} }
break; break;
case 6: case eWinFuncWelch:
// Welch // Welch
for (i = 0; i < NumSamples; i++) { for (i = 0; i < NumSamples; i++) {
in[i] *= 4*i/(float)NumSamples*(1-(i/(float)NumSamples)); in[i] *= 4*i/(float)NumSamples*(1-(i/(float)NumSamples));
} }
break; break;
case 7: case eWinFuncGaussian25:
// Gaussian (a=2.5) // Gaussian (a=2.5)
// Precalculate some values, and simplify the fmla to try and reduce overhead // Precalculate some values, and simplify the fmla to try and reduce overhead
A=-2*2.5*2.5; A=-2*2.5*2.5;
@ -569,7 +574,7 @@ void WindowFunc(int whichFunction, int NumSamples, float *in)
in[i] *= exp(A*(0.25 + ((i/(float)NumSamples)*(i/(float)NumSamples)) - (i/(float)NumSamples))); in[i] *= exp(A*(0.25 + ((i/(float)NumSamples)*(i/(float)NumSamples)) - (i/(float)NumSamples)));
} }
break; break;
case 8: case eWinFuncGaussian35:
// Gaussian (a=3.5) // Gaussian (a=3.5)
A=-2*3.5*3.5; A=-2*3.5*3.5;
for (i = 0; i < NumSamples; i++) { for (i = 0; i < NumSamples; i++) {
@ -577,7 +582,7 @@ void WindowFunc(int whichFunction, int NumSamples, float *in)
in[i] *= exp(A*(0.25 + ((i/(float)NumSamples)*(i/(float)NumSamples)) - (i/(float)NumSamples))); in[i] *= exp(A*(0.25 + ((i/(float)NumSamples)*(i/(float)NumSamples)) - (i/(float)NumSamples)));
} }
break; break;
case 9: case eWinFuncGaussian45:
// Gaussian (a=4.5) // Gaussian (a=4.5)
A=-2*4.5*4.5; A=-2*4.5*4.5;
@ -586,7 +591,5 @@ void WindowFunc(int whichFunction, int NumSamples, float *in)
in[i] *= exp(A*(0.25 + ((i/(float)NumSamples)*(i/(float)NumSamples)) - (i/(float)NumSamples))); in[i] *= exp(A*(0.25 + ((i/(float)NumSamples)*(i/(float)NumSamples)) - (i/(float)NumSamples)));
} }
break; break;
default:
fprintf(stderr,"FFT::WindowFunc - Invalid window function: %d\n",whichFunction);
} }
} }

View File

@ -29,6 +29,9 @@
you need to use doubles. you need to use doubles.
**********************************************************************/ **********************************************************************/
#ifndef __AUDACITY_FFT_H__
#define __AUDACITY_FFT_H__
/* /*
Salvo Ventura - November 2006 Salvo Ventura - November 2006
Added more window functions: Added more window functions:
@ -102,6 +105,21 @@ void FFT(int NumSamples,
* 9: Gaussian(a=4.5) * 9: Gaussian(a=4.5)
*/ */
enum eWindowFunctions
{
eWinFuncRectangular,
eWinFuncBartlett,
eWinFuncHamming,
eWinFuncHanning,
eWinFuncBlackman,
eWinFuncBlackmanHarris,
eWinFuncWelch,
eWinFuncGaussian25,
eWinFuncGaussian35,
eWinFuncGaussian45,
eWinFuncCount
};
void WindowFunc(int whichFunction, int NumSamples, float *data); void WindowFunc(int whichFunction, int NumSamples, float *data);
/* /*
@ -117,3 +135,5 @@ const wxChar *WindowFuncName(int whichFunction);
int NumWindowFuncs(); int NumWindowFuncs();
void DeinitFFT(); void DeinitFFT();
#endif

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <wx/brush.h> #include <wx/brush.h>
#include <wx/dcmemory.h>
#include <wx/frame.h> #include <wx/frame.h>
#include <wx/panel.h> #include <wx/panel.h>
#include <wx/checkbox.h> #include <wx/checkbox.h>
@ -21,8 +22,13 @@
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
#include <wx/pen.h> #include <wx/pen.h>
#include <wx/font.h> #include <wx/font.h>
#include <wx/scrolbar.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/statusbr.h>
#include <wx/textctrl.h>
#include <wx/utils.h>
#include "widgets/Ruler.h" #include "widgets/Ruler.h"
@ -31,26 +37,11 @@ class wxButton;
class wxChoice; class wxChoice;
class FreqWindow; class FreqWindow;
class FreqGauge;
class TrackList; class TrackList;
class ProgressDialog; DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_FREQWINDOW_RECALC, -1);
class FreqPlot:public wxWindow {
public:
FreqPlot(wxWindow * parent, wxWindowID id,
const wxPoint & pos, const wxSize & size);
void OnMouseEvent(wxMouseEvent & event);
void OnPaint(wxPaintEvent & event);
void OnErase(wxEraseEvent & event);
private:
FreqWindow * freqWindow;
DECLARE_EVENT_TABLE()
};
class SpectrumAnalyst class SpectrumAnalyst
{ {
@ -74,32 +65,76 @@ public:
int windowFunc, // see FFT.h for values int windowFunc, // see FFT.h for values
int windowSize, double rate, int windowSize, double rate,
const float *data, int dataLen, const float *data, int dataLen,
float *pYMin = 0, float *pYMax = 0, // outputs float *pYMin = NULL, float *pYMax = NULL, // outputs
ProgressDialog *progress = 0); FreqGauge *progress = NULL);
const float *GetProcessed() const { return &mProcessed[0]; } const float *GetProcessed() const;
int GetProcessedSize() const { return mProcessed.size() / 2; } int GetProcessedSize() const;
float GetProcessedValue(float freq0, float freq1) const; float GetProcessedValue(float freq0, float freq1) const;
float FindPeak(float xPos, float *pY) const; float FindPeak(float xPos, float *pY) const;
private: private:
float CubicInterpolate(float y0, float y1, float y2, float y3, float x) const;
float CubicMaximize(float y0, float y1, float y2, float y3, float * max) const;
private:
Algorithm mAlg; Algorithm mAlg;
double mRate; double mRate;
int mWindowSize; int mWindowSize;
std::vector<float> mProcessed; std::vector<float> mProcessed;
}; };
class FreqWindow:public wxDialog { class FreqGauge : public wxStatusBar
public: {
FreqWindow(wxWindow * parent, wxWindowID id, public:
FreqGauge(wxWindow * parent);
void SetRange(int range, int bar = 12, int gap = 3);
void SetValue(int value);
void Reset();
private:
wxRect mRect;
int mRange;
int mCur;
int mLast;
int mInterval;
int mBar;
int mGap;
int mMargin;
};
class FreqPlot : public wxWindow
{
public:
FreqPlot(wxWindow *parent);
// We don't need or want to accept focus.
bool AcceptsFocus() const;
private:
void OnPaint(wxPaintEvent & event);
void OnErase(wxEraseEvent & event);
void OnMouseEvent(wxMouseEvent & event);
private:
FreqWindow *freqWindow;
DECLARE_EVENT_TABLE();
};
class FreqWindow : public wxDialog
{
public:
FreqWindow(wxWindow *parent, wxWindowID id,
const wxString & title, const wxPoint & pos); const wxString & title, const wxPoint & pos);
virtual ~ FreqWindow(); virtual ~ FreqWindow();
void GetAudio();
void Plot(); virtual bool Show( bool show = true );
private:
void GetAudio();
void PlotMouseEvent(wxMouseEvent & event); void PlotMouseEvent(wxMouseEvent & event);
void PlotPaint(wxPaintEvent & event); void PlotPaint(wxPaintEvent & event);
@ -107,6 +142,8 @@ class FreqWindow:public wxDialog {
void OnCloseWindow(wxCloseEvent & event); void OnCloseWindow(wxCloseEvent & event);
void OnCloseButton(wxCommandEvent & event); void OnCloseButton(wxCommandEvent & event);
void OnSize(wxSizeEvent & event); void OnSize(wxSizeEvent & event);
void OnPanScroller(wxScrollEvent & event);
void OnZoomSlider(wxCommandEvent & event);
void OnAlgChoice(wxCommandEvent & event); void OnAlgChoice(wxCommandEvent & event);
void OnSizeChoice(wxCommandEvent & event); void OnSizeChoice(wxCommandEvent & event);
void OnFuncChoice(wxCommandEvent & event); void OnFuncChoice(wxCommandEvent & event);
@ -114,12 +151,14 @@ class FreqWindow:public wxDialog {
void OnExport(wxCommandEvent & event); void OnExport(wxCommandEvent & event);
void OnReplot(wxCommandEvent & event); void OnReplot(wxCommandEvent & event);
void OnGridOnOff(wxCommandEvent & event); void OnGridOnOff(wxCommandEvent & event);
void OnRecalc(wxCommandEvent & event);
void SendRecalcEvent();
void Recalc(); void Recalc();
void DrawPlot(); void DrawPlot();
void DrawBackground(wxMemoryDC & dc);
private: private:
float *mBuffer;
bool mDrawGrid; bool mDrawGrid;
int mSize; int mSize;
SpectrumAnalyst::Algorithm mAlg; SpectrumAnalyst::Algorithm mAlg;
@ -134,9 +173,12 @@ class FreqWindow:public wxDialog {
static const int fontSize = 10; static const int fontSize = 10;
#endif #endif
wxStatusBar *mInfo; RulerPanel *vRuler;
RulerPanel *hRuler;
FreqPlot *mFreqPlot; FreqPlot *mFreqPlot;
FreqGauge *mProgress;
wxRect mPlotRect;
wxFont mFreqFont; wxFont mFreqFont;
@ -146,22 +188,16 @@ class FreqWindow:public wxDialog {
wxButton *mCloseButton; wxButton *mCloseButton;
wxButton *mExportButton; wxButton *mExportButton;
wxButton *mReplotButton; wxButton *mReplotButton;
wxCheckBox *mGridOnOff;
wxChoice *mAlgChoice; wxChoice *mAlgChoice;
wxChoice *mSizeChoice; wxChoice *mSizeChoice;
wxChoice *mFuncChoice; wxChoice *mFuncChoice;
wxChoice *mAxisChoice; wxChoice *mAxisChoice;
wxCheckBox *mGridOnOff; wxScrollBar *mPanScroller;
wxSlider *mZoomSlider;
wxTextCtrl *mCursorText;
wxTextCtrl *mPeakText;
wxRect mPlotRect;
wxRect mInfoRect;
wxRect mUpdateRect;
wxFlexGridSizer *szr;
RulerPanel *vRuler;
RulerPanel *hRuler;
wxStaticText *mInfoText;
int mLeftMargin;
int mBottomMargin;
int mInfoHeight;
double mRate; double mRate;
int mDataLen; int mDataLen;
@ -180,7 +216,9 @@ class FreqWindow:public wxDialog {
std::auto_ptr<SpectrumAnalyst> mAnalyst; std::auto_ptr<SpectrumAnalyst> mAnalyst;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE();
friend class FreqPlot;
}; };
#endif #endif

View File

@ -5078,8 +5078,6 @@ void AudacityProject::OnPlotSpectrum()
mFreqWindow = new FreqWindow(this, -1, _("Frequency Analysis"), where); mFreqWindow = new FreqWindow(this, -1, _("Frequency Analysis"), where);
} }
wxCommandEvent dummy;
mFreqWindow->OnReplot(dummy);
mFreqWindow->Show(true); mFreqWindow->Show(true);
mFreqWindow->Raise(); mFreqWindow->Raise();
mFreqWindow->SetFocus(); mFreqWindow->SetFocus();

View File

@ -12,6 +12,7 @@
#define __AUDACITY_SPECTRUM__ #define __AUDACITY_SPECTRUM__
#include "WaveTrack.h" #include "WaveTrack.h"
#include "FFT.h"
/* /*
This function computes the power (mean square amplitude) as This function computes the power (mean square amplitude) as
@ -22,6 +23,7 @@
*/ */
bool ComputeSpectrum(float * data, int width, int windowSize, bool ComputeSpectrum(float * data, int width, int windowSize,
double rate, float *out, bool autocorrelation, int windowFunc=3); double rate, float *out, bool autocorrelation,
int windowFunc = eWinFuncHanning);
#endif #endif