Audacity 3.2.0
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
41#include <wx/setup.h> // for wxUSE_* macros
42
43#include <wx/brush.h>
44#include <wx/choice.h>
45#include <wx/dcclient.h>
46#include <wx/dcmemory.h>
47#include <wx/intl.h>
48#include <wx/settings.h>
49#include <wx/slider.h>
50#include <wx/stattext.h>
51#include <wx/utils.h>
52#include <wx/valgen.h>
53
54#include "AColor.h"
55#include "AllThemeResources.h"
57#include "Prefs.h"
58#include "Project.h"
59#include "../ShuttleGui.h"
60#include "Theme.h"
61#include "../WaveTrack.h"
62#include "../widgets/valnum.h"
63#include "../widgets/AudacityMessageBox.h"
64#include "../widgets/Ruler.h"
65#include "../widgets/WindowAccessible.h"
66
67#if !defined(M_PI)
68#define PI = 3.1415926535897932384626433832795
69#else
70#define PI M_PI
71#endif
72#define square(a) ((a)*(a))
73
74enum
75{
85};
86
88{
89 /*i18n-hint: Butterworth is the name of the person after whom the filter type is named.*/
90 { XO("Butterworth") },
91 /*i18n-hint: Chebyshev is the name of the person after whom the filter type is named.*/
92 { XO("Chebyshev Type I") },
93 /*i18n-hint: Chebyshev is the name of the person after whom the filter type is named.*/
94 { XO("Chebyshev Type II") }
95};
96
98{
99 // These are acceptable dual purpose internal/visible names
100 { XO("Lowpass") },
101 { XO("Highpass") }
102};
103
105{
108 > parameters{
110 bool updating){
111 if (updating) {
112 e.mOrderIndex = e.mOrder - 1;
113 e.CalcFilter();
114 }
115 return true;
116 },
117 };
118 return parameters;
119}
120
121//----------------------------------------------------------------------------
122// EffectScienFilter
123//----------------------------------------------------------------------------
124
126{ XO("Classic Filters") };
127
128#ifdef EXPERIMENTAL_SCIENCE_FILTERS
129// true argument means don't automatically enable this effect
131#endif
132
133BEGIN_EVENT_TABLE(EffectScienFilter, wxEvtHandler)
135
145
147{
148 Parameters().Reset(*this);
149 SetLinearEffectFlag(true);
150
151 mOrderIndex = mOrder - 1;
152
153 mdBMin = -30.0;
154 mdBMax = 30.0;
155
156 mLoFreq = 20; // Lowest frequency to display in response graph
157 mNyquist = 44100.0 / 2.0; // only used during initialization, updated when effect is used
158}
159
161{
162}
163
164// ComponentInterface implementation
165
167{
168 return Symbol;
169}
170
172{
173 /* i18n-hint: "infinite impulse response" */
174 return XO("Performs IIR filtering that emulates analog filters");
175}
176
178{
179 return L"Classic_Filters";
180}
181
182
183// EffectDefinitionInterface implementation
184
186{
187 return EffectTypeProcess;
188}
189
191{
192 return 1;
193}
194
196{
197 return 1;
198}
199
201 EffectSettings &, double, sampleCount, ChannelNames chanMap)
202{
203 for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
204 mpBiquad[iPair].Reset();
205 return true;
206}
207
209 const float *const *inBlock, float *const *outBlock, size_t blockLen)
210{
211 const float *ibuf = inBlock[0];
212 for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
213 {
214 mpBiquad[iPair].Process(ibuf, outBlock[0], blockLen);
215 ibuf = outBlock[0];
216 }
217
218 return blockLen;
219}
220
221// Effect implementation
222
224{
225 int selcount = 0;
226 double rate = 0.0;
227
228 auto trackRange = inputTracks()->Selected< const WaveTrack >();
229
230 {
231 auto t = *trackRange.begin();
232 mNyquist =
233 (t
234 ? t->GetRate()
235 : mProjectRate)
236 / 2.0;
237 }
238
239 for (auto t : trackRange)
240 {
241 if (selcount == 0)
242 {
243 rate = t->GetRate();
244 }
245 else
246 {
247 if (t->GetRate() != rate)
248 {
250 XO(
251"To apply a filter, all selected tracks must have the same sample rate.") );
252 return false;
253 }
254 }
255 selcount++;
256 }
257
258 return true;
259}
260
261std::unique_ptr<EffectUIValidator> EffectScienFilter::PopulateOrExchange(
263{
264 S.AddSpace(5);
265 S.SetSizerProportion(1);
266 S.StartMultiColumn(3, wxEXPAND);
267 {
268 S.SetStretchyCol(1);
269 S.SetStretchyRow(0);
270
271 // -------------------------------------------------------------------
272 // ROW 1: Freq response panel and sliders for vertical scale
273 // -------------------------------------------------------------------
274
275 S.StartVerticalLay();
276 {
278 S.GetParent(), wxID_ANY, wxVERTICAL,
279 wxSize{ 100, 100 }, // Ruler can't handle small sizes
280 RulerPanel::Range{ 30.0, -120.0 },
282 XO("dB"),
284 .LabelEdges(true)
285 );
286
287 S.SetBorder(1);
288 S.AddSpace(1, 1);
289 S.Prop(1)
290 .Position(wxALIGN_RIGHT | wxTOP)
291 .AddWindow(mdBRuler);
292 S.AddSpace(1, 1);
293 }
294 S.EndVerticalLay();
295
297 S.GetParent(), wxID_ANY,
298 this, mLoFreq, mNyquist
299 );
300
301 S.SetBorder(5);
302 S.Prop(1)
303 .Position(wxEXPAND | wxRIGHT)
304 .MinSize( { -1, -1 } )
305 .AddWindow(mPanel);
306
307 S.StartVerticalLay();
308 {
309 S.AddVariableText(XO("+ dB"), false, wxCENTER);
311 .Name(XO("Max dB"))
312 .Style(wxSL_VERTICAL | wxSL_INVERSE)
313 .AddSlider( {}, 10, 20, 0);
314#if wxUSE_ACCESSIBILITY
315 mdBMaxSlider->SetAccessible(safenew SliderAx(mdBMaxSlider, XO("%d dB")));
316#endif
318 .Name(XO("Min dB"))
319 .Style(wxSL_VERTICAL | wxSL_INVERSE)
320 .AddSlider( {}, -10, -10, -120);
321#if wxUSE_ACCESSIBILITY
322 mdBMinSlider->SetAccessible(safenew SliderAx(mdBMinSlider, XO("%d dB")));
323#endif
324
325 S.AddVariableText(XO("- dB"), false, wxCENTER);
326 }
327 S.EndVerticalLay();
328
329 // -------------------------------------------------------------------
330 // ROW 2: Frequency ruler
331 // -------------------------------------------------------------------
332
333 S.AddSpace(1, 1);
334
336 S.GetParent(), wxID_ANY, wxHORIZONTAL,
337 wxSize{ 100, 100 }, // Ruler can't handle small sizes
338 RulerPanel::Range{ mLoFreq, mNyquist },
340 {},
342 .Log(true)
343 .Flip(true)
344 .LabelEdges(true)
345 );
346
347 S.Prop(1)
348 .Position(wxEXPAND | wxALIGN_LEFT | wxRIGHT)
349 .AddWindow(mfreqRuler);
350
351 S.AddSpace(1, 1);
352
353 // -------------------------------------------------------------------
354 // ROW 3 and 4: Type, Order, Ripple, Subtype, Cutoff
355 // -------------------------------------------------------------------
356
357 S.AddSpace(1, 1);
358 S.SetSizerProportion(0);
359 S.StartMultiColumn(8, wxALIGN_CENTER);
360 {
361 wxASSERT(nTypes == WXSIZEOF(kTypeStrings));
362
364 .Focus()
365 .Validator<wxGenericValidator>(&mFilterType)
366 .MinSize( { -1, -1 } )
367 .AddChoice(XXO("&Filter Type:"),
369 );
370
372 .Validator<wxGenericValidator>(&mOrderIndex)
373 .MinSize( { -1, -1 } )
374 /*i18n-hint: 'Order' means the complexity of the filter, and is a number between 1 and 10.*/
375 .AddChoice(XXO("O&rder:"),
376 []{
377 TranslatableStrings orders;
378 for (int i = 1; i <= 10; i++)
379 orders.emplace_back( Verbatim("%d").Format( i ) );
380 return orders;
381 }()
382 );
383 S.AddSpace(1, 1);
384
385 mRippleCtlP = S.AddVariableText( XO("&Passband Ripple:"),
386 false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
388 .Name(XO("Passband Ripple (dB)"))
389 .Validator<FloatingPointValidator<float>>(
390 1, &mRipple, NumValidatorStyle::DEFAULT,
392 .AddTextBox( {}, L"", 10);
393 mRippleCtlU = S.AddVariableText(XO("dB"),
394 false, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
395
397 .Validator<wxGenericValidator>(&mFilterSubtype)
398 .MinSize( { -1, -1 } )
399 .AddChoice(XXO("&Subtype:"),
401 );
402
404 .Name(XO("Cutoff (Hz)"))
405 .Validator<FloatingPointValidator<float>>(
406 1, &mCutoff, NumValidatorStyle::DEFAULT,
407 Cutoff.min, mNyquist - 1)
408 .AddTextBox(XXO("C&utoff:"), L"", 10);
409 S.AddUnits(XO("Hz"));
410
412 S.AddVariableText(XO("Minimum S&topband Attenuation:"),
413 false, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
415 .Name(XO("Minimum S&topband Attenuation (dB)"))
416 .Validator<FloatingPointValidator<float>>(
417 1, &mStopbandRipple, NumValidatorStyle::DEFAULT,
419 .AddTextBox( {}, L"", 10);
421 S.AddVariableText(XO("dB"),
422 false, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
423 }
424 S.EndMultiColumn();
425 S.AddSpace(1, 1);
426 }
427 S.EndMultiColumn();
428
429 return nullptr;
430}
431
432//
433// Populate the window with relevant variables
434//
436{
437 mOrderIndex = mOrder - 1;
438
439 mdBMinSlider->SetValue((int) mdBMin);
440 mdBMin = 0.0; // force refresh in TransferGraphLimitsFromWindow()
441
442 mdBMaxSlider->SetValue((int) mdBMax);
443 mdBMax = 0.0; // force refresh in TransferGraphLimitsFromWindow()
444
446
448}
449
451{
452 mOrder = mOrderIndex + 1;
453
454 CalcFilter();
455
456 return true;
457}
458
459// EffectScienFilter implementation
460
461//
462// Retrieve data from the window
463//
465{
466 // Read the sliders and send to the panel
467 wxString tip;
468
469 bool rr = false;
470 int dB = mdBMinSlider->GetValue();
471 if (dB != mdBMin) {
472 rr = true;
473 mdBMin = dB;
474 tip.Printf(_("%d dB"), (int)mdBMin);
475 mdBMinSlider->SetToolTip(tip);
476 }
477
478 dB = mdBMaxSlider->GetValue();
479 if (dB != mdBMax) {
480 rr = true;
481 mdBMax = dB;
482 tip.Printf(_("%d dB"),(int)mdBMax);
483 mdBMaxSlider->SetToolTip(tip);
484 }
485
486 if (rr) {
488 }
489
490 // Refresh ruler if values have changed
491 if (rr) {
492 int w1, w2, h;
493 mdBRuler->ruler.GetMaxSize(&w1, &h);
495 mdBRuler->ruler.GetMaxSize(&w2, &h);
496 if( w1 != w2 ) // Reduces flicker
497 {
498 mdBRuler->SetSize(wxSize(w2,h));
499 mUIParent->Layout();
500 mfreqRuler->Refresh(false);
501 }
502 mdBRuler->Refresh(false);
503 }
504
505 mPanel->Refresh(false);
506
507 return true;
508}
509
511{
512 switch (mFilterType)
513 {
514 case kButterworth:
516 break;
517 case kChebyshevTypeI:
519 break;
520 case kChebyshevTypeII:
522 break;
523 }
524}
525
527{
528 float Magn;
529 if (Freq >= mNyquist)
530 Freq = mNyquist - 1; // prevent tan(PI/2)
531 float FreqWarped = tan (PI * Freq/(2*mNyquist));
532 if (mCutoff >= mNyquist)
533 mCutoff = mNyquist - 1;
534 float CutoffWarped = tan (PI * mCutoff/(2*mNyquist));
535 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
536
537 switch (mFilterType)
538 {
539 case kButterworth: // Butterworth
540 default:
541 switch (mFilterSubtype)
542 {
543 case kLowPass: // lowpass
544 default:
545 if (FreqWarped/CutoffWarped > fOverflowThresh) // prevent pow() overflow
546 Magn = 0;
547 else
548 Magn = sqrt (1 / (1 + pow (FreqWarped/CutoffWarped, 2*mOrder)));
549 break;
550 case kHighPass: // highpass
551 if (FreqWarped/CutoffWarped > fOverflowThresh)
552 Magn = 1;
553 else
554 Magn = sqrt (pow (FreqWarped/CutoffWarped, 2*mOrder) / (1 + pow (FreqWarped/CutoffWarped, 2*mOrder)));
555 break;
556 }
557 break;
558
559 case kChebyshevTypeI: // Chebyshev Type 1
560 double eps; eps = sqrt(pow (10.0, wxMax(0.001, mRipple)/10.0) - 1);
561 double chebyPolyVal;
562 switch (mFilterSubtype)
563 {
564 case 0: // lowpass
565 default:
566 chebyPolyVal = Biquad::ChebyPoly(mOrder, FreqWarped/CutoffWarped);
567 Magn = sqrt (1 / (1 + square(eps) * square(chebyPolyVal)));
568 break;
569 case 1:
570 chebyPolyVal = Biquad::ChebyPoly(mOrder, CutoffWarped/FreqWarped);
571 Magn = sqrt (1 / (1 + square(eps) * square(chebyPolyVal)));
572 break;
573 }
574 break;
575
576 case kChebyshevTypeII: // Chebyshev Type 2
577 eps = 1 / sqrt(pow (10.0, wxMax(0.001, mStopbandRipple)/10.0) - 1);
578 switch (mFilterSubtype)
579 {
580 case kLowPass: // lowpass
581 default:
582 chebyPolyVal = Biquad::ChebyPoly(mOrder, CutoffWarped/FreqWarped);
583 Magn = sqrt (1 / (1 + 1 / (square(eps) * square(chebyPolyVal))));
584 break;
585 case kHighPass:
586 chebyPolyVal = Biquad::ChebyPoly(mOrder, FreqWarped/CutoffWarped);
587 Magn = sqrt (1 / (1 + 1 / (square(eps) * square(chebyPolyVal))));
588 break;
589 }
590 break;
591 }
592
593 return Magn;
594}
595
596void EffectScienFilter::OnOrder(wxCommandEvent & WXUNUSED(evt))
597{
598 mOrderIndex = mFilterOrderCtl->GetSelection();
599 mOrder = mOrderIndex + 1; // 0..n-1 -> 1..n
600 mPanel->Refresh(false);
601}
602
603void EffectScienFilter::OnFilterType(wxCommandEvent & WXUNUSED(evt))
604{
605 mFilterType = mFilterTypeCtl->GetSelection();
607 mPanel->Refresh(false);
608}
609
610void EffectScienFilter::OnFilterSubtype(wxCommandEvent & WXUNUSED(evt))
611{
612 mFilterSubtype = mFilterSubTypeCtl->GetSelection();
613 mPanel->Refresh(false);
614}
615
616void EffectScienFilter::OnCutoff(wxCommandEvent & WXUNUSED(evt))
617{
618 if (!EnableApply(mUIParent->TransferDataFromWindow()))
619 {
620 return;
621 }
622
623 mPanel->Refresh(false);
624}
625
626void EffectScienFilter::OnRipple(wxCommandEvent & WXUNUSED(evt))
627{
628 if (!EnableApply(mUIParent->TransferDataFromWindow()))
629 {
630 return;
631 }
632
633 mPanel->Refresh(false);
634}
635
636void EffectScienFilter::OnStopbandRipple(wxCommandEvent & WXUNUSED(evt))
637{
638 if (!EnableApply(mUIParent->TransferDataFromWindow()))
639 {
640 return;
641 }
642
643 mPanel->Refresh(false);
644}
645
646void EffectScienFilter::OnSliderDBMIN(wxCommandEvent & WXUNUSED(evt))
647{
649}
650
651void EffectScienFilter::OnSliderDBMAX(wxCommandEvent & WXUNUSED(evt))
652{
654}
655
656void EffectScienFilter::OnSize(wxSizeEvent & evt)
657{
658 // On Windows the Passband and Stopband boxes do not refresh properly
659 // on a resize...no idea why.
660 mUIParent->Refresh();
661 evt.Skip();
662}
663
665{
666 bool ripple;
667 bool stop;
668
669 if (FilterType == kButterworth) // Butterworth
670 {
671 ripple = false;
672 stop = false;
673 }
674 else if (FilterType == kChebyshevTypeI) // Chebyshev Type1
675 {
676 ripple = true;
677 stop = false;
678 }
679 else // Chebyshev Type2
680 {
681 ripple = false;
682 stop = true;
683 }
684
685 mRippleCtlP->Enable(ripple);
686 mRippleCtl->Enable(ripple);
687 mRippleCtlU->Enable(ripple);
688 mStopbandRippleCtlP->Enable(stop);
689 mStopbandRippleCtl->Enable(stop);
690 mStopbandRippleCtlU->Enable(stop);
691}
692
693//----------------------------------------------------------------------------
694// EffectScienFilterPanel
695//----------------------------------------------------------------------------
696
697BEGIN_EVENT_TABLE(EffectScienFilterPanel, wxPanelWrapper)
701
703 wxWindow *parent, wxWindowID winid,
704 EffectScienFilter *effect, double lo, double hi)
705: wxPanelWrapper(parent, winid, wxDefaultPosition, wxSize(400, 200))
706{
707 mEffect = effect;
708 mParent = parent;
709
710 mBitmap = NULL;
711 mWidth = 0;
712 mHeight = 0;
713 mLoFreq = 0.0;
714 mHiFreq = 0.0;
715 mDbMin = 0.0;
716 mDbMax = 0.0;
717
718 SetFreqRange(lo, hi);
719}
720
722{
723}
724
725void EffectScienFilterPanel::SetFreqRange(double lo, double hi)
726{
727 mLoFreq = lo;
728 mHiFreq = hi;
729 Refresh(false);
730}
731
733{
734 mDbMin = min;
735 mDbMax = max;
736 Refresh(false);
737}
738
740{
741 return false;
742}
743
745{
746 return false;
747}
748
749void EffectScienFilterPanel::OnSize(wxSizeEvent & WXUNUSED(evt))
750{
751 Refresh(false);
752}
753
754void EffectScienFilterPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
755{
756 wxPaintDC dc(this);
757 int width, height;
758 GetSize(&width, &height);
759
760 if (!mBitmap || mWidth != width || mHeight != height)
761 {
762 mWidth = width;
763 mHeight = height;
764 mBitmap = std::make_unique<wxBitmap>(mWidth, mHeight,24);
765 }
766
767 wxBrush bkgndBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
768
769 wxMemoryDC memDC;
770 memDC.SelectObject(*mBitmap);
771
772 wxRect bkgndRect;
773 bkgndRect.x = 0;
774 bkgndRect.y = 0;
775 bkgndRect.width = mWidth;
776 bkgndRect.height = mHeight;
777 memDC.SetBrush(bkgndBrush);
778 memDC.SetPen(*wxTRANSPARENT_PEN);
779 memDC.DrawRectangle(bkgndRect);
780
781 bkgndRect.y = mHeight;
782 memDC.DrawRectangle(bkgndRect);
783
784 wxRect border;
785 border.x = 0;
786 border.y = 0;
787 border.width = mWidth;
788 border.height = mHeight;
789
790 memDC.SetBrush(*wxWHITE_BRUSH);
791 memDC.SetPen(*wxBLACK_PEN);
792 memDC.DrawRectangle(border);
793
794 mEnvRect = border;
795 mEnvRect.Deflate(2, 2);
796
797 // Pure blue x-axis line
798 memDC.SetPen(wxPen(theTheme.Colour(clrGraphLines), 1, wxPENSTYLE_SOLID));
799 int center = (int) (mEnvRect.height * mDbMax / (mDbMax - mDbMin) + 0.5);
800 AColor::Line(memDC,
801 mEnvRect.GetLeft(), mEnvRect.y + center,
802 mEnvRect.GetRight(), mEnvRect.y + center);
803
804 //Now draw the actual response that you will get.
805 //mFilterFunc has a linear scale, window has a log one so we have to fiddle about
806 memDC.SetPen(wxPen(theTheme.Colour(clrResponseLines), 3, wxPENSTYLE_SOLID));
807 double scale = (double) mEnvRect.height / (mDbMax - mDbMin); // pixels per dB
808 double yF; // gain at this freq
809
810 double loLog = log10(mLoFreq);
811 double step = log10(mHiFreq) - loLog;
812 step /= ((double) mEnvRect.width - 1.0);
813 double freq; // actual freq corresponding to x position
814 int x, y, xlast = 0, ylast = 0;
815 for (int i = 0; i < mEnvRect.width; i++)
816 {
817 x = mEnvRect.x + i;
818 freq = pow(10.0, loLog + i * step); //Hz
819 yF = mEffect->FilterMagnAtFreq (freq);
820 yF = LINEAR_TO_DB(yF);
821
822 if (yF < mDbMin)
823 {
824 yF = mDbMin;
825 }
826
827 yF = center-scale * yF;
828 if (yF > mEnvRect.height)
829 {
830 yF = (double) mEnvRect.height - 1.0;
831 }
832 if (yF < 0.0)
833 {
834 yF = 0.0;
835 }
836 y = (int) (yF + 0.5);
837
838 if (i != 0 && (y < mEnvRect.height - 1 || ylast < mEnvRect.y + mEnvRect.height - 1))
839 {
840 AColor::Line(memDC, xlast, ylast, x, mEnvRect.y + y);
841 }
842 xlast = x;
843 ylast = mEnvRect.y + y;
844 }
845
846 memDC.SetPen(*wxBLACK_PEN);
847 mEffect->mfreqRuler->ruler.DrawGrid(memDC, mEnvRect.height + 2, true, true, 0, 1);
848 mEffect->mdBRuler->ruler.DrawGrid(memDC, mEnvRect.width + 2, true, true, 1, 2);
849
850 dc.Blit(0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE);
851
852 memDC.SelectObject(wxNullBitmap);
853}
END_EVENT_TABLE()
int min(int a, int b)
EffectType
@ EffectTypeProcess
enum ChannelName * ChannelNames
@ nTypes
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:536
#define square(a)
Definition: ScienFilter.cpp:72
#define PI
Definition: ScienFilter.cpp:68
@ ID_Cutoff
Definition: ScienFilter.cpp:83
@ ID_SubType
Definition: ScienFilter.cpp:80
@ ID_dBMax
Definition: ScienFilter.cpp:77
@ ID_Ripple
Definition: ScienFilter.cpp:82
@ ID_StopbandRipple
Definition: ScienFilter.cpp:84
@ ID_Order
Definition: ScienFilter.cpp:81
@ ID_FilterPanel
Definition: ScienFilter.cpp:76
@ ID_Type
Definition: ScienFilter.cpp:79
@ ID_dBMin
Definition: ScienFilter.cpp:78
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::vector< TranslatableString > TranslatableStrings
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
const TrackList * inputTracks() const
Definition: EffectBase.h:102
double mProjectRate
Definition: EffectBase.h:99
int MessageBox(const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={}) const
Definition: Effect.cpp:871
bool EnableApply(bool enable=true)
Definition: Effect.cpp:613
wxWindow * mUIParent
Definition: Effect.h:270
Performs effect computation.
Interface for manipulations of an Effect's settings.
An Effect that applies 'classical' IIR filters.
Definition: ScienFilter.h:36
void OnFilterSubtype(wxCommandEvent &evt)
EffectScienFilterPanel * mPanel
Definition: ScienFilter.h:109
TranslatableString GetDescription() const override
void OnSliderDBMAX(wxCommandEvent &evt)
static const EnumValueSymbol kSubTypeStrings[nSubTypes]
Definition: ScienFilter.h:141
wxStaticText * mRippleCtlU
Definition: ScienFilter.h:115
void OnStopbandRipple(wxCommandEvent &evt)
friend class EffectScienFilterPanel
Definition: ScienFilter.h:133
void OnCutoff(wxCommandEvent &evt)
static const EnumValueSymbol kTypeStrings[nTypes]
Definition: ScienFilter.h:150
ArrayOf< Biquad > mpBiquad
Definition: ScienFilter.h:100
wxTextCtrl * mRippleCtl
Definition: ScienFilter.h:114
void EnableDisableRippleCtl(int FilterType)
wxChoice * mFilterSubTypeCtl
Definition: ScienFilter.h:124
virtual ~EffectScienFilter()
bool ProcessInitialize(EffectSettings &settings, double sampleRate, sampleCount totalLen, ChannelNames chanMap) override
static constexpr EffectParameter Stopband
Definition: ScienFilter.h:164
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
static constexpr EffectParameter Cutoff
Definition: ScienFilter.h:160
size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen) override
Called for destructive effect computation.
static constexpr EnumParameter Subtype
Definition: ScienFilter.h:156
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
wxTextCtrl * mCutoffCtl
Definition: ScienFilter.h:117
wxSlider * mdBMaxSlider
Definition: ScienFilter.h:111
wxChoice * mFilterTypeCtl
Definition: ScienFilter.h:123
void OnFilterType(wxCommandEvent &evt)
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
wxChoice * mFilterOrderCtl
Definition: ScienFilter.h:125
wxStaticText * mStopbandRippleCtlP
Definition: ScienFilter.h:119
const EffectParameterMethods & Parameters() const override
static constexpr EnumParameter Type
Definition: ScienFilter.h:154
static constexpr EffectParameter Passband
Definition: ScienFilter.h:162
RulerPanel * mdBRuler
Definition: ScienFilter.h:127
EffectType GetType() const override
Type determines how it behaves.
static constexpr EffectParameter Order
Definition: ScienFilter.h:158
wxTextCtrl * mStopbandRippleCtl
Definition: ScienFilter.h:120
bool TransferGraphLimitsFromWindow()
static const ComponentInterfaceSymbol Symbol
Definition: ScienFilter.h:40
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
void OnSliderDBMIN(wxCommandEvent &evt)
bool Init() override
Call once to set up state for whole list of tracks to be processed.
void OnOrder(wxCommandEvent &evt)
void OnRipple(wxCommandEvent &evt)
RulerPanel * mfreqRuler
Definition: ScienFilter.h:128
wxStaticText * mRippleCtlP
Definition: ScienFilter.h:113
float FilterMagnAtFreq(float Freq)
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
ComponentInterfaceSymbol GetSymbol() const override
wxStaticText * mStopbandRippleCtlU
Definition: ScienFilter.h:121
void OnSize(wxSizeEvent &evt)
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Add controls to effect panel; always succeeds.
wxSlider * mdBMinSlider
Definition: ScienFilter.h:110
EffectScienFilterPanel is used with EffectScienFilter and controls a graph for EffectScienFilter.
Definition: ScienFilter.h:169
void OnPaint(wxPaintEvent &evt)
void OnSize(wxSizeEvent &evt)
virtual ~EffectScienFilterPanel()
void SetDbRange(double min, double max)
bool AcceptsFocus() const
bool AcceptsFocusFromKeyboard() const
EffectScienFilter * mEffect
Definition: ScienFilter.h:189
std::unique_ptr< wxBitmap > mBitmap
Definition: ScienFilter.h:198
void SetFreqRange(double lo, double hi)
void DrawGrid(wxDC &dc, int length, bool minor=true, bool major=true, int xOffset=0, int yOffset=0) const
Definition: Ruler.cpp:1521
void GetMaxSize(wxCoord *width, wxCoord *height)
Definition: Ruler.cpp:1603
void SetRange(double min, double max)
Definition: Ruler.cpp:188
@ LinearDBFormat
Definition: Ruler.h:34
@ IntFormat
Definition: Ruler.h:30
RulerPanel class allows you to work with a Ruler like any other wxWindow.
Definition: Ruler.h:228
Ruler ruler
Definition: Ruler.h:288
std::pair< double, double > Range
Definition: Ruler.h:232
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
wxColour & Colour(int iIndex)
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1452
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
A Validator is an object which checks whether a wxVariant satisfies a certain criterion....
Definition: Validators.h:53
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
BuiltinCommandsModule::Registration< CompareAudioCommand > reg
static ArrayOf< Biquad > CalcButterworthFilter(int order, double fn, double fc, int type)
Definition: Biquad.cpp:64
static ArrayOf< Biquad > CalcChebyshevType2Filter(int order, double fn, double fc, double ripple, int type)
Definition: Biquad.cpp:228
static double ChebyPoly(int Order, double NormFreq)
Definition: Biquad.cpp:329
static ArrayOf< Biquad > CalcChebyshevType1Filter(int order, double fn, double fc, double ripple, int type)
Definition: Biquad.cpp:146
const Type min
Minimum value.
Definition: Shuttle.h:30
const Type max
Maximum value.
Definition: Shuttle.h:31
Externalized state of a plug-in.
Options & LabelEdges(bool l)
Definition: Ruler.h:250
Options & Flip(bool f)
Definition: Ruler.h:247
Options & Log(bool l)
Definition: Ruler.h:244