1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-24 00:18:07 +02:00

Added Norm C's Scientific Filter.

This commit is contained in:
james.k.crook@gmail.com 2013-10-02 10:32:41 +00:00
parent 856c51e6a6
commit 2543ea7897
7 changed files with 1678 additions and 0 deletions

View File

@ -151,6 +151,7 @@ OBJS = \
effects/Amplify.o \
effects/AutoDuck.o \
effects/BassTreble.o \
effects/Biquad.o \
effects/ChangePitch.o \
effects/ChangeSpeed.o \
effects/ChangeTempo.o \
@ -173,6 +174,7 @@ OBJS = \
effects/Repeat.o \
effects/Reverb.o \
effects/Reverse.o \
effects/ScienFilter.o \
effects/Silence.o \
effects/StereoToMono.o \
effects/TimeWarper.o \

51
src/effects/Biquad.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "Biquad.h"
#define square(a) ((a)*(a))
void Biquad_Process (BiquadStruct* pBQ, int iNumSamples)
{
float* pfIn = pBQ->pfIn;
float* pfOut = pBQ->pfOut;
float fPrevIn = pBQ->fPrevIn;
float fPrevPrevIn = pBQ->fPrevPrevIn;
float fPrevOut = pBQ->fPrevOut;
float fPrevPrevOut = pBQ->fPrevPrevOut;
for (int i = 0; i < iNumSamples; i++)
{
float fIn = *pfIn++;
*pfOut = fIn * pBQ->fNumerCoeffs [0] +
fPrevIn * pBQ->fNumerCoeffs [1] +
fPrevPrevIn * pBQ->fNumerCoeffs [2] -
fPrevOut * pBQ->fDenomCoeffs [0] -
fPrevPrevOut * pBQ->fDenomCoeffs [1];
fPrevPrevIn = fPrevIn;
fPrevIn = fIn;
fPrevPrevOut = fPrevOut;
fPrevOut = *pfOut++;
}
pBQ->fPrevIn = fPrevIn;
pBQ->fPrevPrevIn = fPrevPrevIn;
pBQ->fPrevOut = fPrevOut;
pBQ->fPrevPrevOut = fPrevPrevOut;
}
void ComplexDiv (float fNumerR, float fNumerI, float fDenomR, float fDenomI, float* pfQuotientR, float* pfQuotientI)
{
float fDenom = square(fDenomR) + square(fDenomI);
*pfQuotientR = (fNumerR * fDenomR + fNumerI * fDenomI) / fDenom;
*pfQuotientI = (fNumerI * fDenomR - fNumerR * fDenomI) / fDenom;
}
bool BilinTransform (float fSX, float fSY, float* pfZX, float* pfZY)
{
float fDenom = square (1 - fSX) + square (fSY);
*pfZX = (1 - square (fSX) - square (fSY)) / fDenom;
*pfZY = 2 * fSY / fDenom;
return true;
}
float Calc2D_DistSqr (float fX1, float fY1, float fX2, float fY2)
{
return square (fX1 - fX2) + square (fY1 - fY2);
}

18
src/effects/Biquad.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef __BIQUAD_H__
#define __BIQUAD_H__
typedef struct {
float* pfIn;
float* pfOut;
float fNumerCoeffs [3]; // B0 B1 B2
float fDenomCoeffs [2]; // A1 A2
float fPrevIn;
float fPrevPrevIn;
float fPrevOut;
float fPrevPrevOut;
} BiquadStruct;
void Biquad_Process (BiquadStruct* pBQ, int iNumSamples);
void ComplexDiv (float fNumerR, float fNumerI, float fDenomR, float fDenomI, float* pfQuotientR, float* pfQuotientI);
bool BilinTransform (float fSX, float fSY, float* pfZX, float* pfZY);
float Calc2D_DistSqr (float fX1, float fY1, float fX2, float fY2);
#endif

View File

@ -38,6 +38,7 @@
#include "Reverb.h"
#include "Reverse.h"
#include "Silence.h"
#include "ScienFilter.h"
#include "StereoToMono.h"
#ifdef USE_SBSMS
#include "TimeScale.h"
@ -263,6 +264,7 @@ void LoadEffects()
em.RegisterEffect(new EffectRepeat());
em.RegisterEffect(new EffectReverb());
em.RegisterEffect(new EffectReverse());
em.RegisterEffect(new EffectScienFilter());
em.RegisterEffect(new EffectStereoToMono(), HIDDEN_EFFECT);// NOT in normal effects list.
em.RegisterEffect(new EffectTruncSilence(), SIMPLE_EFFECT);
#ifdef USE_SBSMS

1248
src/effects/ScienFilter.cpp Normal file

File diff suppressed because it is too large Load Diff

341
src/effects/ScienFilter.h Normal file
View File

@ -0,0 +1,341 @@
/**********************************************************************
Audacity: A Digital Audio Editor
EffectScienFilter.h
Mitch Golden
Vaughan Johnson (Preview)
***********************************************************************/
#ifndef __AUDACITY_EFFECT_SCIENFILTER__
#define __AUDACITY_EFFECT_SCIENFILTER__
#define MAX_FILTER_ORDER 10
#include <wx/button.h>
#include <wx/panel.h>
#include <wx/dialog.h>
#include <wx/dynarray.h>
#include <wx/intl.h>
#include <wx/stattext.h>
#include <wx/slider.h>
#include <wx/sizer.h>
#include <wx/string.h>
#include <wx/bitmap.h>
#include <wx/choice.h>
#include <wx/checkbox.h>
#if wxUSE_ACCESSIBILITY
#include <wx/access.h>
#endif
#include "Effect.h"
#include "../WaveTrack.h"
#include "../widgets/Ruler.h"
#include "Biquad.h"
class ScienFilterDialog;
class EffectScienFilter: public Effect {
public:
EffectScienFilter();
virtual ~EffectScienFilter();
virtual wxString GetEffectName() {
return wxString(_("Scientific Filter..."));
}
virtual std::set<wxString> GetEffectCategories() {
std::set<wxString> result;
result.insert(wxT("http://lv2plug.in/ns/lv2core#EQPlugin"));
return result;
}
virtual wxString GetEffectIdentifier() {
return wxString(wxT("Scientific Filter"));
}
virtual wxString GetEffectAction() {
return wxString(_("Performing ScienFilter"));
}
virtual bool Init();
virtual bool PromptUser();
virtual bool DontPromptUser();
virtual bool TransferParameters( Shuttle & shuttle );
bool CalcFilterCoeffs (void);
virtual bool Process();
// Lowest frequency to display in response graph
enum {loFreqI=20};
private:
bool ProcessOne(int count, WaveTrack * t,
sampleCount start, sampleCount len);
void Filter(sampleCount len,
float *buffer);
void ReadPrefs();
//int mM;
float mCutoff;
int mOrder;
float mRipple;
float mStopbandRipple;
int mFilterType; // Butterworth etc.
int mFilterSubtype; // lowpass, highpass
BiquadStruct* mpBiquad[5]; // MAX_ORDER/2
double mdBMax;
double mdBMin;
bool mPrompting;
bool mEditingBatchParams;
public:
friend class ScienFilterDialog;
friend class ScienFilterPanel;
};
class ScienFilterPanel: public wxPanel
{
public:
ScienFilterPanel( double loFreq, double hiFreq,
ScienFilterDialog *parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize);
~ScienFilterPanel();
#if 0
Needed only if user can draw in the graph
void OnMouseEvent(wxMouseEvent & event);
void OnCaptureLost(wxMouseCaptureLostEvent & event);
#endif
void OnPaint(wxPaintEvent & event);
void OnSize (wxSizeEvent & event);
// We don't need or want to accept focus.
bool AcceptsFocus() const { return false; }
float dBMax;
float dBMin;
private:
wxBitmap *mBitmap;
wxRect mEnvRect;
ScienFilterDialog *mParent;
int mWidth;
int mHeight;
double mLoFreq;
double mHiFreq;
DECLARE_EVENT_TABLE()
};
// WDR: class declarations
//----------------------------------------------------------------------------
// ScienFilterDialog
//----------------------------------------------------------------------------
class ScienFilterDialog: public wxDialog //, public XMLTagHandler
{
public:
// constructors and destructors
ScienFilterDialog(EffectScienFilter * effect,
double loFreq, double hiFreq,
//long windowSize, wxString CurveName, bool disallowCustom,
wxWindow *parent, wxWindowID id,
const wxString &title,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE );
~ScienFilterDialog();
// WDR: method declarations for ScienFilterDialog
virtual bool Validate();
virtual bool TransferDataToWindow();
virtual bool TransferGraphLimitsFromWindow();
virtual bool CalcFilter(EffectScienFilter* effect);
float FilterMagnAtFreq (float Freq);
wxChoice* mFilterTypeCtl;
wxChoice* mFilterSubTypeCtl;
wxChoice* mFilterOrderCtl;
float Cutoff;
int Order;
float Ripple;
float StopbandRipple;
int FilterType; // Butterworth etc.
int FilterSubtype; // lowpass, highpass
float dBMin;
float dBMax;
int interp;
RulerPanel *dBRuler;
RulerPanel *freqRuler;
private:
void MakeScienFilterDialog();
void Finish(bool ok);
private:
// WDR: member variable declarations for ScienFilterDialog
enum
{
ID_FILTERPANEL = 10000,
ID_DBMAX,
ID_DBMIN,
ID_FILTER_TYPE,
ID_FILTER_SUBTYPE,
ID_FILTER_ORDER,
ID_RIPPLE,
ID_CUTOFF,
ID_STOPBAND_RIPPLE
};
private:
// WDR: handler declarations for ScienFilterDialog
void OnPaint( wxPaintEvent &event );
void OnSize( wxSizeEvent &event );
void OnErase( wxEraseEvent &event );
void OnSlider( wxCommandEvent &event );
void OnOrder( wxCommandEvent &event );
void OnCutoff( wxCommandEvent &event );
void OnRipple( wxCommandEvent &event );
void OnStopbandRipple( wxCommandEvent &event );
void OnFilterType( wxCommandEvent &event );
void OnFilterSubtype( wxCommandEvent &event );
void OnSliderDBMAX( wxCommandEvent &event );
void OnSliderDBMIN( wxCommandEvent &event );
void OnPreview(wxCommandEvent &event);
void OnOk( wxCommandEvent &event );
void OnCancel( wxCommandEvent &event );
void EnableDisableRippleCtl (int FilterType);
private:
EffectScienFilter * m_pEffect;
double mLoFreq;
double mNyquist;
ScienFilterPanel *mPanel;
wxSlider *dBMinSlider;
wxSlider *dBMaxSlider;
wxBoxSizer *szrV;
wxFlexGridSizer *szr3;
wxBoxSizer *szr4;
wxBoxSizer *szr2;
wxFlexGridSizer *szr1;
wxSize size;
wxTextCtrl* mRippleCtl;
wxTextCtrl* mStopbandRippleCtl;
wxTextCtrl* mCutoffCtl;
private:
DECLARE_EVENT_TABLE()
};
#if wxUSE_ACCESSIBILITY
class SliderAx: public wxWindowAccessible
{
public:
SliderAx(wxWindow * window, wxString fmt);
virtual ~ SliderAx();
// Retrieves the address of an IDispatch interface for the specified child.
// All objects must support this property.
virtual wxAccStatus GetChild( int childId, wxAccessible** child );
// Gets the number of children.
virtual wxAccStatus GetChildCount(int* childCount);
// Gets the default action for this object (0) or > 0 (the action for a child).
// Return wxACC_OK even if there is no action. actionName is the action, or the empty
// string if there is no action.
// The retrieved string describes the action that is performed on an object,
// not what the object does as a result. For example, a toolbar button that prints
// a document has a default action of "Press" rather than "Prints the current document."
virtual wxAccStatus GetDefaultAction( int childId, wxString *actionName );
// Returns the description for this object or a child.
virtual wxAccStatus GetDescription( int childId, wxString *description );
// Gets the window with the keyboard focus.
// If childId is 0 and child is NULL, no object in
// this subhierarchy has the focus.
// If this object has the focus, child should be 'this'.
virtual wxAccStatus GetFocus( int *childId, wxAccessible **child );
// Returns help text for this object or a child, similar to tooltip text.
virtual wxAccStatus GetHelpText( int childId, wxString *helpText );
// Returns the keyboard shortcut for this object or child.
// Return e.g. ALT+K
virtual wxAccStatus GetKeyboardShortcut( int childId, wxString *shortcut );
// Returns the rectangle for this object (id = 0) or a child element (id > 0).
// rect is in screen coordinates.
virtual wxAccStatus GetLocation( wxRect& rect, int elementId );
// Gets the name of the specified object.
virtual wxAccStatus GetName( int childId, wxString *name );
// Returns a role constant.
virtual wxAccStatus GetRole( int childId, wxAccRole *role );
// Gets a variant representing the selected children
// of this object.
// Acceptable values:
// - a null variant (IsNull() returns TRUE)
// - a list variant (GetType() == wxT("list"))
// - an integer representing the selected child element,
// or 0 if this object is selected (GetType() == wxT("long"))
// - a "void*" pointer to a wxAccessible child object
virtual wxAccStatus GetSelections( wxVariant *selections );
// Returns a state constant.
virtual wxAccStatus GetState(int childId, long* state);
// Returns a localized string representing the value for the object
// or child.
virtual wxAccStatus GetValue(int childId, wxString* strValue);
private:
wxWindow *mParent;
wxString mFmt;
};
#endif // wxUSE_ACCESSIBILITY
#endif
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
// version control system. Please do not modify past this point.
//
// Local Variables:
// c-basic-offset: 3
// indent-tabs-mode: nil
// End:
//
// vim: et sts=3 sw=3
// arch-tag: 309f263d-748c-4dc0-9e68-9e86732890bb

View File

@ -1099,6 +1099,14 @@
RelativePath="..\..\..\src\effects\BassTreble.h"
>
</File>
<File
RelativePath="..\..\..\src\effects\Biquad.cpp"
>
</File>
<File
RelativePath="..\..\..\src\effects\Biquad.h"
>
</File>
<File
RelativePath="..\..\..\src\effects\ChangePitch.cpp"
>
@ -1327,6 +1335,14 @@
RelativePath="..\..\..\src\effects\SBSMSEffect.h"
>
</File>
<File
RelativePath="..\..\..\src\effects\ScienFilter.cpp"
>
</File>
<File
RelativePath="..\..\..\src\effects\ScienFilter.h"
>
</File>
<File
RelativePath="..\..\..\src\effects\ScoreAlignDialog.cpp"
>