Audacity  3.0.3
ScienFilter.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Effect/ScienFilter.cpp
6 
7  Norm C
8  Mitch Golden
9  Vaughan Johnson (Preview)
10 
11 *******************************************************************//****************************************************************//****************************************************************//*******************************************************************/
34 
35 
36 #include "ScienFilter.h"
37 #include "LoadEffects.h"
38 
39 #include <math.h>
40 #include <float.h>
41 
42 #include <wx/setup.h> // for wxUSE_* macros
43 
44 #include <wx/brush.h>
45 #include <wx/choice.h>
46 #include <wx/dcclient.h>
47 #include <wx/dcmemory.h>
48 #include <wx/intl.h>
49 #include <wx/settings.h>
50 #include <wx/slider.h>
51 #include <wx/stattext.h>
52 #include <wx/utils.h>
53 #include <wx/valgen.h>
54 
55 #include "../AColor.h"
56 #include "../AllThemeResources.h"
57 #include "../PlatformCompatibility.h"
58 #include "../Prefs.h"
59 #include "../Project.h"
60 #include "../Shuttle.h"
61 #include "../ShuttleGui.h"
62 #include "../Theme.h"
63 #include "../WaveTrack.h"
64 #include "../widgets/valnum.h"
65 #include "../widgets/AudacityMessageBox.h"
66 #include "../widgets/Ruler.h"
67 #include "../widgets/WindowAccessible.h"
68 
69 #if !defined(M_PI)
70 #define PI = 3.1415926535897932384626433832795
71 #else
72 #define PI M_PI
73 #endif
74 #define square(a) ((a)*(a))
75 
76 enum
77 {
78  ID_FilterPanel = 10000,
87 };
88 
89 enum kTypes
90 {
94  nTypes
95 };
96 
98 {
99  /*i18n-hint: Butterworth is the name of the person after whom the filter type is named.*/
100  { XO("Butterworth") },
101  /*i18n-hint: Chebyshev is the name of the person after whom the filter type is named.*/
102  { XO("Chebyshev Type I") },
103  /*i18n-hint: Chebyshev is the name of the person after whom the filter type is named.*/
104  { XO("Chebyshev Type II") }
105 };
106 
108 {
112 };
113 
115 {
116  // These are acceptable dual purpose internal/visible names
117  { XO("Lowpass") },
118  { XO("Highpass") }
119 };
120 
121 static_assert(nSubTypes == WXSIZEOF(kSubTypeStrings), "size mismatch");
122 
123 // Define keys, defaults, minimums, and maximums for the effect parameters
124 //
125 // Name Type Key Def Min Max Scale
126 Param( Type, int, wxT("FilterType"), kButterworth, 0, nTypes - 1, 1 );
127 Param( Subtype, int, wxT("FilterSubtype"), kLowPass, 0, nSubTypes - 1, 1 );
128 Param( Order, int, wxT("Order"), 1, 1, 10, 1 );
129 Param( Cutoff, float, wxT("Cutoff"), 1000.0, 1.0, FLT_MAX, 1 );
130 Param( Passband, float, wxT("PassbandRipple"), 1.0, 0.0, 100.0, 1 );
131 Param( Stopband, float, wxT("StopbandRipple"), 30.0, 0.0, 100.0, 1 );
132 
133 //----------------------------------------------------------------------------
134 // EffectScienFilter
135 //----------------------------------------------------------------------------
136 
138 { XO("Classic Filters") };
139 
140 #ifdef EXPERIMENTAL_SCIENCE_FILTERS
141 // true argument means don't automatically enable this effect
143 #endif
144 
145 BEGIN_EVENT_TABLE(EffectScienFilter, wxEvtHandler)
146  EVT_SIZE(EffectScienFilter::OnSize)
147 
157 
159 {
160  mOrder = DEF_Order;
161  mFilterType = DEF_Type;
162  mFilterSubtype = DEF_Subtype;
163  mCutoff = DEF_Cutoff;
164  mRipple = DEF_Passband;
165  mStopbandRipple = DEF_Stopband;
166 
167  SetLinearEffectFlag(true);
168 
169  mOrderIndex = mOrder - 1;
170 
171  mdBMin = -30.0;
172  mdBMax = 30.0;
173 
174  mLoFreq = 20; // Lowest frequency to display in response graph
175  mNyquist = 44100.0 / 2.0; // only used during initialization, updated when effect is used
176 }
177 
179 {
180 }
181 
182 // ComponentInterface implementation
183 
185 {
186  return Symbol;
187 }
188 
190 {
191  /* i18n-hint: "infinite impulse response" */
192  return XO("Performs IIR filtering that emulates analog filters");
193 }
194 
196 {
197  return wxT("Classic_Filters");
198 }
199 
200 
201 // EffectDefinitionInterface implementation
202 
204 {
205  return EffectTypeProcess;
206 }
207 
208 // EffectClientInterface implementation
209 
211 {
212  return 1;
213 }
214 
216 {
217  return 1;
218 }
219 
220 bool EffectScienFilter::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
221 {
222  for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
223  mpBiquad[iPair].Reset();
224 
225  return true;
226 }
227 
228 size_t EffectScienFilter::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
229 {
230  float *ibuf = inBlock[0];
231  for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
232  {
233  mpBiquad[iPair].Process(ibuf, outBlock[0], blockLen);
234  ibuf = outBlock[0];
235  }
236 
237  return blockLen;
238 }
240  S.SHUTTLE_ENUM_PARAM( mFilterType, Type, kTypeStrings, nTypes );
241  S.SHUTTLE_ENUM_PARAM( mFilterSubtype, Subtype, kSubTypeStrings, nSubTypes );
242  S.SHUTTLE_PARAM( mOrder, Order );
243  S.SHUTTLE_PARAM( mCutoff, Cutoff );
244  S.SHUTTLE_PARAM( mRipple, Passband );
245  S.SHUTTLE_PARAM( mStopbandRipple, Stopband );
246  return true;
247 }
248 
250 {
251  parms.Write(KEY_Type, kTypeStrings[mFilterType].Internal());
252  parms.Write(KEY_Subtype, kSubTypeStrings[mFilterSubtype].Internal());
253  parms.Write(KEY_Order, mOrder);
254  parms.WriteFloat(KEY_Cutoff, mCutoff);
255  parms.WriteFloat(KEY_Passband, mRipple);
256  parms.WriteFloat(KEY_Stopband, mStopbandRipple);
257 
258  return true;
259 }
260 
262 {
265  ReadAndVerifyInt(Order);
266  ReadAndVerifyFloat(Cutoff);
267  ReadAndVerifyFloat(Passband);
268  ReadAndVerifyFloat(Stopband);
269 
270  mFilterType = Type;
271  mFilterSubtype = Subtype;
272  mOrder = Order;
273  mCutoff = Cutoff;
274  mRipple = Passband;
275  mStopbandRipple = Stopband;
276 
277  mOrderIndex = mOrder - 1;
278 
279  CalcFilter();
280 
281  return true;
282 }
283 
284 // Effect implementation
285 
287 {
288  wxString base = wxT("/SciFilter/");
289 
290  // Migrate settings from 2.1.0 or before
291 
292  // Already migrated, so bail
293  if (gPrefs->Exists(base + wxT("Migrated")))
294  {
295  return true;
296  }
297 
298  // Load the old "current" settings
299  if (gPrefs->Exists(base))
300  {
301  double dTemp;
302  gPrefs->Read(base + wxT("Order"), &mOrder, 1);
303  mOrder = wxMax (1, mOrder);
304  mOrder = wxMin (MAX_Order, mOrder);
305  gPrefs->Read(base + wxT("FilterType"), &mFilterType, 0);
306  mFilterType = wxMax (0, mFilterType);
307  mFilterType = wxMin (2, mFilterType);
308  gPrefs->Read(base + wxT("FilterSubtype"), &mFilterSubtype, 0);
309  mFilterSubtype = wxMax (0, mFilterSubtype);
310  mFilterSubtype = wxMin (1, mFilterSubtype);
311  gPrefs->Read(base + wxT("Cutoff"), &dTemp, 1000.0);
312  mCutoff = (float)dTemp;
313  mCutoff = wxMax (1, mCutoff);
314  mCutoff = wxMin (100000, mCutoff);
315  gPrefs->Read(base + wxT("Ripple"), &dTemp, 1.0);
316  mRipple = dTemp;
317  mRipple = wxMax (0, mRipple);
318  mRipple = wxMin (100, mRipple);
319  gPrefs->Read(base + wxT("StopbandRipple"), &dTemp, 30.0);
320  mStopbandRipple = dTemp;
321  mStopbandRipple = wxMax (0, mStopbandRipple);
322  mStopbandRipple = wxMin (100, mStopbandRipple);
323 
325 
326  // Do not migrate again
327  gPrefs->Write(base + wxT("Migrated"), true);
328  gPrefs->Flush();
329  }
330 
331  return true;
332 }
333 
335 {
336  int selcount = 0;
337  double rate = 0.0;
338 
339  auto trackRange = inputTracks()->Selected< const WaveTrack >();
340 
341  {
342  auto t = *trackRange.begin();
343  mNyquist =
344  (t
345  ? t->GetRate()
346  : mProjectRate)
347  / 2.0;
348  }
349 
350  for (auto t : trackRange)
351  {
352  if (selcount == 0)
353  {
354  rate = t->GetRate();
355  }
356  else
357  {
358  if (t->GetRate() != rate)
359  {
361  XO(
362 "To apply a filter, all selected tracks must have the same sample rate.") );
363  return false;
364  }
365  }
366  selcount++;
367  }
368 
369  return true;
370 }
371 
373 {
374  S.AddSpace(5);
375  S.SetSizerProportion(1);
376  S.StartMultiColumn(3, wxEXPAND);
377  {
378  S.SetStretchyCol(1);
379  S.SetStretchyRow(0);
380 
381  // -------------------------------------------------------------------
382  // ROW 1: Freq response panel and sliders for vertical scale
383  // -------------------------------------------------------------------
384 
385  S.StartVerticalLay();
386  {
388  S.GetParent(), wxID_ANY, wxVERTICAL,
389  wxSize{ 100, 100 }, // Ruler can't handle small sizes
390  RulerPanel::Range{ 30.0, -120.0 },
392  XO("dB"),
394  .LabelEdges(true)
395  );
396 
397  S.SetBorder(1);
398  S.AddSpace(1, 1);
399  S.Prop(1)
400  .Position(wxALIGN_RIGHT | wxTOP)
402  S.AddSpace(1, 1);
403  }
404  S.EndVerticalLay();
405 
407  S.GetParent(), wxID_ANY,
408  this, mLoFreq, mNyquist
409  );
410 
411  S.SetBorder(5);
412  S.Prop(1)
413  .Position(wxEXPAND | wxRIGHT)
414  .MinSize( { -1, -1 } )
415  .AddWindow(mPanel);
416 
417  S.StartVerticalLay();
418  {
419  S.AddVariableText(XO("+ dB"), false, wxCENTER);
421  .Name(XO("Max dB"))
422  .Style(wxSL_VERTICAL | wxSL_INVERSE)
423  .AddSlider( {}, 10, 20, 0);
424 #if wxUSE_ACCESSIBILITY
425  mdBMaxSlider->SetAccessible(safenew SliderAx(mdBMaxSlider, XO("%d dB")));
426 #endif
428  .Name(XO("Min dB"))
429  .Style(wxSL_VERTICAL | wxSL_INVERSE)
430  .AddSlider( {}, -10, -10, -120);
431 #if wxUSE_ACCESSIBILITY
432  mdBMinSlider->SetAccessible(safenew SliderAx(mdBMinSlider, XO("%d dB")));
433 #endif
434 
435  S.AddVariableText(XO("- dB"), false, wxCENTER);
436  }
437  S.EndVerticalLay();
438 
439  // -------------------------------------------------------------------
440  // ROW 2: Frequency ruler
441  // -------------------------------------------------------------------
442 
443  S.AddSpace(1, 1);
444 
446  S.GetParent(), wxID_ANY, wxHORIZONTAL,
447  wxSize{ 100, 100 }, // Ruler can't handle small sizes
448  RulerPanel::Range{ mLoFreq, mNyquist },
450  {},
452  .Log(true)
453  .Flip(true)
454  .LabelEdges(true)
455  );
456 
457  S.Prop(1)
458  .Position(wxEXPAND | wxALIGN_LEFT | wxRIGHT)
460 
461  S.AddSpace(1, 1);
462 
463  // -------------------------------------------------------------------
464  // ROW 3 and 4: Type, Order, Ripple, Subtype, Cutoff
465  // -------------------------------------------------------------------
466 
467  S.AddSpace(1, 1);
468  S.SetSizerProportion(0);
469  S.StartMultiColumn(8, wxALIGN_CENTER);
470  {
471  wxASSERT(nTypes == WXSIZEOF(kTypeStrings));
472 
474  .Focus()
475  .Validator<wxGenericValidator>(&mFilterType)
476  .MinSize( { -1, -1 } )
477  .AddChoice(XXO("&Filter Type:"),
479  );
480 
482  .Validator<wxGenericValidator>(&mOrderIndex)
483  .MinSize( { -1, -1 } )
484  /*i18n-hint: 'Order' means the complexity of the filter, and is a number between 1 and 10.*/
485  .AddChoice(XXO("O&rder:"),
486  []{
487  TranslatableStrings orders;
488  for (int i = 1; i <= 10; i++)
489  orders.emplace_back( Verbatim("%d").Format( i ) );
490  return orders;
491  }()
492  );
493  S.AddSpace(1, 1);
494 
495  mRippleCtlP = S.AddVariableText( XO("&Passband Ripple:"),
496  false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
497  mRippleCtl = S.Id(ID_Ripple)
498  .Name(XO("Passband Ripple (dB)"))
499  .Validator<FloatingPointValidator<float>>(
500  1, &mRipple, NumValidatorStyle::DEFAULT,
501  MIN_Passband, MAX_Passband)
502  .AddTextBox( {}, wxT(""), 10);
503  mRippleCtlU = S.AddVariableText(XO("dB"),
504  false, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
505 
507  .Validator<wxGenericValidator>(&mFilterSubtype)
508  .MinSize( { -1, -1 } )
509  .AddChoice(XXO("&Subtype:"),
511  );
512 
513  mCutoffCtl = S.Id(ID_Cutoff)
514  .Name(XO("Cutoff (Hz)"))
515  .Validator<FloatingPointValidator<float>>(
516  1, &mCutoff, NumValidatorStyle::DEFAULT,
517  MIN_Cutoff, mNyquist - 1)
518  .AddTextBox(XXO("C&utoff:"), wxT(""), 10);
519  S.AddUnits(XO("Hz"));
520 
522  S.AddVariableText(XO("Minimum S&topband Attenuation:"),
523  false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
525  .Name(XO("Minimum S&topband Attenuation (dB)"))
526  .Validator<FloatingPointValidator<float>>(
527  1, &mStopbandRipple, NumValidatorStyle::DEFAULT,
528  MIN_Stopband, MAX_Stopband)
529  .AddTextBox( {}, wxT(""), 10);
531  S.AddVariableText(XO("dB"),
532  false, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
533  }
534  S.EndMultiColumn();
535  S.AddSpace(1, 1);
536  }
537  S.EndMultiColumn();
538 
539  return;
540 }
541 
542 //
543 // Populate the window with relevant variables
544 //
546 {
547  mOrderIndex = mOrder - 1;
548 
549  if (!mUIParent->TransferDataToWindow())
550  {
551  return false;
552  }
553 
554  mdBMinSlider->SetValue((int) mdBMin);
555  mdBMin = 0.0; // force refresh in TransferGraphLimitsFromWindow()
556 
557  mdBMaxSlider->SetValue((int) mdBMax);
558  mdBMax = 0.0; // force refresh in TransferGraphLimitsFromWindow()
559 
561 
563 }
564 
566 {
567  if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
568  {
569  return false;
570  }
571 
572  mOrder = mOrderIndex + 1;
573 
574  CalcFilter();
575 
576  return true;
577 }
578 
579 // EffectScienFilter implementation
580 
581 //
582 // Retrieve data from the window
583 //
585 {
586  // Read the sliders and send to the panel
587  wxString tip;
588 
589  bool rr = false;
590  int dB = mdBMinSlider->GetValue();
591  if (dB != mdBMin) {
592  rr = true;
593  mdBMin = dB;
594  tip.Printf(_("%d dB"), (int)mdBMin);
595  mdBMinSlider->SetToolTip(tip);
596  }
597 
598  dB = mdBMaxSlider->GetValue();
599  if (dB != mdBMax) {
600  rr = true;
601  mdBMax = dB;
602  tip.Printf(_("%d dB"),(int)mdBMax);
603  mdBMaxSlider->SetToolTip(tip);
604  }
605 
606  if (rr) {
608  }
609 
610  // Refresh ruler if values have changed
611  if (rr) {
612  int w1, w2, h;
613  mdBRuler->ruler.GetMaxSize(&w1, &h);
615  mdBRuler->ruler.GetMaxSize(&w2, &h);
616  if( w1 != w2 ) // Reduces flicker
617  {
618  mdBRuler->SetSize(wxSize(w2,h));
619  mUIParent->Layout();
620  mfreqRuler->Refresh(false);
621  }
622  mdBRuler->Refresh(false);
623  }
624 
625  mPanel->Refresh(false);
626 
627  return true;
628 }
629 
631 {
632  switch (mFilterType)
633  {
634  case kButterworth:
636  break;
637  case kChebyshevTypeI:
639  break;
640  case kChebyshevTypeII:
642  break;
643  }
644 }
645 
647 {
648  float Magn;
649  if (Freq >= mNyquist)
650  Freq = mNyquist - 1; // prevent tan(PI/2)
651  float FreqWarped = tan (PI * Freq/(2*mNyquist));
652  if (mCutoff >= mNyquist)
653  mCutoff = mNyquist - 1;
654  float CutoffWarped = tan (PI * mCutoff/(2*mNyquist));
655  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
656 
657  switch (mFilterType)
658  {
659  case kButterworth: // Butterworth
660  default:
661  switch (mFilterSubtype)
662  {
663  case kLowPass: // lowpass
664  default:
665  if (FreqWarped/CutoffWarped > fOverflowThresh) // prevent pow() overflow
666  Magn = 0;
667  else
668  Magn = sqrt (1 / (1 + pow (FreqWarped/CutoffWarped, 2*mOrder)));
669  break;
670  case kHighPass: // highpass
671  if (FreqWarped/CutoffWarped > fOverflowThresh)
672  Magn = 1;
673  else
674  Magn = sqrt (pow (FreqWarped/CutoffWarped, 2*mOrder) / (1 + pow (FreqWarped/CutoffWarped, 2*mOrder)));
675  break;
676  }
677  break;
678 
679  case kChebyshevTypeI: // Chebyshev Type 1
680  double eps; eps = sqrt(pow (10.0, wxMax(0.001, mRipple)/10.0) - 1);
681  double chebyPolyVal;
682  switch (mFilterSubtype)
683  {
684  case 0: // lowpass
685  default:
686  chebyPolyVal = Biquad::ChebyPoly(mOrder, FreqWarped/CutoffWarped);
687  Magn = sqrt (1 / (1 + square(eps) * square(chebyPolyVal)));
688  break;
689  case 1:
690  chebyPolyVal = Biquad::ChebyPoly(mOrder, CutoffWarped/FreqWarped);
691  Magn = sqrt (1 / (1 + square(eps) * square(chebyPolyVal)));
692  break;
693  }
694  break;
695 
696  case kChebyshevTypeII: // Chebyshev Type 2
697  eps = 1 / sqrt(pow (10.0, wxMax(0.001, mStopbandRipple)/10.0) - 1);
698  switch (mFilterSubtype)
699  {
700  case kLowPass: // lowpass
701  default:
702  chebyPolyVal = Biquad::ChebyPoly(mOrder, CutoffWarped/FreqWarped);
703  Magn = sqrt (1 / (1 + 1 / (square(eps) * square(chebyPolyVal))));
704  break;
705  case kHighPass:
706  chebyPolyVal = Biquad::ChebyPoly(mOrder, FreqWarped/CutoffWarped);
707  Magn = sqrt (1 / (1 + 1 / (square(eps) * square(chebyPolyVal))));
708  break;
709  }
710  break;
711  }
712 
713  return Magn;
714 }
715 
716 void EffectScienFilter::OnOrder(wxCommandEvent & WXUNUSED(evt))
717 {
718  mOrderIndex = mFilterOrderCtl->GetSelection();
719  mOrder = mOrderIndex + 1; // 0..n-1 -> 1..n
720  mPanel->Refresh(false);
721 }
722 
723 void EffectScienFilter::OnFilterType(wxCommandEvent & WXUNUSED(evt))
724 {
725  mFilterType = mFilterTypeCtl->GetSelection();
727  mPanel->Refresh(false);
728 }
729 
730 void EffectScienFilter::OnFilterSubtype(wxCommandEvent & WXUNUSED(evt))
731 {
732  mFilterSubtype = mFilterSubTypeCtl->GetSelection();
733  mPanel->Refresh(false);
734 }
735 
736 void EffectScienFilter::OnCutoff(wxCommandEvent & WXUNUSED(evt))
737 {
738  if (!EnableApply(mUIParent->TransferDataFromWindow()))
739  {
740  return;
741  }
742 
743  mPanel->Refresh(false);
744 }
745 
746 void EffectScienFilter::OnRipple(wxCommandEvent & WXUNUSED(evt))
747 {
748  if (!EnableApply(mUIParent->TransferDataFromWindow()))
749  {
750  return;
751  }
752 
753  mPanel->Refresh(false);
754 }
755 
756 void EffectScienFilter::OnStopbandRipple(wxCommandEvent & WXUNUSED(evt))
757 {
758  if (!EnableApply(mUIParent->TransferDataFromWindow()))
759  {
760  return;
761  }
762 
763  mPanel->Refresh(false);
764 }
765 
766 void EffectScienFilter::OnSliderDBMIN(wxCommandEvent & WXUNUSED(evt))
767 {
769 }
770 
771 void EffectScienFilter::OnSliderDBMAX(wxCommandEvent & WXUNUSED(evt))
772 {
774 }
775 
776 void EffectScienFilter::OnSize(wxSizeEvent & evt)
777 {
778  // On Windows the Passband and Stopband boxes do not refresh properly
779  // on a resize...no idea why.
780  mUIParent->Refresh();
781  evt.Skip();
782 }
783 
785 {
786  bool ripple;
787  bool stop;
788 
789  if (FilterType == kButterworth) // Butterworth
790  {
791  ripple = false;
792  stop = false;
793  }
794  else if (FilterType == kChebyshevTypeI) // Chebyshev Type1
795  {
796  ripple = true;
797  stop = false;
798  }
799  else // Chebyshev Type2
800  {
801  ripple = false;
802  stop = true;
803  }
804 
805  mRippleCtlP->Enable(ripple);
806  mRippleCtl->Enable(ripple);
807  mRippleCtlU->Enable(ripple);
808  mStopbandRippleCtlP->Enable(stop);
809  mStopbandRippleCtl->Enable(stop);
810  mStopbandRippleCtlU->Enable(stop);
811 }
812 
813 //----------------------------------------------------------------------------
814 // EffectScienFilterPanel
815 //----------------------------------------------------------------------------
816 
817 BEGIN_EVENT_TABLE(EffectScienFilterPanel, wxPanelWrapper)
821 
823  wxWindow *parent, wxWindowID winid,
824  EffectScienFilter *effect, double lo, double hi)
825 : wxPanelWrapper(parent, winid, wxDefaultPosition, wxSize(400, 200))
826 {
827  mEffect = effect;
828  mParent = parent;
829 
830  mBitmap = NULL;
831  mWidth = 0;
832  mHeight = 0;
833  mLoFreq = 0.0;
834  mHiFreq = 0.0;
835  mDbMin = 0.0;
836  mDbMax = 0.0;
837 
838  SetFreqRange(lo, hi);
839 }
840 
842 {
843 }
844 
845 void EffectScienFilterPanel::SetFreqRange(double lo, double hi)
846 {
847  mLoFreq = lo;
848  mHiFreq = hi;
849  Refresh(false);
850 }
851 
852 void EffectScienFilterPanel::SetDbRange(double min, double max)
853 {
854  mDbMin = min;
855  mDbMax = max;
856  Refresh(false);
857 }
858 
860 {
861  return false;
862 }
863 
865 {
866  return false;
867 }
868 
869 void EffectScienFilterPanel::OnSize(wxSizeEvent & WXUNUSED(evt))
870 {
871  Refresh(false);
872 }
873 
874 void EffectScienFilterPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
875 {
876  wxPaintDC dc(this);
877  int width, height;
878  GetSize(&width, &height);
879 
880  if (!mBitmap || mWidth != width || mHeight != height)
881  {
882  mWidth = width;
883  mHeight = height;
884  mBitmap = std::make_unique<wxBitmap>(mWidth, mHeight,24);
885  }
886 
887  wxBrush bkgndBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
888 
889  wxMemoryDC memDC;
890  memDC.SelectObject(*mBitmap);
891 
892  wxRect bkgndRect;
893  bkgndRect.x = 0;
894  bkgndRect.y = 0;
895  bkgndRect.width = mWidth;
896  bkgndRect.height = mHeight;
897  memDC.SetBrush(bkgndBrush);
898  memDC.SetPen(*wxTRANSPARENT_PEN);
899  memDC.DrawRectangle(bkgndRect);
900 
901  bkgndRect.y = mHeight;
902  memDC.DrawRectangle(bkgndRect);
903 
904  wxRect border;
905  border.x = 0;
906  border.y = 0;
907  border.width = mWidth;
908  border.height = mHeight;
909 
910  memDC.SetBrush(*wxWHITE_BRUSH);
911  memDC.SetPen(*wxBLACK_PEN);
912  memDC.DrawRectangle(border);
913 
914  mEnvRect = border;
915  mEnvRect.Deflate(2, 2);
916 
917  // Pure blue x-axis line
918  memDC.SetPen(wxPen(theTheme.Colour(clrGraphLines), 1, wxPENSTYLE_SOLID));
919  int center = (int) (mEnvRect.height * mDbMax / (mDbMax - mDbMin) + 0.5);
920  AColor::Line(memDC,
921  mEnvRect.GetLeft(), mEnvRect.y + center,
922  mEnvRect.GetRight(), mEnvRect.y + center);
923 
924  //Now draw the actual response that you will get.
925  //mFilterFunc has a linear scale, window has a log one so we have to fiddle about
926  memDC.SetPen(wxPen(theTheme.Colour(clrResponseLines), 3, wxPENSTYLE_SOLID));
927  double scale = (double) mEnvRect.height / (mDbMax - mDbMin); // pixels per dB
928  double yF; // gain at this freq
929 
930  double loLog = log10(mLoFreq);
931  double step = log10(mHiFreq) - loLog;
932  step /= ((double) mEnvRect.width - 1.0);
933  double freq; // actual freq corresponding to x position
934  int x, y, xlast = 0, ylast = 0;
935  for (int i = 0; i < mEnvRect.width; i++)
936  {
937  x = mEnvRect.x + i;
938  freq = pow(10.0, loLog + i * step); //Hz
939  yF = mEffect->FilterMagnAtFreq (freq);
940  yF = LINEAR_TO_DB(yF);
941 
942  if (yF < mDbMin)
943  {
944  yF = mDbMin;
945  }
946 
947  yF = center-scale * yF;
948  if (yF > mEnvRect.height)
949  {
950  yF = (double) mEnvRect.height - 1.0;
951  }
952  if (yF < 0.0)
953  {
954  yF = 0.0;
955  }
956  y = (int) (yF + 0.5);
957 
958  if (i != 0 && (y < mEnvRect.height - 1 || ylast < mEnvRect.y + mEnvRect.height - 1))
959  {
960  AColor::Line(memDC, xlast, ylast, x, mEnvRect.y + y);
961  }
962  xlast = x;
963  ylast = mEnvRect.y + y;
964  }
965 
966  memDC.SetPen(*wxBLACK_PEN);
967  mEffect->mfreqRuler->ruler.DrawGrid(memDC, mEnvRect.height + 2, true, true, 0, 1);
968  mEffect->mdBRuler->ruler.DrawGrid(memDC, mEnvRect.width + 2, true, true, 1, 2);
969 
970  dc.Blit(0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE);
971 
972  memDC.SelectObject(wxNullBitmap);
973 }
kSubTypes
kSubTypes
Definition: ScienFilter.cpp:108
ID_Type
@ ID_Type
Definition: ScienFilter.cpp:81
EffectScienFilter::TransferDataToWindow
bool TransferDataToWindow() override
Definition: ScienFilter.cpp:545
TranslatableString
Definition: Types.h:290
CommandParameters
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
Definition: EffectAutomationParameters.h:67
EffectScienFilter::OnCutoff
void OnCutoff(wxCommandEvent &evt)
Definition: ScienFilter.cpp:736
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1177
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:68
EffectTypeProcess
@ EffectTypeProcess
Definition: EffectInterface.h:59
ShuttleGui::Focus
ShuttleGui & Focus(bool focused=true)
Definition: ShuttleGui.h:651
kHighPass
@ kHighPass
Definition: ScienFilter.cpp:110
EffectScienFilterPanel::AcceptsFocusFromKeyboard
bool AcceptsFocusFromKeyboard() const
Definition: ScienFilter.cpp:864
RulerPanel
RulerPanel class allows you to work with a Ruler like any other wxWindow.
Definition: Ruler.h:228
Param
Param(Type, int, wxT("FilterType"), kButterworth, 0, nTypes - 1, 1)
Effect::EnableApply
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1925
EffectScienFilter
An Effect that applies 'classical' IIR filters.
Definition: ScienFilter.h:33
EffectScienFilter::mdBMax
double mdBMax
Definition: ScienFilter.h:99
EffectScienFilter::mLoFreq
double mLoFreq
Definition: ScienFilter.h:103
Ruler::LinearDBFormat
@ LinearDBFormat
Definition: Ruler.h:34
EffectScienFilterPanel::mWidth
int mWidth
Definition: ScienFilter.h:164
EffectScienFilter::mOrderIndex
int mOrderIndex
Definition: ScienFilter.h:96
EffectScienFilterPanel::mEnvRect
wxRect mEnvRect
Definition: ScienFilter.h:163
EffectScienFilterPanel::OnSize
void OnSize(wxSizeEvent &evt)
Definition: ScienFilter.cpp:869
EffectScienFilter::mRippleCtlU
wxStaticText * mRippleCtlU
Definition: ScienFilter.h:112
EffectScienFilter::ProcessInitialize
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
Definition: ScienFilter.cpp:220
EffectScienFilter::~EffectScienFilter
virtual ~EffectScienFilter()
Definition: ScienFilter.cpp:178
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:67
EffectScienFilter::mFilterType
int mFilterType
Definition: ScienFilter.h:93
Effect::MessageBox
int MessageBox(const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
Definition: Effect.cpp:2478
EffectScienFilterPanel::mHeight
int mHeight
Definition: ScienFilter.h:165
kChebyshevTypeII
@ kChebyshevTypeII
Definition: ScienFilter.cpp:93
EffectScienFilter::OnSliderDBMAX
void OnSliderDBMAX(wxCommandEvent &evt)
Definition: ScienFilter.cpp:771
EffectScienFilter::mpBiquad
ArrayOf< Biquad > mpBiquad
Definition: ScienFilter.h:97
EffectScienFilter::ManualPage
wxString ManualPage() override
Definition: ScienFilter.cpp:195
wxPanelWrapper
Definition: wxPanelWrapper.h:41
EffectScienFilter::OnSize
void OnSize(wxSizeEvent &evt)
Definition: ScienFilter.cpp:776
ID_StopbandRipple
@ ID_StopbandRipple
Definition: ScienFilter.cpp:86
ID_Ripple
@ ID_Ripple
Definition: ScienFilter.cpp:84
square
#define square(a)
Definition: ScienFilter.cpp:74
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:112
Biquad::nSubTypes
@ nSubTypes
Definition: Biquad.h:63
EffectScienFilter::mCutoff
float mCutoff
Definition: ScienFilter.h:90
EffectScienFilter::mNyquist
double mNyquist
Definition: ScienFilter.h:104
Validator
A Validator is an object which checks whether a wxVariant satisfies a certain criterion....
Definition: Validators.h:53
ShuttleGui::AddSpace
wxSizerItem * AddSpace(int width, int height, int prop=0)
Definition: ShuttleGui.cpp:2421
kSubTypeStrings
static const EnumValueSymbol kSubTypeStrings[nSubTypes]
Definition: ScienFilter.cpp:114
EffectScienFilter::EnableDisableRippleCtl
void EnableDisableRippleCtl(int FilterType)
Definition: ScienFilter.cpp:784
ShuttleGui::MinSize
ShuttleGui & MinSize()
Definition: ShuttleGui.h:740
XO
#define XO(s)
Definition: Internat.h:32
ID_SubType
@ ID_SubType
Definition: ScienFilter.cpp:82
ShuttleParams
Shuttle that deals with parameters. This is a base class with lots of virtual functions that do nothi...
Definition: Shuttle.h:61
ID_dBMin
@ ID_dBMin
Definition: ScienFilter.cpp:80
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1212
EffectScienFilter::OnStopbandRipple
void OnStopbandRipple(wxCommandEvent &evt)
Definition: ScienFilter.cpp:756
CommandParameters::WriteFloat
bool WriteFloat(const wxString &key, float f)
Definition: EffectAutomationParameters.h:156
nTypes
@ nTypes
Definition: ScienFilter.cpp:94
EffectScienFilterPanel::~EffectScienFilterPanel
virtual ~EffectScienFilterPanel()
Definition: ScienFilter.cpp:841
EffectScienFilter::OnRipple
void OnRipple(wxCommandEvent &evt)
Definition: ScienFilter.cpp:746
Effect::SaveUserPreset
bool SaveUserPreset(const RegistryPath &name) override
Definition: Effect.cpp:569
EffectScienFilter::CalcFilter
void CalcFilter()
Definition: ScienFilter.cpp:630
EffectScienFilter::OnSliderDBMIN
void OnSliderDBMIN(wxCommandEvent &evt)
Definition: ScienFilter.cpp:766
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterface.h:60
EffectScienFilter::GetAutomationParameters
bool GetAutomationParameters(CommandParameters &parms) override
Definition: ScienFilter.cpp:249
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2248
EffectScienFilter::mFilterOrderCtl
wxChoice * mFilterOrderCtl
Definition: ScienFilter.h:122
EffectScienFilterPanel
EffectScienFilterPanel is used with EffectScienFilter and controls a graph for EffectScienFilter.
Definition: ScienFilter.h:133
EffectScienFilter::mfreqRuler
RulerPanel * mfreqRuler
Definition: ScienFilter.h:125
EffectScienFilter::FilterMagnAtFreq
float FilterMagnAtFreq(float Freq)
Definition: ScienFilter.cpp:646
kTypeStrings
static const EnumValueSymbol kTypeStrings[nTypes]
Definition: ScienFilter.cpp:97
Ruler::GetMaxSize
void GetMaxSize(wxCoord *width, wxCoord *height)
Definition: Ruler.cpp:1603
RulerPanel::Range
std::pair< double, double > Range
Definition: Ruler.h:232
ShuttleGui::Style
ShuttleGui & Style(long iStyle)
Definition: ShuttleGui.h:734
PI
#define PI
Definition: ScienFilter.cpp:70
Effect::mProjectRate
double mProjectRate
Definition: Effect.h:457
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: Types.h:555
ReadAndVerifyEnum
#define ReadAndVerifyEnum(name, list, listSize)
Definition: Effect.h:620
ShuttleGuiBase::SetSizerProportion
void SetSizerProportion(int iProp)
Definition: ShuttleGui.h:498
ReadAndVerifyInt
#define ReadAndVerifyInt(name)
Definition: Effect.h:631
EffectScienFilter::OnOrder
void OnOrder(wxCommandEvent &evt)
Definition: ScienFilter.cpp:716
XXO
#define XXO(s)
Definition: Internat.h:45
Effect::inputTracks
const TrackList * inputTracks() const
Definition: Effect.h:462
EffectScienFilter::GetType
EffectType GetType() override
Definition: ScienFilter.cpp:203
ID_Order
@ ID_Order
Definition: ScienFilter.cpp:83
EffectScienFilter::mdBMaxSlider
wxSlider * mdBMaxSlider
Definition: ScienFilter.h:108
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1203
kChebyshevTypeI
@ kChebyshevTypeI
Definition: ScienFilter.cpp:92
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1196
EffectScienFilterPanel::OnPaint
void OnPaint(wxPaintEvent &evt)
Definition: ScienFilter.cpp:874
EffectScienFilterPanel::mDbMax
double mDbMax
Definition: ScienFilter.h:160
EffectScienFilter::mStopbandRippleCtl
wxTextCtrl * mStopbandRippleCtl
Definition: ScienFilter.h:117
EffectScienFilterPanel::mBitmap
std::unique_ptr< wxBitmap > mBitmap
Definition: ScienFilter.h:162
ShuttleGuiBase::AddUnits
void AddUnits(const TranslatableString &Prompt, int wrapWidth=0)
Left aligned text string.
Definition: ShuttleGui.cpp:256
ChannelNames
enum ChannelName * ChannelNames
ID_Cutoff
@ ID_Cutoff
Definition: ScienFilter.cpp:85
Msgids
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Definition: Internat.cpp:267
EffectScienFilter::mFilterSubtype
int mFilterSubtype
Definition: ScienFilter.h:94
EffectScienFilter::mFilterSubTypeCtl
wxChoice * mFilterSubTypeCtl
Definition: ScienFilter.h:121
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:503
ShuttleGui::Validator
ShuttleGui & Validator(const Factory &f)
Definition: ShuttleGui.h:685
Ruler::SetRange
void SetRange(double min, double max)
Definition: Ruler.cpp:188
EffectScienFilterPanel::SetFreqRange
void SetFreqRange(double lo, double hi)
Definition: ScienFilter.cpp:845
Ruler::IntFormat
@ IntFormat
Definition: Ruler.h:30
EffectScienFilter::OnFilterSubtype
void OnFilterSubtype(wxCommandEvent &evt)
Definition: ScienFilter.cpp:730
EffectScienFilter::Symbol
static const ComponentInterfaceSymbol Symbol
Definition: ScienFilter.h:35
EffectScienFilter::mStopbandRippleCtlP
wxStaticText * mStopbandRippleCtlP
Definition: ScienFilter.h:116
ShuttleGui::Prop
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:732
ShuttleGuiBase::AddSlider
wxSlider * AddSlider(const TranslatableString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:582
RulerPanel::Options::LabelEdges
Options & LabelEdges(bool l)
Definition: Ruler.h:250
EffectScienFilter::SetAutomationParameters
bool SetAutomationParameters(CommandParameters &parms) override
Definition: ScienFilter.cpp:261
Effect::GetCurrentSettingsGroup
RegistryPath GetCurrentSettingsGroup() override
Definition: Effect.cpp:865
RulerPanel::Options::Flip
Options & Flip(bool f)
Definition: Ruler.h:247
EffectScienFilter::GetAudioInCount
unsigned GetAudioInCount() override
Definition: ScienFilter.cpp:210
EffectScienFilter::DefineParams
bool DefineParams(ShuttleParams &S) override
Definition: ScienFilter.cpp:239
EffectScienFilter::Init
bool Init() override
Definition: ScienFilter.cpp:334
LoadEffects.h
EffectScienFilter::mdBMin
double mdBMin
Definition: ScienFilter.h:100
Biquad::CalcChebyshevType1Filter
static ArrayOf< Biquad > CalcChebyshevType1Filter(int order, double fn, double fc, double ripple, int type)
Definition: Biquad.cpp:145
kButterworth
@ kButterworth
Definition: ScienFilter.cpp:91
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:670
EffectScienFilter::mPanel
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:106
EffectScienFilterPanel::mHiFreq
double mHiFreq
Definition: ScienFilter.h:157
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow)
Definition: ShuttleGui.cpp:292
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:151
EffectScienFilterPanel::SetDbRange
void SetDbRange(double min, double max)
Definition: ScienFilter.cpp:852
EffectScienFilter::mdBMinSlider
wxSlider * mdBMinSlider
Definition: ScienFilter.h:107
EffectScienFilter::GetSymbol
ComponentInterfaceSymbol GetSymbol() override
Definition: ScienFilter.cpp:184
BuiltinEffectsModule::Registration
Definition: LoadEffects.h:40
EffectScienFilter::mRipple
float mRipple
Definition: ScienFilter.h:91
Biquad::kHighPass
@ kHighPass
Definition: Biquad.h:62
ShuttleGui::Position
ShuttleGui & Position(int flags)
Definition: ShuttleGui.h:719
Effect::mUIParent
wxWindow * mUIParent
Definition: Effect.h:477
_
#define _(s)
Definition: Internat.h:76
sampleCount
Definition: Types.h:589
EffectScienFilterPanel::mEffect
EffectScienFilter * mEffect
Definition: ScienFilter.h:153
Verbatim
TranslatableString Verbatim(wxString str)
Definition: Types.h:581
EffectScienFilter::GetDescription
TranslatableString GetDescription() override
Definition: ScienFilter.cpp:189
EffectScienFilter::TransferDataFromWindow
bool TransferDataFromWindow() override
Definition: ScienFilter.cpp:565
EffectScienFilter::Startup
bool Startup() override
Definition: ScienFilter.cpp:286
EffectScienFilter::ProcessBlock
size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override
Definition: ScienFilter.cpp:228
EffectScienFilter::mCutoffCtl
wxTextCtrl * mCutoffCtl
Definition: ScienFilter.h:114
nSubTypes
@ nSubTypes
Definition: ScienFilter.cpp:111
Biquad::kLowPass
@ kLowPass
Definition: Biquad.h:61
RulerPanel::Options
Definition: Ruler.h:234
EffectScienFilter::mRippleCtlP
wxStaticText * mRippleCtlP
Definition: ScienFilter.h:110
EffectScienFilter::mOrder
int mOrder
Definition: ScienFilter.h:95
ID_dBMax
@ ID_dBMax
Definition: ScienFilter.cpp:79
RulerPanel::ruler
Ruler ruler
Definition: Ruler.h:288
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1192
LINEAR_TO_DB
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:721
kLowPass
@ kLowPass
Definition: ScienFilter.cpp:109
EffectScienFilter::mStopbandRippleCtlU
wxStaticText * mStopbandRippleCtlU
Definition: ScienFilter.h:118
EffectScienFilterPanel::AcceptsFocus
bool AcceptsFocus() const
Definition: ScienFilter.cpp:859
EffectScienFilter::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S) override
Definition: ScienFilter.cpp:372
theTheme
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:201
EffectScienFilter::mStopbandRipple
float mStopbandRipple
Definition: ScienFilter.h:92
Biquad::ChebyPoly
static double ChebyPoly(int Order, double NormFreq)
Definition: Biquad.cpp:328
EffectScienFilterPanel::mLoFreq
double mLoFreq
Definition: ScienFilter.h:156
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:497
TranslatableString::Format
TranslatableString & Format(Args &&...args) &
Definition: Types.h:363
ID_FilterPanel
@ ID_FilterPanel
Definition: ScienFilter.cpp:78
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:456
kTypes
kTypes
Definition: Noise.cpp:34
Biquad::CalcButterworthFilter
static ArrayOf< Biquad > CalcButterworthFilter(int order, double fn, double fc, int type)
Definition: Biquad.cpp:63
EffectScienFilter::EffectScienFilterPanel
friend class EffectScienFilterPanel
Definition: ScienFilter.h:129
EffectType
EffectType
Definition: EffectInterface.h:55
safenew
#define safenew
Definition: MemoryX.h:8
Biquad::CalcChebyshevType2Filter
static ArrayOf< Biquad > CalcChebyshevType2Filter(int order, double fn, double fc, double ripple, int type)
Definition: Biquad.cpp:227
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:195
EffectScienFilterPanel::mDbMin
double mDbMin
Definition: ScienFilter.h:159
Ruler::DrawGrid
void DrawGrid(wxDC &dc, int length, bool minor=true, bool major=true, int xOffset=0, int yOffset=0) const
Definition: Ruler.cpp:1521
EffectScienFilter::mFilterTypeCtl
wxChoice * mFilterTypeCtl
Definition: ScienFilter.h:120
ScienFilter.h
TrackList::Selected
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1371
anonymous_namespace{CompareAudioCommand.cpp}::reg
BuiltinCommandsModule::Registration< CompareAudioCommand > reg
Definition: CompareAudioCommand.cpp:41
EffectScienFilter::TransferGraphLimitsFromWindow
bool TransferGraphLimitsFromWindow()
Definition: ScienFilter.cpp:584
END_EVENT_TABLE
END_EVENT_TABLE()
ShuttleGuiBase::SetStretchyRow
void SetStretchyRow(int i)
Used to modify an already placed FlexGridSizer to make a row stretchy.
Definition: ShuttleGui.cpp:205
RulerPanel::Options::Log
Options & Log(bool l)
Definition: Ruler.h:244
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:638
EffectScienFilter::OnFilterType
void OnFilterType(wxCommandEvent &evt)
Definition: ScienFilter.cpp:723
ReadAndVerifyFloat
#define ReadAndVerifyFloat(name)
Definition: Effect.h:633
EffectScienFilter::mRippleCtl
wxTextCtrl * mRippleCtl
Definition: ScienFilter.h:111
EffectScienFilter::mdBRuler
RulerPanel * mdBRuler
Definition: ScienFilter.h:124
EffectScienFilter::GetAudioOutCount
unsigned GetAudioOutCount() override
Definition: ScienFilter.cpp:215