Audacity  2.2.2
Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
EffectScienFilter Class Referencefinal

An Effect that applies 'classical' IIR filters. More...

#include <ScienFilter.h>

Inheritance diagram for EffectScienFilter:
Effect EffectClientInterface EffectUIClientInterface EffectHostInterface EffectDefinitionInterface ConfigClientInterface IdentInterface ParamsInterface

Public Member Functions

 EffectScienFilter ()
 
virtual ~EffectScienFilter ()
 
IdentInterfaceSymbol GetSymbol () override
 
wxString GetDescription () override
 
wxString ManualPage () override
 
EffectType GetType () override
 
unsigned GetAudioInCount () override
 
unsigned GetAudioOutCount () override
 
bool ProcessInitialize (sampleCount totalLen, ChannelNames chanMap=NULL) override
 
size_t ProcessBlock (float **inBlock, float **outBlock, size_t blockLen) override
 
bool DefineParams (ShuttleParams &S) override
 
bool GetAutomationParameters (CommandParameters &parms) override
 
bool SetAutomationParameters (CommandParameters &parms) override
 
bool Startup () override
 
bool Init () override
 
void PopulateOrExchange (ShuttleGui &S) override
 
bool TransferDataToWindow () override
 
bool TransferDataFromWindow () override
 
- Public Member Functions inherited from Effect
 Effect ()
 
virtual ~Effect ()
 
wxString GetPath () override
 
IdentInterfaceSymbol GetVendor () override
 
wxString GetVersion () override
 
IdentInterfaceSymbol GetFamilyId () override
 
bool IsInteractive () override
 
bool IsDefault () override
 
bool IsLegacy () override
 
bool SupportsRealtime () override
 
bool SupportsAutomation () override
 
bool SetHost (EffectHostInterface *host) override
 
int GetMidiInCount () override
 
int GetMidiOutCount () override
 
sampleCount GetLatency () override
 
size_t GetTailSize () override
 
void SetSampleRate (double rate) override
 
size_t SetBlockSize (size_t maxBlockSize) override
 
bool IsReady () override
 
bool ProcessFinalize () override
 
bool RealtimeInitialize () override
 
bool RealtimeAddProcessor (unsigned numChannels, float sampleRate) override
 
bool RealtimeFinalize () override
 
bool RealtimeSuspend () override
 
bool RealtimeResume () override
 
bool RealtimeProcessStart () override
 
size_t RealtimeProcess (int group, float **inbuf, float **outbuf, size_t numSamples) override
 
bool RealtimeProcessEnd () override
 
bool ShowInterface (wxWindow *parent, bool forceModal=false) override
 
bool LoadUserPreset (const wxString &name) override
 
bool SaveUserPreset (const wxString &name) override
 
wxArrayString GetFactoryPresets () override
 
bool LoadFactoryPreset (int id) override
 
bool LoadFactoryDefaults () override
 
void SetHostUI (EffectUIHostInterface *host) override
 
bool PopulateUI (wxWindow *parent) override
 
bool IsGraphicalUI () override
 
bool ValidateUI () override
 
bool HideUI () override
 
bool CloseUI () override
 
bool CanExportPresets () override
 
void ExportPresets () override
 
void ImportPresets () override
 
bool HasOptions () override
 
void ShowOptions () override
 
double GetDefaultDuration () override
 
double GetDuration () override
 
NumericFormatId GetDurationFormat () override
 
virtual NumericFormatId GetSelectionFormat ()
 
void SetDuration (double duration) override
 
bool Apply () override
 
void Preview () override
 
wxDialog * CreateUI (wxWindow *parent, EffectUIClientInterface *client) override
 
wxString GetUserPresetsGroup (const wxString &name) override
 
wxString GetCurrentSettingsGroup () override
 
wxString GetFactoryDefaultsGroup () override
 
virtual wxString GetSavedStateGroup ()
 
bool HasSharedConfigGroup (const wxString &group) override
 
bool GetSharedConfigSubgroups (const wxString &group, wxArrayString &subgroups) override
 
bool GetSharedConfig (const wxString &group, const wxString &key, wxString &value, const wxString &defval=wxEmptyString) override
 
bool GetSharedConfig (const wxString &group, const wxString &key, int &value, int defval=0) override
 
bool GetSharedConfig (const wxString &group, const wxString &key, bool &value, bool defval=false) override
 
bool GetSharedConfig (const wxString &group, const wxString &key, float &value, float defval=0.0) override
 
bool GetSharedConfig (const wxString &group, const wxString &key, double &value, double defval=0.0) override
 
bool SetSharedConfig (const wxString &group, const wxString &key, const wxString &value) override
 
bool SetSharedConfig (const wxString &group, const wxString &key, const int &value) override
 
bool SetSharedConfig (const wxString &group, const wxString &key, const bool &value) override
 
bool SetSharedConfig (const wxString &group, const wxString &key, const float &value) override
 
bool SetSharedConfig (const wxString &group, const wxString &key, const double &value) override
 
bool RemoveSharedConfigSubgroup (const wxString &group) override
 
bool RemoveSharedConfig (const wxString &group, const wxString &key) override
 
bool HasPrivateConfigGroup (const wxString &group) override
 
bool GetPrivateConfigSubgroups (const wxString &group, wxArrayString &subgroups) override
 
bool GetPrivateConfig (const wxString &group, const wxString &key, wxString &value, const wxString &defval=wxEmptyString) override
 
bool GetPrivateConfig (const wxString &group, const wxString &key, int &value, int defval=0) override
 
bool GetPrivateConfig (const wxString &group, const wxString &key, bool &value, bool defval=false) override
 
bool GetPrivateConfig (const wxString &group, const wxString &key, float &value, float defval=0.0) override
 
bool GetPrivateConfig (const wxString &group, const wxString &key, double &value, double defval=0.0) override
 
bool SetPrivateConfig (const wxString &group, const wxString &key, const wxString &value) override
 
bool SetPrivateConfig (const wxString &group, const wxString &key, const int &value) override
 
bool SetPrivateConfig (const wxString &group, const wxString &key, const bool &value) override
 
bool SetPrivateConfig (const wxString &group, const wxString &key, const float &value) override
 
bool SetPrivateConfig (const wxString &group, const wxString &key, const double &value) override
 
bool RemovePrivateConfigSubgroup (const wxString &group) override
 
bool RemovePrivateConfig (const wxString &group, const wxString &key) override
 
virtual PluginID GetID ()
 
virtual bool Startup (EffectClientInterface *client)
 
virtual bool GetAutomationParameters (wxString &parms)
 
virtual bool SetAutomationParameters (const wxString &parms)
 
virtual wxArrayString GetUserPresets ()
 
virtual bool HasCurrentSettings ()
 
virtual bool HasFactoryDefaults ()
 
virtual wxString GetPreset (wxWindow *parent, const wxString &parms)
 
virtual wxString HelpPage ()
 
virtual bool IsBatchProcessing ()
 
virtual void SetBatchProcessing (bool start)
 
void SetPresetParameters (const wxArrayString *Names, const wxArrayString *Values)
 
bool DoEffect (wxWindow *parent, double projectRate, TrackList *list, TrackFactory *factory, SelectedRegion *selectedRegion, bool shouldPrompt=true)
 
bool Delegate (Effect &delegate, wxWindow *parent, bool shouldPrompt)
 
bool RealtimeAddProcessor (int group, unsigned chans, float rate)
 
size_t RealtimeProcess (int group, unsigned chans, float **inbuf, float **outbuf, size_t numSamples)
 
bool IsRealtimeActive ()
 
virtual bool IsHidden ()
 
int MessageBox (const wxString &message, long style=DefaultMessageBoxStyle, const wxString &titleStr=wxString{})
 
- Public Member Functions inherited from EffectClientInterface
virtual ~EffectClientInterface ()
 
- Public Member Functions inherited from EffectDefinitionInterface
virtual ~EffectDefinitionInterface ()
 
- Public Member Functions inherited from IdentInterface
virtual ~IdentInterface ()
 
const wxString & GetTranslatedName ()
 
- Public Member Functions inherited from ParamsInterface
virtual ~ParamsInterface ()
 
virtual bool DefineParams (ShuttleParams &WXUNUSED(S))
 
- Public Member Functions inherited from EffectUIClientInterface
virtual ~EffectUIClientInterface ()
 
- Public Member Functions inherited from EffectHostInterface
virtual ~EffectHostInterface ()
 
- Public Member Functions inherited from ConfigClientInterface
virtual ~ConfigClientInterface ()
 

Private Member Functions

bool TransferGraphLimitsFromWindow ()
 
bool CalcFilter ()
 
double ChebyPoly (int Order, double NormFreq)
 
float FilterMagnAtFreq (float Freq)
 
bool CalcFilterCoeffs (void)
 
void EnableDisableRippleCtl (int FilterType)
 
void OnSize (wxSizeEvent &evt)
 
void OnSlider (wxCommandEvent &evt)
 
void OnOrder (wxCommandEvent &evt)
 
void OnCutoff (wxCommandEvent &evt)
 
void OnRipple (wxCommandEvent &evt)
 
void OnStopbandRipple (wxCommandEvent &evt)
 
void OnFilterType (wxCommandEvent &evt)
 
void OnFilterSubtype (wxCommandEvent &evt)
 
void OnSliderDBMAX (wxCommandEvent &evt)
 
void OnSliderDBMIN (wxCommandEvent &evt)
 

Private Attributes

float mCutoff
 
float mRipple
 
float mStopbandRipple
 
int mFilterType
 
int mFilterSubtype
 
int mOrder
 
int mOrderIndex
 
ArrayOf< BiquadStructmpBiquad
 
double mdBMax
 
double mdBMin
 
bool mEditingBatchParams
 
double mLoFreq
 
double mNyquist
 
EffectScienFilterPanelmPanel
 
wxSlider * mdBMinSlider
 
wxSlider * mdBMaxSlider
 
wxStaticText * mRippleCtlP
 
wxTextCtrl * mRippleCtl
 
wxStaticText * mRippleCtlU
 
wxTextCtrl * mCutoffCtl
 
wxStaticText * mStopbandRippleCtlP
 
wxTextCtrl * mStopbandRippleCtl
 
wxStaticText * mStopbandRippleCtlU
 
wxChoice * mFilterTypeCtl
 
wxChoice * mFilterSubTypeCtl
 
wxChoice * mFilterOrderCtl
 
RulerPanelmdBRuler
 
RulerPanelmfreqRuler
 

Friends

class EffectScienFilterPanel
 

Additional Inherited Members

- Public Types inherited from Effect
enum  : long { DefaultMessageBoxStyle = wxOK | wxCENTRE }
 
- Protected Member Functions inherited from Effect
virtual bool PromptUser (wxWindow *parent)
 
virtual bool CheckWhetherSkipEffect ()
 
virtual bool Process ()
 
virtual bool ProcessPass ()
 
virtual bool InitPass1 ()
 
virtual bool InitPass2 ()
 
virtual int GetPass ()
 
virtual void End ()
 
virtual double CalcPreviewInputLength (double previewLength)
 
virtual void Preview (bool dryOnly)
 
virtual bool EnableApply (bool enable=true)
 
virtual bool EnablePreview (bool enable=true)
 
virtual void EnableDebug (bool enable=true)
 
bool TotalProgress (double frac)
 
bool TrackProgress (int whichTrack, double frac, const wxString &=wxEmptyString)
 
bool TrackGroupProgress (int whichGroup, double frac, const wxString &=wxEmptyString)
 
int GetNumWaveTracks ()
 
int GetNumWaveGroups ()
 
void GetSamples (const WaveTrack *track, sampleCount *start, sampleCount *len)
 
void SetLinearEffectFlag (bool linearEffectFlag)
 
void SetPreviewFullSelectionFlag (bool previewDurationFlag)
 
bool IsPreviewing ()
 
void IncludeNotSelectedPreviewTracks (bool includeNotSelected)
 
void CopyInputTracks ()
 
void CopyInputTracks (int trackType)
 
std::shared_ptr
< AddedAnalysisTrack
AddAnalysisTrack (const wxString &name=wxString())
 
ModifiedAnalysisTrack ModifyAnalysisTrack (const LabelTrack *pOrigTrack, const wxString &name=wxString())
 
void ReplaceProcessedTracks (const bool bGoodResult)
 
TrackAddToOutputTracks (std::unique_ptr< Track > &&t)
 
TrackListinputTracks () const
 
- Protected Attributes inherited from Effect
ProgressDialogmProgress
 
double mProjectRate
 
double mSampleRate
 
SelectedRegionmpSelectedRegion {}
 
TrackFactorymFactory
 
std::shared_ptr< TrackListmOutputTracks
 
double mT0
 
double mT1
 
double mF0
 
double mF1
 
wxArrayString mPresetNames
 
wxArrayString mPresetValues
 
int mPass
 
wxDialog * mUIDialog
 
wxWindow * mUIParent
 
int mUIResultID
 
sampleCount mSampleCnt
 
int mOutputTracksType
 

Detailed Description

An Effect that applies 'classical' IIR filters.

Performs IIR filtering that emulates analog filters, specifically Butterworth, Chebyshev Type I and Type II. Highpass and lowpass filters are supported, as are filter orders from 1 to 10.

The filter is applied using biquads

Definition at line 38 of file ScienFilter.h.

Constructor & Destructor Documentation

EffectScienFilter::EffectScienFilter ( )

Definition at line 156 of file ScienFilter.cpp.

157 : mpBiquad{ size_t( MAX_Order / 2 ), true }
158 {
159  mOrder = DEF_Order;
160  mFilterType = DEF_Type;
161  mFilterSubtype = DEF_Subtype;
162  mCutoff = DEF_Cutoff;
163  mRipple = DEF_Passband;
164  mStopbandRipple = DEF_Stopband;
165 
166  SetLinearEffectFlag(true);
167 
168  mOrderIndex = mOrder - 1;
169 
170  mdBMin = -30.0;
171  mdBMax = 30.0;
172 
173  mLoFreq = 20; // Lowest frequency to display in response graph
174  mNyquist = 44100.0 / 2.0; // only used during initialization, updated when effect is used
175 }
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: Effect.cpp:1961
ArrayOf< BiquadStruct > mpBiquad
Definition: ScienFilter.h:105
EffectScienFilter::~EffectScienFilter ( )
virtual

Definition at line 177 of file ScienFilter.cpp.

178 {
179 }

Member Function Documentation

bool EffectScienFilter::CalcFilter ( )
private

Definition at line 618 of file ScienFilter.cpp.

References BilinTransform(), Calc2D_DistSqr(), ComplexDiv(), DB_TO_LINEAR(), kButterworth, kChebyshevTypeI, kChebyshevTypeII, kLowPass, mCutoff, mFilterSubtype, mFilterType, mNyquist, mOrder, mpBiquad, mRipple, mStopbandRipple, PI, and square.

Referenced by SetAutomationParameters(), and TransferDataFromWindow().

619 {
620  // Set up the coefficients in all the biquads
621  float fNorm = mCutoff / mNyquist;
622  if (fNorm >= 0.9999)
623  fNorm = 0.9999F;
624  float fC = tan (PI * fNorm / 2);
625  float fDCPoleDistSqr = 1.0F;
626  float fZPoleX, fZPoleY;
627  float fZZeroX, fZZeroY;
628  float beta = cos (fNorm*PI);
629  switch (mFilterType)
630  {
631  case kButterworth: // Butterworth
632  if ((mOrder & 1) == 0)
633  {
634  // Even order
635  for (int iPair = 0; iPair < mOrder/2; iPair++)
636  {
637  float fSPoleX = fC * cos (PI - (iPair + 0.5) * PI / mOrder);
638  float fSPoleY = fC * sin (PI - (iPair + 0.5) * PI / mOrder);
639  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
640  mpBiquad[iPair].fNumerCoeffs [0] = 1;
641  if (mFilterSubtype == kLowPass) // LOWPASS
642  mpBiquad[iPair].fNumerCoeffs [1] = 2;
643  else
644  mpBiquad[iPair].fNumerCoeffs [1] = -2;
645  mpBiquad[iPair].fNumerCoeffs [2] = 1;
646  mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX;
647  mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY);
648  if (mFilterSubtype == kLowPass) // LOWPASS
649  fDCPoleDistSqr *= Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY);
650  else
651  fDCPoleDistSqr *= Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist
652  }
653  }
654  else
655  {
656  // Odd order - first do the 1st-order section
657  float fSPoleX = -fC;
658  float fSPoleY = 0;
659  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
660  mpBiquad[0].fNumerCoeffs [0] = 1;
661  if (mFilterSubtype == kLowPass) // LOWPASS
662  mpBiquad[0].fNumerCoeffs [1] = 1;
663  else
664  mpBiquad[0].fNumerCoeffs [1] = -1;
665  mpBiquad[0].fNumerCoeffs [2] = 0;
666  mpBiquad[0].fDenomCoeffs [0] = -fZPoleX;
667  mpBiquad[0].fDenomCoeffs [1] = 0;
668  if (mFilterSubtype == kLowPass) // LOWPASS
669  fDCPoleDistSqr = 1 - fZPoleX;
670  else
671  fDCPoleDistSqr = fZPoleX + 1; // dist from Nyquist
672  for (int iPair = 1; iPair <= mOrder/2; iPair++)
673  {
674  float fSPoleX = fC * cos (PI - iPair * PI / mOrder);
675  float fSPoleY = fC * sin (PI - iPair * PI / mOrder);
676  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
677  mpBiquad[iPair].fNumerCoeffs [0] = 1;
678  if (mFilterSubtype == kLowPass) // LOWPASS
679  mpBiquad[iPair].fNumerCoeffs [1] = 2;
680  else
681  mpBiquad[iPair].fNumerCoeffs [1] = -2;
682  mpBiquad[iPair].fNumerCoeffs [2] = 1;
683  mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX;
684  mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY);
685  if (mFilterSubtype == kLowPass) // LOWPASS
686  fDCPoleDistSqr *= Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY);
687  else
688  fDCPoleDistSqr *= Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist
689  }
690  }
691  mpBiquad[0].fNumerCoeffs [0] *= fDCPoleDistSqr / (1 << mOrder); // mult by DC dist from poles, divide by dist from zeroes
692  mpBiquad[0].fNumerCoeffs [1] *= fDCPoleDistSqr / (1 << mOrder);
693  mpBiquad[0].fNumerCoeffs [2] *= fDCPoleDistSqr / (1 << mOrder);
694  break;
695 
696  case kChebyshevTypeI: // Chebyshev Type 1
697  double eps; eps = sqrt (pow (10.0, wxMax(0.001, mRipple) / 10.0) - 1);
698  double a; a = log (1 / eps + sqrt(1 / square(eps) + 1)) / mOrder;
699  // Assume even order to start
700  for (int iPair = 0; iPair < mOrder/2; iPair++)
701  {
702  float fSPoleX = -fC * sinh (a) * sin ((2*iPair + 1) * PI / (2 * mOrder));
703  float fSPoleY = fC * cosh (a) * cos ((2*iPair + 1) * PI / (2 * mOrder));
704  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
705  if (mFilterSubtype == kLowPass) // LOWPASS
706  {
707  fZZeroX = -1;
708  fDCPoleDistSqr = Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY);
709  fDCPoleDistSqr /= 2*2; // dist from zero at Nyquist
710  }
711  else
712  {
713  // Highpass - do the digital LP->HP transform on the poles and zeroes
714  ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -beta * fZPoleY, &fZPoleX, &fZPoleY);
715  fZZeroX = 1;
716  fDCPoleDistSqr = Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist
717  fDCPoleDistSqr /= 2*2; // dist from zero at Nyquist
718  }
719  mpBiquad[iPair].fNumerCoeffs [0] = fDCPoleDistSqr;
720  mpBiquad[iPair].fNumerCoeffs [1] = -2 * fZZeroX * fDCPoleDistSqr;
721  mpBiquad[iPair].fNumerCoeffs [2] = fDCPoleDistSqr;
722  mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX;
723  mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY);
724  }
725  if ((mOrder & 1) == 0)
726  {
727  float fTemp = DB_TO_LINEAR(-wxMax(0.001, mRipple)); // at DC the response is down R dB (for even-order)
728  mpBiquad[0].fNumerCoeffs [0] *= fTemp;
729  mpBiquad[0].fNumerCoeffs [1] *= fTemp;
730  mpBiquad[0].fNumerCoeffs [2] *= fTemp;
731  }
732  else
733  {
734  // Odd order - now do the 1st-order section
735  float fSPoleX = -fC * sinh (a);
736  float fSPoleY = 0;
737  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
738  if (mFilterSubtype == kLowPass) // LOWPASS
739  {
740  fZZeroX = -1;
741  fDCPoleDistSqr = sqrt(Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY));
742  fDCPoleDistSqr /= 2; // dist from zero at Nyquist
743  }
744  else
745  {
746  // Highpass - do the digital LP->HP transform on the poles and zeroes
747  ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -beta * fZPoleY, &fZPoleX, &fZPoleY);
748  fZZeroX = 1;
749  fDCPoleDistSqr = sqrt(Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY)); // distance from Nyquist
750  fDCPoleDistSqr /= 2; // dist from zero at Nyquist
751  }
752  mpBiquad[(mOrder-1)/2].fNumerCoeffs [0] = fDCPoleDistSqr;
753  mpBiquad[(mOrder-1)/2].fNumerCoeffs [1] = -fZZeroX * fDCPoleDistSqr;
754  mpBiquad[(mOrder-1)/2].fNumerCoeffs [2] = 0;
755  mpBiquad[(mOrder-1)/2].fDenomCoeffs [0] = -fZPoleX;
756  mpBiquad[(mOrder-1)/2].fDenomCoeffs [1] = 0;
757  }
758  break;
759 
760  case kChebyshevTypeII: // Chebyshev Type 2
761  float fSZeroX, fSZeroY;
762  float fSPoleX, fSPoleY;
763  eps = DB_TO_LINEAR(-wxMax(0.001, mStopbandRipple));
764  a = log (1 / eps + sqrt(1 / square(eps) + 1)) / mOrder;
765 
766  // Assume even order
767  for (int iPair = 0; iPair < mOrder/2; iPair++)
768  {
769  ComplexDiv (fC, 0, -sinh (a) * sin ((2*iPair + 1) * PI / (2 * mOrder)),
770  cosh (a) * cos ((2*iPair + 1) * PI / (2 * mOrder)),
771  &fSPoleX, &fSPoleY);
772  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
773  fSZeroX = 0;
774  fSZeroY = fC / cos (((2 * iPair) + 1) * PI / (2 * mOrder));
775  BilinTransform (fSZeroX, fSZeroY, &fZZeroX, &fZZeroY);
776 
777  if (mFilterSubtype == kLowPass) // LOWPASS
778  {
779  fDCPoleDistSqr = Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY);
780  fDCPoleDistSqr /= Calc2D_DistSqr (1, 0, fZZeroX, fZZeroY);
781  }
782  else
783  {
784  // Highpass - do the digital LP->HP transform on the poles and zeroes
785  ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -beta * fZPoleY, &fZPoleX, &fZPoleY);
786  ComplexDiv (beta - fZZeroX, -fZZeroY, 1 - beta * fZZeroX, -beta * fZZeroY, &fZZeroX, &fZZeroY);
787  fDCPoleDistSqr = Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist
788  fDCPoleDistSqr /= Calc2D_DistSqr (-1, 0, fZZeroX, fZZeroY);
789  }
790  mpBiquad[iPair].fNumerCoeffs [0] = fDCPoleDistSqr;
791  mpBiquad[iPair].fNumerCoeffs [1] = -2 * fZZeroX * fDCPoleDistSqr;
792  mpBiquad[iPair].fNumerCoeffs [2] = (square(fZZeroX) + square(fZZeroY)) * fDCPoleDistSqr;
793  mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX;
794  mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY);
795  }
796  // Now, if it's odd order, we have one more to do
797  if (mOrder & 1)
798  {
799  int iPair = (mOrder-1)/2; // we'll do it as a biquad, but it's just first-order
800  ComplexDiv (fC, 0, -sinh (a) * sin ((2*iPair + 1) * PI / (2 * mOrder)),
801  cosh (a) * cos ((2*iPair + 1) * PI / (2 * mOrder)),
802  &fSPoleX, &fSPoleY);
803  BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY);
804  fZZeroX = -1; // in the s-plane, the zero is at infinity
805  fZZeroY = 0;
806  if (mFilterSubtype == kLowPass) // LOWPASS
807  {
808  fDCPoleDistSqr = sqrt(Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY));
809  fDCPoleDistSqr /= 2;
810  }
811  else
812  {
813  // Highpass - do the digital LP->HP transform on the poles and zeroes
814  ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -fZPoleY, &fZPoleX, &fZPoleY);
815  fZZeroX = 1;
816  fDCPoleDistSqr = sqrt(Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY)); // distance from Nyquist
817  fDCPoleDistSqr /= 2;
818  }
819  mpBiquad[iPair].fNumerCoeffs [0] = fDCPoleDistSqr;
820  mpBiquad[iPair].fNumerCoeffs [1] = -fZZeroX * fDCPoleDistSqr;
821  mpBiquad[iPair].fNumerCoeffs [2] = 0;
822  mpBiquad[iPair].fDenomCoeffs [0] = -fZPoleX;
823  mpBiquad[iPair].fDenomCoeffs [1] = 0;
824  }
825  break;
826  }
827  return true;
828 }
#define PI
Definition: ScienFilter.cpp:62
bool BilinTransform(float fSX, float fSY, float *pfZX, float *pfZY)
Definition: Biquad.cpp:39
#define square(a)
Definition: ScienFilter.cpp:66
ArrayOf< BiquadStruct > mpBiquad
Definition: ScienFilter.h:105
float Calc2D_DistSqr(float fX1, float fY1, float fX2, float fY2)
Definition: Biquad.cpp:47
const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB)
void ComplexDiv(float fNumerR, float fNumerI, float fDenomR, float fDenomI, float *pfQuotientR, float *pfQuotientI)
Definition: Biquad.cpp:32
bool EffectScienFilter::CalcFilterCoeffs ( void  )
private
double EffectScienFilter::ChebyPoly ( int  Order,
double  NormFreq 
)
private

Definition at line 830 of file ScienFilter.cpp.

Referenced by FilterMagnAtFreq().

831 {
832  // Calc cosh (Order * acosh (NormFreq));
833  double x = 1;
834  double fSum = 0;
835  wxASSERT (Order >= MIN_Order && Order <= MAX_Order);
836  for (int i = 0; i <= Order; i++)
837  {
838  fSum += s_fChebyCoeffs [Order-1][i] * x;
839  x *= NormFreq;
840  }
841  return fSum;
842 }
static const double s_fChebyCoeffs[MAX_Order][MAX_Order+1]
bool EffectScienFilter::DefineParams ( ShuttleParams S)
override

Definition at line 244 of file ScienFilter.cpp.

References mCutoff, mFilterSubtype, mFilterType, mOrder, mRipple, mStopbandRipple, nSubTypes, and nTypes.

244  {
245  S.SHUTTLE_ENUM_PARAM( mFilterType, Type, kTypeStrings, nTypes );
246  S.SHUTTLE_ENUM_PARAM( mFilterSubtype, Subtype, kSubTypeStrings, nSubTypes );
247  S.SHUTTLE_PARAM( mOrder, Order );
248  S.SHUTTLE_PARAM( mCutoff, Cutoff );
249  S.SHUTTLE_PARAM( mRipple, Passband );
250  S.SHUTTLE_PARAM( mStopbandRipple, Stopband );
251  return true;
252 }
static const IdentInterfaceSymbol kSubTypeStrings[nSubTypes]
static const IdentInterfaceSymbol kTypeStrings[nTypes]
Definition: ScienFilter.cpp:89
void EffectScienFilter::EnableDisableRippleCtl ( int  FilterType)
private

Definition at line 977 of file ScienFilter.cpp.

References kButterworth, kChebyshevTypeI, mRippleCtl, mRippleCtlP, mRippleCtlU, mStopbandRippleCtl, mStopbandRippleCtlP, and mStopbandRippleCtlU.

Referenced by OnFilterType(), and TransferDataToWindow().

978 {
979  bool ripple;
980  bool stop;
981 
982  if (FilterType == kButterworth) // Butterworth
983  {
984  ripple = false;
985  stop = false;
986  }
987  else if (FilterType == kChebyshevTypeI) // Chebyshev Type1
988  {
989  ripple = true;
990  stop = false;
991  }
992  else // Chebyshev Type2
993  {
994  ripple = false;
995  stop = true;
996  }
997 
998  mRippleCtlP->Enable(ripple);
999  mRippleCtl->Enable(ripple);
1000  mRippleCtlU->Enable(ripple);
1001  mStopbandRippleCtlP->Enable(stop);
1002  mStopbandRippleCtl->Enable(stop);
1003  mStopbandRippleCtlU->Enable(stop);
1004 }
wxStaticText * mRippleCtlP
Definition: ScienFilter.h:118
wxTextCtrl * mStopbandRippleCtl
Definition: ScienFilter.h:125
wxStaticText * mRippleCtlU
Definition: ScienFilter.h:120
wxTextCtrl * mRippleCtl
Definition: ScienFilter.h:119
wxStaticText * mStopbandRippleCtlP
Definition: ScienFilter.h:124
wxStaticText * mStopbandRippleCtlU
Definition: ScienFilter.h:126
float EffectScienFilter::FilterMagnAtFreq ( float  Freq)
private

Definition at line 844 of file ScienFilter.cpp.

References ChebyPoly(), kButterworth, kChebyshevTypeI, kChebyshevTypeII, kHighPass, kLowPass, mCutoff, mFilterSubtype, mFilterType, mNyquist, mOrder, mRipple, mStopbandRipple, PI, and square.

Referenced by EffectScienFilterPanel::OnPaint().

845 {
846  float Magn;
847  if (Freq >= mNyquist)
848  Freq = mNyquist - 1; // prevent tan(PI/2)
849  float FreqWarped = tan (PI * Freq/(2*mNyquist));
850  if (mCutoff >= mNyquist)
851  mCutoff = mNyquist - 1;
852  float CutoffWarped = tan (PI * mCutoff/(2*mNyquist));
853  float fOverflowThresh = pow (10.0, 12.0 / (2*mOrder)); // once we exceed 10^12 there's not much to be gained and overflow could happen
854 
855  switch (mFilterType)
856  {
857  case kButterworth: // Butterworth
858  default:
859  switch (mFilterSubtype)
860  {
861  case kLowPass: // lowpass
862  default:
863  if (FreqWarped/CutoffWarped > fOverflowThresh) // prevent pow() overflow
864  Magn = 0;
865  else
866  Magn = sqrt (1 / (1 + pow (FreqWarped/CutoffWarped, 2*mOrder)));
867  break;
868  case kHighPass: // highpass
869  if (FreqWarped/CutoffWarped > fOverflowThresh)
870  Magn = 1;
871  else
872  Magn = sqrt (pow (FreqWarped/CutoffWarped, 2*mOrder) / (1 + pow (FreqWarped/CutoffWarped, 2*mOrder)));
873  break;
874  }
875  break;
876 
877  case kChebyshevTypeI: // Chebyshev Type 1
878  double eps; eps = sqrt(pow (10.0, wxMax(0.001, mRipple)/10.0) - 1);
879  switch (mFilterSubtype)
880  {
881  case 0: // lowpass
882  default:
883  Magn = sqrt (1 / (1 + square(eps) * square(ChebyPoly(mOrder, FreqWarped/CutoffWarped))));
884  break;
885  case 1:
886  Magn = sqrt (1 / (1 + square(eps) * square(ChebyPoly(mOrder, CutoffWarped/FreqWarped))));
887  break;
888  }
889  break;
890 
891  case kChebyshevTypeII: // Chebyshev Type 2
892  eps = 1 / sqrt(pow (10.0, wxMax(0.001, mStopbandRipple)/10.0) - 1);
893  switch (mFilterSubtype)
894  {
895  case kLowPass: // lowpass
896  default:
897  Magn = sqrt (1 / (1 + 1 / (square(eps) * square(ChebyPoly(mOrder, CutoffWarped/FreqWarped)))));
898  break;
899  case kHighPass:
900  Magn = sqrt (1 / (1 + 1 / (square(eps) * square(ChebyPoly(mOrder, FreqWarped/CutoffWarped)))));
901  break;
902  }
903  break;
904  }
905 
906  return Magn;
907 }
#define PI
Definition: ScienFilter.cpp:62
#define square(a)
Definition: ScienFilter.cpp:66
double ChebyPoly(int Order, double NormFreq)
unsigned EffectScienFilter::GetAudioInCount ( )
overridevirtual

Reimplemented from Effect.

Definition at line 208 of file ScienFilter.cpp.

209 {
210  return 1;
211 }
unsigned EffectScienFilter::GetAudioOutCount ( )
overridevirtual

Reimplemented from Effect.

Definition at line 213 of file ScienFilter.cpp.

214 {
215  return 1;
216 }
bool EffectScienFilter::GetAutomationParameters ( CommandParameters parms)
overridevirtual

Reimplemented from Effect.

Definition at line 254 of file ScienFilter.cpp.

References mCutoff, mFilterSubtype, mFilterType, mOrder, mRipple, mStopbandRipple, and CommandParameters::WriteFloat().

255 {
256  parms.Write(KEY_Type, kTypeStrings[mFilterType].Internal());
257  parms.Write(KEY_Subtype, kSubTypeStrings[mFilterSubtype].Internal());
258  parms.Write(KEY_Order, mOrder);
259  parms.WriteFloat(KEY_Cutoff, mCutoff);
260  parms.WriteFloat(KEY_Passband, mRipple);
261  parms.WriteFloat(KEY_Stopband, mStopbandRipple);
262 
263  return true;
264 }
static const IdentInterfaceSymbol kSubTypeStrings[nSubTypes]
bool WriteFloat(const wxString &key, float f)
static const IdentInterfaceSymbol kTypeStrings[nTypes]
Definition: ScienFilter.cpp:89
wxString EffectScienFilter::GetDescription ( )
overridevirtual

Reimplemented from Effect.

Definition at line 188 of file ScienFilter.cpp.

References _().

189 {
190  return _("Performs IIR filtering that emulates analog filters");
191 }
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
IdentInterfaceSymbol EffectScienFilter::GetSymbol ( )
overridevirtual

Reimplemented from Effect.

Definition at line 183 of file ScienFilter.cpp.

References CLASSICFILTERS_PLUGIN_SYMBOL.

184 {
186 }
#define CLASSICFILTERS_PLUGIN_SYMBOL
Definition: ScienFilter.h:34
EffectType EffectScienFilter::GetType ( )
overridevirtual

Reimplemented from Effect.

Definition at line 201 of file ScienFilter.cpp.

References EffectTypeProcess.

202 {
203  return EffectTypeProcess;
204 }
bool EffectScienFilter::Init ( )
overridevirtual

Reimplemented from Effect.

Definition at line 339 of file ScienFilter.cpp.

References _(), TrackListCondIterator::First(), GetActiveProject(), WaveTrack::GetRate(), AudacityProject::GetRate(), Track::GetSelected(), Effect::inputTracks(), Effect::MessageBox(), mNyquist, TrackListCondIterator::Next(), and Track::Wave.

340 {
341  int selcount = 0;
342  double rate = 0.0;
343 
345  WaveTrack *t = (WaveTrack *) iter.First();
346 
347  mNyquist = (t ? t->GetRate() : GetActiveProject()->GetRate()) / 2.0;
348 
349  while (t)
350  {
351  if (t->GetSelected())
352  {
353  if (selcount == 0)
354  {
355  rate = t->GetRate();
356  }
357  else
358  {
359  if (t->GetRate() != rate)
360  {
361  Effect::MessageBox(_("To apply a filter, all selected tracks must have the same sample rate."));
362  return false;
363  }
364  }
365  selcount++;
366  }
367  t = (WaveTrack *) iter.Next();
368  }
369 
370  return true;
371 }
int MessageBox(const wxString &message, long style=DefaultMessageBoxStyle, const wxString &titleStr=wxString{})
Definition: Effect.cpp:2646
bool GetSelected() const
Definition: Track.h:276
TrackList * inputTracks() const
Definition: Effect.h:458
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:308
double GetRate() const
Definition: Project.h:199
double GetRate() const
Definition: WaveTrack.cpp:398
wxString EffectScienFilter::ManualPage ( )
overridevirtual

Reimplemented from Effect.

Definition at line 193 of file ScienFilter.cpp.

194 {
195  return wxT("Classic_Filters");
196 }
void EffectScienFilter::OnCutoff ( wxCommandEvent &  evt)
private

Definition at line 929 of file ScienFilter.cpp.

References Effect::EnableApply(), mPanel, and Effect::mUIParent.

930 {
931  if (!EnableApply(mUIParent->TransferDataFromWindow()))
932  {
933  return;
934  }
935 
936  mPanel->Refresh(false);
937 }
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
wxWindow * mUIParent
Definition: Effect.h:472
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1886
void EffectScienFilter::OnFilterSubtype ( wxCommandEvent &  evt)
private

Definition at line 923 of file ScienFilter.cpp.

References mFilterSubtype, mFilterSubTypeCtl, and mPanel.

924 {
925  mFilterSubtype = mFilterSubTypeCtl->GetSelection();
926  mPanel->Refresh(false);
927 }
wxChoice * mFilterSubTypeCtl
Definition: ScienFilter.h:129
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
void EffectScienFilter::OnFilterType ( wxCommandEvent &  evt)
private

Definition at line 916 of file ScienFilter.cpp.

References EnableDisableRippleCtl(), mFilterType, mFilterTypeCtl, and mPanel.

917 {
918  mFilterType = mFilterTypeCtl->GetSelection();
920  mPanel->Refresh(false);
921 }
wxChoice * mFilterTypeCtl
Definition: ScienFilter.h:128
void EnableDisableRippleCtl(int FilterType)
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
void EffectScienFilter::OnOrder ( wxCommandEvent &  evt)
private

Definition at line 909 of file ScienFilter.cpp.

References mFilterOrderCtl, mOrder, mOrderIndex, and mPanel.

910 {
911  mOrderIndex = mFilterOrderCtl->GetSelection();
912  mOrder = mOrderIndex + 1; // 0..n-1 -> 1..n
913  mPanel->Refresh(false);
914 }
wxChoice * mFilterOrderCtl
Definition: ScienFilter.h:130
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
void EffectScienFilter::OnRipple ( wxCommandEvent &  evt)
private

Definition at line 939 of file ScienFilter.cpp.

References Effect::EnableApply(), mPanel, and Effect::mUIParent.

940 {
941  if (!EnableApply(mUIParent->TransferDataFromWindow()))
942  {
943  return;
944  }
945 
946  mPanel->Refresh(false);
947 }
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
wxWindow * mUIParent
Definition: Effect.h:472
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1886
void EffectScienFilter::OnSize ( wxSizeEvent &  evt)
private

Definition at line 969 of file ScienFilter.cpp.

References Effect::mUIParent.

970 {
971  // On Windows the Passband and Stopband boxes do not refresh properly
972  // on a resize...no idea why.
973  mUIParent->Refresh();
974  evt.Skip();
975 }
wxWindow * mUIParent
Definition: Effect.h:472
void EffectScienFilter::OnSlider ( wxCommandEvent &  evt)
private
void EffectScienFilter::OnSliderDBMAX ( wxCommandEvent &  evt)
private

Definition at line 964 of file ScienFilter.cpp.

References TransferGraphLimitsFromWindow().

965 {
967 }
bool TransferGraphLimitsFromWindow()
void EffectScienFilter::OnSliderDBMIN ( wxCommandEvent &  evt)
private

Definition at line 959 of file ScienFilter.cpp.

References TransferGraphLimitsFromWindow().

960 {
962 }
bool TransferGraphLimitsFromWindow()
void EffectScienFilter::OnStopbandRipple ( wxCommandEvent &  evt)
private

Definition at line 949 of file ScienFilter.cpp.

References Effect::EnableApply(), mPanel, and Effect::mUIParent.

950 {
951  if (!EnableApply(mUIParent->TransferDataFromWindow()))
952  {
953  return;
954  }
955 
956  mPanel->Refresh(false);
957 }
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
wxWindow * mUIParent
Definition: Effect.h:472
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1886
void EffectScienFilter::PopulateOrExchange ( ShuttleGui S)
overridevirtual

Reimplemented from Effect.

Definition at line 373 of file ScienFilter.cpp.

References _(), ShuttleGuiBase::AddChoice(), ShuttleGuiBase::AddSlider(), ShuttleGui::AddSpace(), ShuttleGuiBase::AddTextBox(), ShuttleGuiBase::AddUnits(), ShuttleGuiBase::AddVariableText(), ShuttleGuiBase::AddWindow(), EffectScienFilterPanel, ShuttleGuiBase::EndMultiColumn(), ShuttleGuiBase::EndVerticalLay(), RulerPanel::Options::Flip(), ShuttleGuiBase::GetParent(), ShuttleGui::Id(), ID_Cutoff, ID_dBMax, ID_dBMin, ID_Order, ID_Ripple, ID_StopbandRipple, ID_SubType, ID_Type, Ruler::IntFormat, RulerPanel::Options::LabelEdges(), Ruler::LinearDBFormat, LocalizedStrings(), RulerPanel::Options::Log(), mCutoff, mCutoffCtl, mdBMaxSlider, mdBMinSlider, mdBRuler, mFilterOrderCtl, mFilterSubtype, mFilterSubTypeCtl, mFilterType, mFilterTypeCtl, mfreqRuler, mLoFreq, mNyquist, mOrderIndex, mPanel, mRipple, mRippleCtl, mRippleCtlP, mRippleCtlU, mStopbandRipple, mStopbandRippleCtl, mStopbandRippleCtlP, mStopbandRippleCtlU, nSubTypes, nTypes, ShuttleGui::Prop(), safenew, ShuttleGuiBase::SetBorder(), ShuttleGuiBase::SetSizeHints(), ShuttleGuiBase::SetSizerProportion(), ShuttleGuiBase::SetStretchyCol(), ShuttleGuiBase::SetStretchyRow(), ShuttleGuiBase::SetStyle(), ShuttleGuiBase::StartMultiColumn(), and ShuttleGuiBase::StartVerticalLay().

374 {
375  wxWindow *const parent = S.GetParent();
376 
377  S.AddSpace(5);
378  S.SetSizerProportion(1);
379  S.StartMultiColumn(3, wxEXPAND);
380  {
381  S.SetStretchyCol(1);
382  S.SetStretchyRow(0);
383 
384  // -------------------------------------------------------------------
385  // ROW 1: Freq response panel and sliders for vertical scale
386  // -------------------------------------------------------------------
387 
388  S.StartVerticalLay();
389  {
391  parent, wxID_ANY, wxVERTICAL,
392  wxSize{ 100, 100 }, // Ruler can't handle small sizes
393  RulerPanel::Range{ 30.0, -120.0 },
395  _("dB"),
397  .LabelEdges(true)
398  );
399 
400  S.SetBorder(1);
401  S.AddSpace(1, 1);
402  S.Prop(1);
403  S.AddWindow(mdBRuler, wxALIGN_RIGHT | wxTOP);
404  S.AddSpace(1, 1);
405  }
406  S.EndVerticalLay();
407 
409  parent, wxID_ANY,
410  this, mLoFreq, mNyquist
411  );
412 
413  S.SetBorder(5);
414  S.Prop(1);
415  S.AddWindow(mPanel, wxEXPAND | wxRIGHT);
416  S.SetSizeHints(-1, -1);
417 
418  S.StartVerticalLay();
419  {
420  S.AddVariableText(_("+ dB"), false, wxCENTER);
421  S.SetStyle(wxSL_VERTICAL | wxSL_INVERSE);
422  mdBMaxSlider = S.Id(ID_dBMax).AddSlider( {}, 10, 20, 0);
423 #if wxUSE_ACCESSIBILITY
424  mdBMaxSlider->SetName(_("Max dB"));
425  mdBMaxSlider->SetAccessible(safenew SliderAx(mdBMaxSlider, _("%d dB")));
426 #endif
427 
428  S.SetStyle(wxSL_VERTICAL | wxSL_INVERSE);
429  mdBMinSlider = S.Id(ID_dBMin).AddSlider( {}, -10, -10, -120);
430  S.AddVariableText(_("- dB"), false, wxCENTER);
431 #if wxUSE_ACCESSIBILITY
432  mdBMinSlider->SetName(_("Min dB"));
433  mdBMinSlider->SetAccessible(safenew SliderAx(mdBMinSlider, _("%d dB")));
434 #endif
435  }
436  S.EndVerticalLay();
437 
438  // -------------------------------------------------------------------
439  // ROW 2: Frequency ruler
440  // -------------------------------------------------------------------
441 
442  S.AddSpace(1, 1);
443 
445  parent, wxID_ANY, wxHORIZONTAL,
446  wxSize{ 100, 100 }, // Ruler can't handle small sizes
449  wxT(""),
451  .Log(true)
452  .Flip(true)
453  .LabelEdges(true)
454  );
455 
456  S.Prop(1);
457  S.AddWindow(mfreqRuler, wxEXPAND | wxALIGN_LEFT | wxRIGHT);
458 
459  S.AddSpace(1, 1);
460 
461  // -------------------------------------------------------------------
462  // ROW 3 and 4: Type, Order, Ripple, Subtype, Cutoff
463  // -------------------------------------------------------------------
464 
465  S.AddSpace(1, 1);
466  S.SetSizerProportion(0);
467  S.StartMultiColumn(8, wxALIGN_CENTER);
468  {
469  wxASSERT(nTypes == WXSIZEOF(kTypeStrings));
470 
471  auto typeChoices = LocalizedStrings(kTypeStrings, nTypes);
472  mFilterTypeCtl = S.Id(ID_Type).AddChoice(_("&Filter Type:"), wxT(""), &typeChoices);
473  mFilterTypeCtl->SetValidator(wxGenericValidator(&mFilterType));
474  S.SetSizeHints(-1, -1);
475 
476  wxArrayString orders;
477  for (int i = 1; i <= 10; i++)
478  {
479  orders.Add(wxString::Format(wxT("%d"), i));
480  }
481  /*i18n-hint: 'Order' means the complexity of the filter, and is a number between 1 and 10.*/
482  mFilterOrderCtl = S.Id(ID_Order).AddChoice(_("O&rder:"), wxT(""), &orders);
483  mFilterOrderCtl->SetValidator(wxGenericValidator(&mOrderIndex));
484  S.SetSizeHints(-1, -1);
485  S.AddSpace(1, 1);
486 
487  FloatingPointValidator<float> vldRipple(1, &mRipple);
488  vldRipple.SetRange(MIN_Passband, MAX_Passband);
489 
490  mRippleCtlP = S.AddVariableText(_("&Passband Ripple:"), false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
491  mRippleCtl = S.Id(ID_Ripple).AddTextBox( {}, wxT(""), 10);
492  mRippleCtl->SetName(_("Passband Ripple (dB)"));
493  mRippleCtl->SetValidator(vldRipple);
494  mRippleCtlU = S.AddVariableText(_("dB"), false, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
495 
496  wxASSERT(nSubTypes == WXSIZEOF(kSubTypeStrings));
497 
498  auto subTypeChoices = LocalizedStrings(kSubTypeStrings, nSubTypes);
499  mFilterSubTypeCtl = S.Id(ID_SubType).AddChoice(_("&Subtype:"), wxT(""), &subTypeChoices);
500  mFilterSubTypeCtl->SetValidator(wxGenericValidator(&mFilterSubtype));
501  S.SetSizeHints(-1, -1);
502 
503  FloatingPointValidator<float> vldCutoff(1, &mCutoff);
504  vldCutoff.SetRange(MIN_Cutoff, mNyquist - 1);
505 
506  mCutoffCtl = S.Id(ID_Cutoff).AddTextBox(_("C&utoff:"), wxT(""), 10);
507  mCutoffCtl->SetName(_("Cutoff (Hz)"));
508  mCutoffCtl->SetValidator(vldCutoff);
509  S.AddUnits(_("Hz"));
510 
511  FloatingPointValidator<float> vldStopbandRipple(1, &mStopbandRipple);
512  vldStopbandRipple.SetRange(MIN_Stopband, MAX_Stopband);
513 
514  mStopbandRippleCtlP = S.AddVariableText(_("Minimum S&topband Attenuation:"), false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
515  mStopbandRippleCtl = S.Id(ID_StopbandRipple).AddTextBox( {}, wxT(""), 10);
516  mStopbandRippleCtl->SetName(_("Minimum S&topband Attenuation (dB)"));
517  mStopbandRippleCtl->SetValidator(vldStopbandRipple);
518  mStopbandRippleCtlU = S.AddVariableText(_("dB"), false, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
519  }
520  S.EndMultiColumn();
521  S.AddSpace(1, 1);
522  }
523  S.EndMultiColumn();
524 
525  mFilterTypeCtl->SetFocus();
526 
527  return;
528 }
wxChoice * mFilterTypeCtl
Definition: ScienFilter.h:128
void SetSizeHints(int minX, int minY)
Used to modify an already placed Window.
Definition: ShuttleGui.cpp:194
wxStaticText * mRippleCtlP
Definition: ScienFilter.h:118
wxWindow * AddWindow(wxWindow *pWindow, int Flags=wxALIGN_CENTRE|wxALL)
Definition: ShuttleGui.cpp:288
static const IdentInterfaceSymbol kSubTypeStrings[nSubTypes]
wxArrayString LocalizedStrings(const IdentInterfaceSymbol strings[], size_t nStrings)
Definition: Internat.cpp:303
wxSlider * mdBMinSlider
Definition: ScienFilter.h:115
friend class EffectScienFilterPanel
Definition: ScienFilter.h:137
wxTextCtrl * mStopbandRippleCtl
Definition: ScienFilter.h:125
RulerPanel * mfreqRuler
Definition: ScienFilter.h:133
Options & LabelEdges(bool l)
Definition: Ruler.h:268
void EndMultiColumn()
wxChoice * mFilterSubTypeCtl
Definition: ScienFilter.h:129
wxTextCtrl * mCutoffCtl
Definition: ScienFilter.h:122
RulerPanel class allows you to work with a Ruler like any other wxWindow.
Definition: Ruler.h:246
void SetSizerProportion(int iProp)
Definition: ShuttleGui.h:289
#define safenew
Definition: Audacity.h:230
wxChoice * mFilterOrderCtl
Definition: ScienFilter.h:130
wxStaticText * mRippleCtlU
Definition: ScienFilter.h:120
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
void AddUnits(const wxString &Prompt)
Left aligned text string.
Definition: ShuttleGui.cpp:260
void EndVerticalLay()
Options & Flip(bool f)
Definition: Ruler.h:265
wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:540
RulerPanel * mdBRuler
Definition: ScienFilter.h:132
wxWindow * GetParent()
Definition: ShuttleGui.h:294
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:371
ShuttleGui & Id(int id)
void SetStyle(int Style)
Definition: ShuttleGui.h:287
Options & Log(bool l)
Definition: Ruler.h:262
wxTextCtrl * mRippleCtl
Definition: ScienFilter.h:119
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxStaticText * AddVariableText(const wxString &Str, bool bCenter=false, int PositionFlags=0)
Definition: ShuttleGui.cpp:414
static const IdentInterfaceSymbol kTypeStrings[nTypes]
Definition: ScienFilter.cpp:89
std::pair< double, double > Range
Definition: Ruler.h:250
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:418
wxSizerItem * AddSpace(int width, int height)
void SetBorder(int Border)
Definition: ShuttleGui.h:286
wxSlider * mdBMaxSlider
Definition: ScienFilter.h:116
wxStaticText * mStopbandRippleCtlP
Definition: ScienFilter.h:124
wxStaticText * mStopbandRippleCtlU
Definition: ScienFilter.h:126
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:203
void SetStretchyRow(int i)
Used to modify an already placed FlexGridSizer to make a row stretchy.
Definition: ShuttleGui.cpp:213
wxSlider * AddSlider(const wxString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:497
void StartVerticalLay(int iProp=1)
size_t EffectScienFilter::ProcessBlock ( float **  inBlock,
float **  outBlock,
size_t  blockLen 
)
overridevirtual

Reimplemented from Effect.

Definition at line 231 of file ScienFilter.cpp.

References Biquad_Process(), mOrder, and mpBiquad.

232 {
233  float *ibuf = inBlock[0];
234  for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
235  {
236  mpBiquad[iPair].pfIn = ibuf;
237  mpBiquad[iPair].pfOut = outBlock[0];
238  Biquad_Process(&mpBiquad[iPair], blockLen);
239  ibuf = outBlock[0];
240  }
241 
242  return blockLen;
243 }
ArrayOf< BiquadStruct > mpBiquad
Definition: ScienFilter.h:105
void Biquad_Process(BiquadStruct *pBQ, int iNumSamples)
Definition: Biquad.cpp:5
bool EffectScienFilter::ProcessInitialize ( sampleCount  totalLen,
ChannelNames  chanMap = NULL 
)
overridevirtual

Reimplemented from Effect.

Definition at line 218 of file ScienFilter.cpp.

References mOrder, and mpBiquad.

219 {
220  for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
221  {
222  mpBiquad[iPair].fPrevIn = 0;
223  mpBiquad[iPair].fPrevPrevIn = 0;
224  mpBiquad[iPair].fPrevOut = 0;
225  mpBiquad[iPair].fPrevPrevOut = 0;
226  }
227 
228  return true;
229 }
ArrayOf< BiquadStruct > mpBiquad
Definition: ScienFilter.h:105
bool EffectScienFilter::SetAutomationParameters ( CommandParameters parms)
overridevirtual

Reimplemented from Effect.

Definition at line 266 of file ScienFilter.cpp.

References CalcFilter(), mCutoff, mFilterSubtype, mFilterType, mOrder, mOrderIndex, mRipple, mStopbandRipple, nSubTypes, nTypes, ReadAndVerifyEnum, ReadAndVerifyFloat, and ReadAndVerifyInt.

267 {
270  ReadAndVerifyInt(Order);
271  ReadAndVerifyFloat(Cutoff);
272  ReadAndVerifyFloat(Passband);
273  ReadAndVerifyFloat(Stopband);
274 
275  mFilterType = Type;
276  mFilterSubtype = Subtype;
277  mOrder = Order;
278  mCutoff = Cutoff;
279  mRipple = Passband;
280  mStopbandRipple = Stopband;
281 
282  mOrderIndex = mOrder - 1;
283 
284  CalcFilter();
285 
286  return true;
287 }
#define ReadAndVerifyFloat(name)
Definition: Effect.h:799
static const IdentInterfaceSymbol kSubTypeStrings[nSubTypes]
#define ReadAndVerifyEnum(name, list, listSize)
Definition: Effect.h:786
#define ReadAndVerifyInt(name)
Definition: Effect.h:797
static const IdentInterfaceSymbol kTypeStrings[nTypes]
Definition: ScienFilter.cpp:89
bool EffectScienFilter::Startup ( )
overridevirtual

Reimplemented from Effect.

Definition at line 291 of file ScienFilter.cpp.

References Effect::GetCurrentSettingsGroup(), gPrefs, mCutoff, mFilterSubtype, mFilterType, mOrder, mRipple, mStopbandRipple, and Effect::SaveUserPreset().

292 {
293  wxString base = wxT("/SciFilter/");
294 
295  // Migrate settings from 2.1.0 or before
296 
297  // Already migrated, so bail
298  if (gPrefs->Exists(base + wxT("Migrated")))
299  {
300  return true;
301  }
302 
303  // Load the old "current" settings
304  if (gPrefs->Exists(base))
305  {
306  double dTemp;
307  gPrefs->Read(base + wxT("Order"), &mOrder, 1);
308  mOrder = wxMax (1, mOrder);
309  mOrder = wxMin (MAX_Order, mOrder);
310  gPrefs->Read(base + wxT("FilterType"), &mFilterType, 0);
311  mFilterType = wxMax (0, mFilterType);
312  mFilterType = wxMin (2, mFilterType);
313  gPrefs->Read(base + wxT("FilterSubtype"), &mFilterSubtype, 0);
314  mFilterSubtype = wxMax (0, mFilterSubtype);
315  mFilterSubtype = wxMin (1, mFilterSubtype);
316  gPrefs->Read(base + wxT("Cutoff"), &dTemp, 1000.0);
317  mCutoff = (float)dTemp;
318  mCutoff = wxMax (1, mCutoff);
319  mCutoff = wxMin (100000, mCutoff);
320  gPrefs->Read(base + wxT("Ripple"), &dTemp, 1.0);
321  mRipple = dTemp;
322  mRipple = wxMax (0, mRipple);
323  mRipple = wxMin (100, mRipple);
324  gPrefs->Read(base + wxT("StopbandRipple"), &dTemp, 30.0);
325  mStopbandRipple = dTemp;
326  mStopbandRipple = wxMax (0, mStopbandRipple);
327  mStopbandRipple = wxMin (100, mStopbandRipple);
328 
330 
331  // Do not migrate again
332  gPrefs->Write(base + wxT("Migrated"), true);
333  gPrefs->Flush();
334  }
335 
336  return true;
337 }
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
bool SaveUserPreset(const wxString &name) override
Definition: Effect.cpp:600
wxString GetCurrentSettingsGroup() override
Definition: Effect.cpp:801
bool EffectScienFilter::TransferDataFromWindow ( )
overridevirtual

Reimplemented from Effect.

Definition at line 553 of file ScienFilter.cpp.

References CalcFilter(), mOrder, mOrderIndex, and Effect::mUIParent.

554 {
555  if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
556  {
557  return false;
558  }
559 
560  mOrder = mOrderIndex + 1;
561 
562  CalcFilter();
563 
564  return true;
565 }
wxWindow * mUIParent
Definition: Effect.h:472
bool EffectScienFilter::TransferDataToWindow ( )
overridevirtual

Reimplemented from Effect.

Definition at line 533 of file ScienFilter.cpp.

References EnableDisableRippleCtl(), mdBMax, mdBMaxSlider, mdBMin, mdBMinSlider, mFilterType, mOrder, mOrderIndex, Effect::mUIParent, and TransferGraphLimitsFromWindow().

534 {
535  mOrderIndex = mOrder - 1;
536 
537  if (!mUIParent->TransferDataToWindow())
538  {
539  return false;
540  }
541 
542  mdBMinSlider->SetValue((int) mdBMin);
543  mdBMin = 0.0; // force refresh in TransferGraphLimitsFromWindow()
544 
545  mdBMaxSlider->SetValue((int) mdBMax);
546  mdBMax = 0.0; // force refresh in TransferGraphLimitsFromWindow()
547 
549 
551 }
bool TransferGraphLimitsFromWindow()
wxSlider * mdBMinSlider
Definition: ScienFilter.h:115
void EnableDisableRippleCtl(int FilterType)
wxWindow * mUIParent
Definition: Effect.h:472
wxSlider * mdBMaxSlider
Definition: ScienFilter.h:116
bool EffectScienFilter::TransferGraphLimitsFromWindow ( )
private

Definition at line 572 of file ScienFilter.cpp.

References _(), Ruler::GetMaxSize(), mdBMax, mdBMaxSlider, mdBMin, mdBMinSlider, mdBRuler, mfreqRuler, mPanel, Effect::mUIParent, RulerPanel::ruler, EffectScienFilterPanel::SetDbRange(), and Ruler::SetRange().

Referenced by OnSliderDBMAX(), OnSliderDBMIN(), and TransferDataToWindow().

573 {
574  // Read the sliders and send to the panel
575  wxString tip;
576 
577  bool rr = false;
578  int dB = mdBMinSlider->GetValue();
579  if (dB != mdBMin) {
580  rr = true;
581  mdBMin = dB;
582  tip.Printf(_("%d dB"), (int)mdBMin);
583  mdBMinSlider->SetToolTip(tip);
584  }
585 
586  dB = mdBMaxSlider->GetValue();
587  if (dB != mdBMax) {
588  rr = true;
589  mdBMax = dB;
590  tip.Printf(_("%d dB"),(int)mdBMax);
591  mdBMaxSlider->SetToolTip(tip);
592  }
593 
594  if (rr) {
595  mPanel->SetDbRange(mdBMin, mdBMax);
596  }
597 
598  // Refresh ruler if values have changed
599  if (rr) {
600  int w1, w2, h;
601  mdBRuler->ruler.GetMaxSize(&w1, &h);
602  mdBRuler->ruler.SetRange(mdBMax, mdBMin);
603  mdBRuler->ruler.GetMaxSize(&w2, &h);
604  if( w1 != w2 ) // Reduces flicker
605  {
606  mdBRuler->SetSize(wxSize(w2,h));
607  mUIParent->Layout();
608  mfreqRuler->Refresh(false);
609  }
610  mdBRuler->Refresh(false);
611  }
612 
613  mPanel->Refresh(false);
614 
615  return true;
616 }
wxSlider * mdBMinSlider
Definition: ScienFilter.h:115
RulerPanel * mfreqRuler
Definition: ScienFilter.h:133
void GetMaxSize(wxCoord *width, wxCoord *height)
Definition: Ruler.cpp:1549
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:114
RulerPanel * mdBRuler
Definition: ScienFilter.h:132
wxWindow * mUIParent
Definition: Effect.h:472
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void SetRange(double min, double max)
Definition: Ruler.cpp:236
void SetDbRange(double min, double max)
wxSlider * mdBMaxSlider
Definition: ScienFilter.h:116
Ruler ruler
Definition: Ruler.h:306

Friends And Related Function Documentation

friend class EffectScienFilterPanel
friend

Definition at line 137 of file ScienFilter.h.

Referenced by PopulateOrExchange().

Member Data Documentation

float EffectScienFilter::mCutoff
private
wxTextCtrl* EffectScienFilter::mCutoffCtl
private

Definition at line 122 of file ScienFilter.h.

Referenced by PopulateOrExchange().

double EffectScienFilter::mdBMax
private

Definition at line 107 of file ScienFilter.h.

Referenced by TransferDataToWindow(), and TransferGraphLimitsFromWindow().

wxSlider* EffectScienFilter::mdBMaxSlider
private
double EffectScienFilter::mdBMin
private

Definition at line 108 of file ScienFilter.h.

Referenced by TransferDataToWindow(), and TransferGraphLimitsFromWindow().

wxSlider* EffectScienFilter::mdBMinSlider
private
RulerPanel* EffectScienFilter::mdBRuler
private
bool EffectScienFilter::mEditingBatchParams
private

Definition at line 109 of file ScienFilter.h.

wxChoice* EffectScienFilter::mFilterOrderCtl
private

Definition at line 130 of file ScienFilter.h.

Referenced by OnOrder(), and PopulateOrExchange().

int EffectScienFilter::mFilterSubtype
private
wxChoice* EffectScienFilter::mFilterSubTypeCtl
private

Definition at line 129 of file ScienFilter.h.

Referenced by OnFilterSubtype(), and PopulateOrExchange().

int EffectScienFilter::mFilterType
private
wxChoice* EffectScienFilter::mFilterTypeCtl
private

Definition at line 128 of file ScienFilter.h.

Referenced by OnFilterType(), and PopulateOrExchange().

RulerPanel* EffectScienFilter::mfreqRuler
private
double EffectScienFilter::mLoFreq
private

Definition at line 111 of file ScienFilter.h.

Referenced by PopulateOrExchange().

double EffectScienFilter::mNyquist
private

Definition at line 112 of file ScienFilter.h.

Referenced by CalcFilter(), FilterMagnAtFreq(), Init(), and PopulateOrExchange().

int EffectScienFilter::mOrder
private
int EffectScienFilter::mOrderIndex
private
EffectScienFilterPanel* EffectScienFilter::mPanel
private
ArrayOf<BiquadStruct> EffectScienFilter::mpBiquad
private

Definition at line 105 of file ScienFilter.h.

Referenced by CalcFilter(), ProcessBlock(), and ProcessInitialize().

float EffectScienFilter::mRipple
private
wxTextCtrl* EffectScienFilter::mRippleCtl
private

Definition at line 119 of file ScienFilter.h.

Referenced by EnableDisableRippleCtl(), and PopulateOrExchange().

wxStaticText* EffectScienFilter::mRippleCtlP
private

Definition at line 118 of file ScienFilter.h.

Referenced by EnableDisableRippleCtl(), and PopulateOrExchange().

wxStaticText* EffectScienFilter::mRippleCtlU
private

Definition at line 120 of file ScienFilter.h.

Referenced by EnableDisableRippleCtl(), and PopulateOrExchange().

float EffectScienFilter::mStopbandRipple
private
wxTextCtrl* EffectScienFilter::mStopbandRippleCtl
private

Definition at line 125 of file ScienFilter.h.

Referenced by EnableDisableRippleCtl(), and PopulateOrExchange().

wxStaticText* EffectScienFilter::mStopbandRippleCtlP
private

Definition at line 124 of file ScienFilter.h.

Referenced by EnableDisableRippleCtl(), and PopulateOrExchange().

wxStaticText* EffectScienFilter::mStopbandRippleCtlU
private

Definition at line 126 of file ScienFilter.h.

Referenced by EnableDisableRippleCtl(), and PopulateOrExchange().


The documentation for this class was generated from the following files: