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

Added zoom and pan plus fix for bug #884

It started out as just the fix for #884, but it went
a bit further.  Steve had the idea for the zoom and
pan addition, so I added it while I was working on
This commit is contained in:
Leland Lucius 2015-05-03 15:23:33 -05:00
parent 879b9c9931
commit 9212629945
6 changed files with 1231 additions and 941 deletions

View File

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

View File

@ -29,6 +29,9 @@
you need to use doubles.
**********************************************************************/
#ifndef __AUDACITY_FFT_H__
#define __AUDACITY_FFT_H__
/*
Salvo Ventura - November 2006
Added more window functions:
@ -102,6 +105,21 @@ void FFT(int NumSamples,
* 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);
/*
@ -117,3 +135,5 @@ const wxChar *WindowFuncName(int whichFunction);
int NumWindowFuncs();
void DeinitFFT();
#endif

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#include <wx/brush.h>
#include <wx/dcmemory.h>
#include <wx/frame.h>
#include <wx/panel.h>
#include <wx/checkbox.h>
@ -21,8 +22,13 @@
#include <wx/gdicmn.h>
#include <wx/pen.h>
#include <wx/font.h>
#include <wx/scrolbar.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h>
#include <wx/statusbr.h>
#include <wx/textctrl.h>
#include <wx/utils.h>
#include "widgets/Ruler.h"
@ -31,26 +37,11 @@ class wxButton;
class wxChoice;
class FreqWindow;
class FreqGauge;
class TrackList;
class ProgressDialog;
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()
};
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_FREQWINDOW_RECALC, -1);
class SpectrumAnalyst
{
@ -74,32 +65,76 @@ public:
int windowFunc, // see FFT.h for values
int windowSize, double rate,
const float *data, int dataLen,
float *pYMin = 0, float *pYMax = 0, // outputs
ProgressDialog *progress = 0);
float *pYMin = NULL, float *pYMax = NULL, // outputs
FreqGauge *progress = NULL);
const float *GetProcessed() const { return &mProcessed[0]; }
int GetProcessedSize() const { return mProcessed.size() / 2; }
const float *GetProcessed() const;
int GetProcessedSize() const;
float GetProcessedValue(float freq0, float freq1) const;
float FindPeak(float xPos, float *pY) const;
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;
double mRate;
int mWindowSize;
std::vector<float> mProcessed;
};
class FreqWindow:public wxDialog {
public:
FreqWindow(wxWindow * parent, wxWindowID id,
class FreqGauge : public wxStatusBar
{
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);
virtual ~ FreqWindow();
void GetAudio();
void Plot();
virtual bool Show( bool show = true );
private:
void GetAudio();
void PlotMouseEvent(wxMouseEvent & event);
void PlotPaint(wxPaintEvent & event);
@ -107,6 +142,8 @@ class FreqWindow:public wxDialog {
void OnCloseWindow(wxCloseEvent & event);
void OnCloseButton(wxCommandEvent & event);
void OnSize(wxSizeEvent & event);
void OnPanScroller(wxScrollEvent & event);
void OnZoomSlider(wxCommandEvent & event);
void OnAlgChoice(wxCommandEvent & event);
void OnSizeChoice(wxCommandEvent & event);
void OnFuncChoice(wxCommandEvent & event);
@ -114,12 +151,14 @@ class FreqWindow:public wxDialog {
void OnExport(wxCommandEvent & event);
void OnReplot(wxCommandEvent & event);
void OnGridOnOff(wxCommandEvent & event);
void OnRecalc(wxCommandEvent & event);
void SendRecalcEvent();
void Recalc();
void DrawPlot();
void DrawBackground(wxMemoryDC & dc);
private:
float *mBuffer;
bool mDrawGrid;
int mSize;
SpectrumAnalyst::Algorithm mAlg;
@ -134,9 +173,12 @@ class FreqWindow:public wxDialog {
static const int fontSize = 10;
#endif
wxStatusBar *mInfo;
RulerPanel *vRuler;
RulerPanel *hRuler;
FreqPlot *mFreqPlot;
FreqGauge *mProgress;
wxRect mPlotRect;
wxFont mFreqFont;
@ -146,22 +188,16 @@ class FreqWindow:public wxDialog {
wxButton *mCloseButton;
wxButton *mExportButton;
wxButton *mReplotButton;
wxCheckBox *mGridOnOff;
wxChoice *mAlgChoice;
wxChoice *mSizeChoice;
wxChoice *mFuncChoice;
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;
int mDataLen;
@ -180,7 +216,9 @@ class FreqWindow:public wxDialog {
std::auto_ptr<SpectrumAnalyst> mAnalyst;
DECLARE_EVENT_TABLE()
DECLARE_EVENT_TABLE();
friend class FreqPlot;
};
#endif

View File

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

View File

@ -12,6 +12,7 @@
#define __AUDACITY_SPECTRUM__
#include "WaveTrack.h"
#include "FFT.h"
/*
This function computes the power (mean square amplitude) as
@ -22,6 +23,7 @@
*/
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