Audacity 3.2.0
Distortion.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Distortion.cpp
6
7 Steve Daulton
8
9*//*******************************************************************/
10
11
12#include "Distortion.h"
13#include "EffectEditor.h"
14#include "LoadEffects.h"
15
16#include <cmath>
17#include <algorithm>
18//#define _USE_MATH_DEFINES
19
20// Belt and braces
21#ifndef M_PI
22#define M_PI 3.1415926535897932384626433832795
23#endif
24#ifndef M_PI_2
25#define M_PI_2 1.57079632679489661923132169163975
26#endif
27
28#include <wx/checkbox.h>
29#include <wx/choice.h>
30#include <wx/valgen.h>
31#include <wx/log.h>
32#include <wx/slider.h>
33#include <wx/stattext.h>
34#include <wx/weakref.h>
35
36#include "Prefs.h"
37#include "ShuttleGui.h"
38#include "../widgets/valnum.h"
39
41{
42 static const TranslatableString names[] = {
43 XO("Upper Threshold"),
44 XO("Noise Floor"),
45 XO("Parameter 1"),
46 XO("Parameter 2"),
47 XO("Number of repeats"),
48 };
49
50 return names[ index ];
51}
52
53//
54// DistortionBase
55//
56
58
59
62{
63 Editor(const EffectUIServices& services,
66 ) : EffectEditor{ services, access }
67 , mInstance(instance)
69 {}
70 virtual ~Editor() = default;
71
72 bool ValidateUI() override;
73 bool UpdateUI() override;
74
76
77 // Control Handlers
78 void OnTypeChoice(wxCommandEvent& evt);
79 void OnDCBlockCheckbox(wxCommandEvent& evt);
80 void OnThresholdText(wxCommandEvent& evt);
81 void OnThresholdSlider(wxCommandEvent& evt);
82 void OnNoiseFloorText(wxCommandEvent& evt);
83 void OnNoiseFloorSlider(wxCommandEvent& evt);
84 void OnParam1Text(wxCommandEvent& evt);
85 void OnParam1Slider(wxCommandEvent& evt);
86 void OnParam2Text(wxCommandEvent& evt);
87 void OnParam2Slider(wxCommandEvent& evt);
88 void OnRepeatsText(wxCommandEvent& evt);
89 void OnRepeatsSlider(wxCommandEvent& evt);
90
91 wxChoice* mTypeChoiceCtrl;
92 wxTextCtrl* mThresholdT;
93 wxTextCtrl* mNoiseFloorT;
94 wxTextCtrl* mParam1T;
95 wxTextCtrl* mParam2T;
96 wxTextCtrl* mRepeatsT;
97
98 wxSlider* mThresholdS;
99 wxSlider* mNoiseFloorS;
100 wxSlider* mParam1S;
101 wxSlider* mParam2S;
102 wxSlider* mRepeatsS;
103
104 wxCheckBox* mDCBlockCheckBox;
105
106 wxStaticText* mThresholdTxt;
107 wxStaticText* mNoiseFloorTxt;
108 wxStaticText* mParam1Txt;
109 wxStaticText* mParam2Txt;
110 wxStaticText* mRepeatsTxt;
111
117
119
121
122 void UpdateControl(control id, bool enable, TranslatableString name);
123 void UpdateUIControls();
124 void UpdateControlText(wxTextCtrl* textCtrl, wxString& string, bool enabled);
125
126 wxWeakRef<wxWindow> mUIParent{};
128};
129
130
132{
133 {
134 // This section was copied from the original
135 // DistortionBase::TransferDataFromWindow
136 //
137 // However, the call to ->Validate would bring up an error dialog
138 // saying "Empty value"
139
140 if ( !mUIParent->TransferDataFromWindow())
141 {
142 return false;
143 }
144 }
145
146
148 (
149 [this](EffectSettings& settings)
150 {
151 // pass back the modified settings to the MessageBuffer
152
154
155 return nullptr;
156 }
157 );
158
159 return true;
160}
161
163{
164 return mInstance.mMaster;
165}
166
167// Effect implementation
168
169std::unique_ptr<EffectEditor>
171 EffectSettingsAccess& access, const EffectOutputs* pOutputs) const
172{
173 auto& settings = access.Get();
174 auto& myEffSettings = GetSettings(settings);
175
176 auto result = std::make_unique<Editor>(*this, dynamic_cast<DistortionBase::Instance&>(instance), access, myEffSettings);
177 result->PopulateOrExchange(S);
178 return result;
179}
180
181
183{
184 mUIParent = S.GetParent();
185 auto& ms = mSettings;
186
187 S.AddSpace(0, 5);
188 S.StartVerticalLay();
189 {
190 S.StartMultiColumn(4, wxCENTER);
191 {
192 mTypeChoiceCtrl = S
193 .MinSize( { -1, -1 } )
194 .Validator<wxGenericValidator>(&ms.mTableChoiceIndx)
195 .AddChoice(XXO("Distortion type:"),
197
198 BindTo(*mTypeChoiceCtrl, wxEVT_CHOICE, &Editor::OnTypeChoice);
199
200 mDCBlockCheckBox = S.AddCheckBox(XXO("DC blocking filter"),
201 DCBlock.def);
202
203 BindTo(*mDCBlockCheckBox, wxEVT_CHECKBOX, &Editor::OnDCBlockCheckbox);
204 }
205 S.EndMultiColumn();
206 S.AddSpace(0, 10);
207
208
209 S.StartStatic(XO("Threshold controls"));
210 {
211 S.StartMultiColumn(4, wxEXPAND);
212 S.SetStretchyCol(2);
213 {
214 // Allow space for first Column
215 S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0);
216
217 // Upper threshold control
218 mThresholdTxt = S.AddVariableText(defaultLabel(0),
219 false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
220 mThresholdT = S
221 .Name(defaultLabel(0))
222 .Validator<FloatingPointValidator<double>>(
223 2, &ms.mThreshold_dB, NumValidatorStyle::DEFAULT,
225 .AddTextBox( {}, wxT(""), 10);
226
227 BindTo(*mThresholdT, wxEVT_TEXT, &Editor::OnThresholdText);
228
229 mThresholdS = S
230 .Name(defaultLabel(0))
231 .Style(wxSL_HORIZONTAL)
232 .AddSlider( {}, 0,
235 S.AddSpace(20, 0);
236
237 BindTo(*mThresholdS, wxEVT_SLIDER, &Editor::OnThresholdSlider);
238
239 // Noise floor control
240 mNoiseFloorTxt = S.AddVariableText(defaultLabel(1),
241 false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
242 mNoiseFloorT = S
243 .Name(defaultLabel(1))
244 .Validator<FloatingPointValidator<double>>(
245 2, &ms.mNoiseFloor, NumValidatorStyle::DEFAULT,
247 )
248 .AddTextBox( {}, wxT(""), 10);
249
250 BindTo(*mNoiseFloorT, wxEVT_TEXT, &Editor::OnNoiseFloorText);
251
252 mNoiseFloorS = S
253 .Name(defaultLabel(1))
254 .Style(wxSL_HORIZONTAL)
255 .AddSlider( {}, 0, NoiseFloor.max, NoiseFloor.min);
256 S.AddSpace(20, 0);
257
258 BindTo(*mNoiseFloorS, wxEVT_SLIDER, &Editor::OnNoiseFloorSlider);
259 }
260 S.EndMultiColumn();
261 }
262 S.EndStatic();
263
264 S.StartStatic(XO("Parameter controls"));
265 {
266 S.StartMultiColumn(4, wxEXPAND);
267 S.SetStretchyCol(2);
268 {
269 // Allow space for first Column
270 S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0);
271
272 // Parameter1 control
273 mParam1Txt = S.AddVariableText(defaultLabel(2),
274 false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
275 mParam1T = S
276 .Name(defaultLabel(2))
277 .Validator<FloatingPointValidator<double>>(
278 2, &ms.mParam1, NumValidatorStyle::DEFAULT,
280 )
281 .AddTextBox( {}, wxT(""), 10);
282
283 BindTo(*mParam1T, wxEVT_TEXT, &Editor::OnParam1Text);
284
285 mParam1S = S
286 .Name(defaultLabel(2))
287 .Style(wxSL_HORIZONTAL)
288 .AddSlider( {}, 0, Param1.max, Param1.min);
289 S.AddSpace(20, 0);
290
291 BindTo(*mParam1S, wxEVT_SLIDER, &Editor::OnParam1Slider);
292
293 // Parameter2 control
294 mParam2Txt = S.AddVariableText(defaultLabel(3),
295 false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
296 mParam2T = S
297 .Name(defaultLabel(3))
298 .Validator<FloatingPointValidator<double>>(
299 2, &ms.mParam2, NumValidatorStyle::DEFAULT,
301 )
302 .AddTextBox( {}, wxT(""), 10);
303
304 BindTo(*mParam2T, wxEVT_TEXT, &Editor::OnParam2Text);
305
306 mParam2S = S
307 .Name(defaultLabel(3))
308 .Style(wxSL_HORIZONTAL)
309 .AddSlider( {}, 0, Param2.max, Param2.min);
310
311 BindTo(*mParam2S, wxEVT_SLIDER, &Editor::OnParam2Slider);
312
313 S.AddSpace(20, 0);
314
315 // Repeats control
316 mRepeatsTxt = S.AddVariableText(defaultLabel(4),
317 false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
318 mRepeatsT = S
319 .Name(defaultLabel(4))
320 .Validator<IntegerValidator<int>>(
321 &ms.mRepeats, NumValidatorStyle::DEFAULT,
323 )
324 .AddTextBox( {}, wxT(""), 10);
325
326 BindTo(*mRepeatsT, wxEVT_TEXT, &Editor::OnRepeatsText);
327
328 mRepeatsS = S
329 .Name(defaultLabel(4))
330 .Style(wxSL_HORIZONTAL)
331 .AddSlider( {}, Repeats.def, Repeats.max, Repeats.min);
332
333 BindTo(*mRepeatsS, wxEVT_SLIDER, &Editor::OnRepeatsSlider);
334
335 S.AddSpace(20, 0);
336 }
337 S.EndMultiColumn();
338 }
339 S.EndStatic();
340 }
341 S.EndVerticalLay();
342
343}
344
345
347{
348 const auto& ms = mSettings;
349
350 if (!mUIParent->TransferDataToWindow())
351 {
352 return false;
353 }
354
355 const double threshold = DB_TO_LINEAR(ms.mThreshold_dB);
356
357 mThresholdS-> SetValue((int) (threshold * Threshold_dB.scale + 0.5));
358 mDCBlockCheckBox->SetValue( ms.mDCBlock);
359 mNoiseFloorS-> SetValue((int)ms.mNoiseFloor + 0.5);
360 mParam1S-> SetValue((int)ms.mParam1 + 0.5);
361 mParam2S-> SetValue((int)ms.mParam2 + 0.5);
362 mRepeatsS-> SetValue( ms.mRepeats);
363
364 GetState().mbSavedFilterState = ms.mDCBlock;
365
366 UpdateUIControls();
367
368 return true;
369}
370
371void EffectDistortion::Editor::OnTypeChoice(wxCommandEvent& /*evt*/)
372{
373 mTypeChoiceCtrl->GetValidator()->TransferFromWindow();
374
375 UpdateUIControls();
376
377 ValidateUI();
378 Publish(EffectSettingChanged{});
379}
380
382{
383 auto& ms = mSettings;
384
385 ms.mDCBlock = mDCBlockCheckBox->GetValue();
386
387 GetState().mbSavedFilterState = ms.mDCBlock;
388
389 ValidateUI();
390 Publish(EffectSettingChanged{});
391}
392
393
394void EffectDistortion::Editor::OnThresholdText(wxCommandEvent& /*evt*/)
395{
396 const auto& ms = mSettings;
397
398 mThresholdT->GetValidator()->TransferFromWindow();
399 const double threshold = DB_TO_LINEAR(ms.mThreshold_dB);
400 mThresholdS->SetValue((int) (threshold * Threshold_dB.scale + 0.5));
401
402 ValidateUI();
403 Publish(EffectSettingChanged{});
404}
405
407{
408 auto& ms = mSettings;
409
410 static const double MIN_Threshold_Linear = DB_TO_LINEAR(Threshold_dB.min);
411
412 const double thresholdDB = (double)evt.GetInt() / Threshold_dB.scale;
413 ms.mThreshold_dB = wxMax(LINEAR_TO_DB(thresholdDB), Threshold_dB.min);
414
415 mThresholdT->GetValidator()->TransferToWindow();
416
417 ValidateUI();
418 Publish(EffectSettingChanged{});
419}
420
422{
423 const auto& ms = mSettings;
424
425 mNoiseFloorT->GetValidator()->TransferFromWindow();
426 mNoiseFloorS->SetValue((int) floor(ms.mNoiseFloor + 0.5));
427
428 ValidateUI();
429 Publish(EffectSettingChanged{});
430}
431
433{
434 auto& ms = mSettings;
435
436 ms.mNoiseFloor = (double) evt.GetInt();
437 mNoiseFloorT->GetValidator()->TransferToWindow();
438
439 ValidateUI();
440 Publish(EffectSettingChanged{});
441}
442
443
444void EffectDistortion::Editor::OnParam1Text(wxCommandEvent& /*evt*/)
445{
446 const auto& ms = mSettings;
447
448 mParam1T->GetValidator()->TransferFromWindow();
449 mParam1S->SetValue((int) floor(ms.mParam1 + 0.5));
450
451 ValidateUI();
452 Publish(EffectSettingChanged{});
453}
454
456{
457 auto& ms = mSettings;
458
459 ms.mParam1 = (double) evt.GetInt();
460 mParam1T->GetValidator()->TransferToWindow();
461
462 ValidateUI();
463 Publish(EffectSettingChanged{});
464}
465
466void EffectDistortion::Editor::OnParam2Text(wxCommandEvent& /*evt*/)
467{
468 const auto& ms = mSettings;
469
470 mParam2T->GetValidator()->TransferFromWindow();
471 mParam2S->SetValue((int) floor(ms.mParam2 + 0.5));
472
473 ValidateUI();
474 Publish(EffectSettingChanged{});
475}
476
478{
479 auto& ms = mSettings;
480
481 ms.mParam2 = (double) evt.GetInt();
482 mParam2T->GetValidator()->TransferToWindow();
483
484 ValidateUI();
485 Publish(EffectSettingChanged{});
486}
487
488void EffectDistortion::Editor::OnRepeatsText(wxCommandEvent& /*evt*/)
489{
490 const auto& ms = mSettings;
491
492 mRepeatsT->GetValidator()->TransferFromWindow();
493 mRepeatsS->SetValue(ms.mRepeats);
494
495 ValidateUI();
496 Publish(EffectSettingChanged{});
497}
498
500{
501 auto& ms = mSettings;
502
503 ms.mRepeats = evt.GetInt();
504 mRepeatsT->GetValidator()->TransferToWindow();
505
506 ValidateUI();
507 Publish(EffectSettingChanged{});
508}
509
511{
512 const auto& ms = mSettings;
513
514 // set control text and names to match distortion type
515 switch (ms.mTableChoiceIndx)
516 {
517 case kHardClip:
518 UpdateControlText(mThresholdT, mOldThresholdTxt, true);
519 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
520 UpdateControlText(mParam1T, mOldParam1Txt, true);
521 UpdateControlText(mParam2T, mOldParam2Txt, true);
522 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
523
524 UpdateControl(ID_Threshold, true, XO("Clipping level"));
525 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
526 UpdateControl(ID_Param1, true, XO("Drive"));
527 UpdateControl(ID_Param2, true, XO("Make-up Gain"));
528 UpdateControl(ID_Repeats, false, defaultLabel(4));
529 UpdateControl(ID_DCBlock, false, {});
530 break;
531 case kSoftClip:
532 UpdateControlText(mThresholdT, mOldThresholdTxt, true);
533 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
534 UpdateControlText(mParam1T, mOldParam1Txt, true);
535 UpdateControlText(mParam2T, mOldParam2Txt, true);
536 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
537
538 UpdateControl(ID_Threshold, true, XO("Clipping threshold"));
539 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
540 UpdateControl(ID_Param1, true, XO("Hardness"));
541 UpdateControl(ID_Param2, true, XO("Make-up Gain"));
542 UpdateControl(ID_Repeats, false, defaultLabel(4));
543 UpdateControl(ID_DCBlock, false, {});
544 break;
545 case kHalfSinCurve:
546 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
547 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
548 UpdateControlText(mParam1T, mOldParam1Txt, true);
549 UpdateControlText(mParam2T, mOldParam2Txt, true);
550 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
551
552 UpdateControl(ID_Threshold, false, defaultLabel(0));
553 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
554 UpdateControl(ID_Param1, true, XO("Distortion amount"));
555 UpdateControl(ID_Param2, true, XO("Output level"));
556 UpdateControl(ID_Repeats, false, defaultLabel(4));
557 UpdateControl(ID_DCBlock, false, {});
558 break;
559 case kExpCurve:
560 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
561 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
562 UpdateControlText(mParam1T, mOldParam1Txt, true);
563 UpdateControlText(mParam2T, mOldParam2Txt, true);
564 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
565
566 UpdateControl(ID_Threshold, false, defaultLabel(0));
567 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
568 UpdateControl(ID_Param1, true, XO("Distortion amount"));
569 UpdateControl(ID_Param2, true, XO("Output level"));
570 UpdateControl(ID_Repeats, false, defaultLabel(4));
571 UpdateControl(ID_DCBlock, false, {});
572 break;
573 case kLogCurve:
574 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
575 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
576 UpdateControlText(mParam1T, mOldParam1Txt, true);
577 UpdateControlText(mParam2T, mOldParam2Txt, true);
578 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
579
580 UpdateControl(ID_Threshold, false, defaultLabel(0));
581 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
582 UpdateControl(ID_Param1, true, XO("Distortion amount"));
583 UpdateControl(ID_Param2, true, XO("Output level"));
584 UpdateControl(ID_Repeats, false, defaultLabel(4));
585 UpdateControl(ID_DCBlock, false, {});
586 break;
587 case kCubic:
588 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
589 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
590 UpdateControlText(mParam1T, mOldParam1Txt, true);
591 UpdateControlText(mParam2T, mOldParam2Txt, true);
592 UpdateControlText(mRepeatsT, mOldRepeatsTxt, true);
593
594 UpdateControl(ID_Threshold, false, defaultLabel(0));
595 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
596 UpdateControl(ID_Param1, true, XO("Distortion amount"));
597 UpdateControl(ID_Param2, true, XO("Output level"));
598 UpdateControl(ID_Repeats, true, XO("Repeat processing"));
599 UpdateControl(ID_DCBlock, false, {});
600 break;
601 case kEvenHarmonics:
602 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
603 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
604 UpdateControlText(mParam1T, mOldParam1Txt, true);
605 UpdateControlText(mParam2T, mOldParam2Txt, true);
606 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
607
608 UpdateControl(ID_Threshold, false, defaultLabel(0));
609 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
610 UpdateControl(ID_Param1, true, XO("Distortion amount"));
611 UpdateControl(ID_Param2, true, XO("Harmonic brightness"));
612 UpdateControl(ID_Repeats, false, defaultLabel(4));
613 UpdateControl(ID_DCBlock, true, {});
614 break;
615 case kSinCurve:
616 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
617 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
618 UpdateControlText(mParam1T, mOldParam1Txt, true);
619 UpdateControlText(mParam2T, mOldParam2Txt, true);
620 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
621
622 UpdateControl(ID_Threshold, false, defaultLabel(0));
623 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
624 UpdateControl(ID_Param1, true, XO("Distortion amount"));
625 UpdateControl(ID_Param2, true, XO("Output level"));
626 UpdateControl(ID_Repeats, false, defaultLabel(4));
627 UpdateControl(ID_DCBlock, false, {});
628 break;
629 case kLeveller:
630 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
631 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, true);
632 UpdateControlText(mParam1T, mOldParam1Txt, true);
633 UpdateControlText(mParam2T, mOldParam2Txt, false);
634 UpdateControlText(mRepeatsT, mOldRepeatsTxt, true);
635
636 UpdateControl(ID_Threshold, false, defaultLabel(0));
637 UpdateControl(ID_NoiseFloor, true, defaultLabel(1));
638 UpdateControl(ID_Param1, true, XO("Levelling fine adjustment"));
639 UpdateControl(ID_Param2, false, defaultLabel(3));
640 UpdateControl(ID_Repeats, true, XO("Degree of Levelling"));
641 UpdateControl(ID_DCBlock, false, {});
642 break;
643 case kRectifier:
644 UpdateControlText(mThresholdT, mOldThresholdTxt, false);
645 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
646 UpdateControlText(mParam1T, mOldParam1Txt, true);
647 UpdateControlText(mParam2T, mOldParam2Txt, false);
648 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
649
650 UpdateControl(ID_Threshold, false, defaultLabel(0));
651 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
652 UpdateControl(ID_Param1, true, XO("Distortion amount"));
653 UpdateControl(ID_Param2, false, defaultLabel(3));
654 UpdateControl(ID_Repeats, false, defaultLabel(4));
655 UpdateControl(ID_DCBlock, true, {});
656 break;
657 case kHardLimiter:
658 UpdateControlText(mThresholdT, mOldThresholdTxt, true);
659 UpdateControlText(mNoiseFloorT, mOldmNoiseFloorTxt, false);
660 UpdateControlText(mParam1T, mOldParam1Txt, true);
661 UpdateControlText(mParam2T, mOldParam2Txt, true);
662 UpdateControlText(mRepeatsT, mOldRepeatsTxt, false);
663
664 UpdateControl(ID_Threshold, true, XO("dB Limit"));
665 UpdateControl(ID_NoiseFloor, false, defaultLabel(1));
666 UpdateControl(ID_Param1, true, XO("Wet level"));
667 UpdateControl(ID_Param2, true, XO("Residual level"));
668 UpdateControl(ID_Repeats, false, defaultLabel(4));
669 UpdateControl(ID_DCBlock, false, {});
670 break;
671 default:
672 UpdateControl(ID_Threshold, true, defaultLabel(0));
673 UpdateControl(ID_NoiseFloor, true, defaultLabel(1));
674 UpdateControl(ID_Param1, true, defaultLabel(2));
675 UpdateControl(ID_Param2, true, defaultLabel(3));
676 UpdateControl(ID_Repeats, true, defaultLabel(4));
677 UpdateControl(ID_DCBlock, false, {});
678 }
679}
680
681
683 control id, bool enabled, TranslatableString name)
684{
685 auto& ms = mSettings;
686
687 auto suffix = XO("(Not Used):");
688 switch (id)
689 {
690 case ID_Threshold: {
691 /* i18n-hint: Control range. */
692 if (enabled) suffix = XO("(-100 to 0 dB):");
693 name.Join( suffix, wxT(" ") );
694
695 // Logarithmic slider is set indirectly
696 const double threshold = DB_TO_LINEAR(ms.mThreshold_dB);
697 mThresholdS->SetValue((int) (threshold * Threshold_dB.scale + 0.5));
698
699 auto translated = name.Translation();
700 mThresholdTxt->SetLabel(translated);
701 mThresholdS->SetName(translated);
702 mThresholdT->SetName(translated);
703 mThresholdS->Enable(enabled);
704 mThresholdT->Enable(enabled);
705 break;
706 }
707 case ID_NoiseFloor: {
708 /* i18n-hint: Control range. */
709 if (enabled) suffix = XO("(-80 to -20 dB):");
710 name.Join( suffix, wxT(" ") );
711
712 auto translated = name.Translation();
713 mNoiseFloorTxt->SetLabel(translated);
714 mNoiseFloorS->SetName(translated);
715 mNoiseFloorT->SetName(translated);
716 mNoiseFloorS->Enable(enabled);
717 mNoiseFloorT->Enable(enabled);
718 break;
719 }
720 case ID_Param1: {
721 /* i18n-hint: Control range. */
722 if (enabled) suffix = XO("(0 to 100):");
723 name.Join( suffix, wxT(" ") );
724
725 auto translated = name.Translation();
726 mParam1Txt->SetLabel(translated);
727 mParam1S->SetName(translated);
728 mParam1T->SetName(translated);
729 mParam1S->Enable(enabled);
730 mParam1T->Enable(enabled);
731 break;
732 }
733 case ID_Param2: {
734 /* i18n-hint: Control range. */
735 if (enabled) suffix = XO("(0 to 100):");
736 name.Join( suffix, wxT(" ") );
737
738 auto translated = name.Translation();
739 mParam2Txt->SetLabel(translated);
740 mParam2S->SetName(translated);
741 mParam2T->SetName(translated);
742 mParam2S->Enable(enabled);
743 mParam2T->Enable(enabled);
744 break;
745 }
746 case ID_Repeats: {
747 /* i18n-hint: Control range. */
748 if (enabled) suffix = XO("(0 to 5):");
749 name.Join( suffix, wxT(" ") );
750
751 auto translated = name.Translation();
752 mRepeatsTxt->SetLabel(translated);
753 mRepeatsS->SetName(translated);
754 mRepeatsT->SetName(translated);
755 mRepeatsS->Enable(enabled);
756 mRepeatsT->Enable(enabled);
757 break;
758 }
759 case ID_DCBlock: {
760 if (enabled) {
761 mDCBlockCheckBox->SetValue(GetState().mbSavedFilterState);
762 ms.mDCBlock = GetState().mbSavedFilterState;
763 }
764 else {
765 mDCBlockCheckBox->SetValue(false);
766 ms.mDCBlock = false;
767 }
768
769 mDCBlockCheckBox->Enable(enabled);
770 break;
771 }
772 default:
773 break;
774 }
775}
776
777void EffectDistortion::Editor::UpdateControlText(wxTextCtrl* textCtrl, wxString& string, bool enabled)
778{
779 if (enabled) {
780 if (textCtrl->GetValue().empty())
781 textCtrl->SetValue(string);
782 else
783 string = textCtrl->GetValue();
784 }
785 else {
786 if (!textCtrl->GetValue().empty())
787 string = textCtrl->GetValue();
788 textCtrl->SetValue(wxT(""));
789 }
790}
wxT("CloseDown"))
TranslatableString defaultLabel(int index)
Definition: Distortion.cpp:40
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:339
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:338
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
wxString name
Definition: TagsEditor.cpp:166
static TranslatableStrings names
Definition: TagsEditor.cpp:153
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:51
bool ValidateUI(const EffectPlugin &context, EffectSettings &) const override
static constexpr EffectParameter DCBlock
static const EnumValueSymbol kTableTypeStrings[nTableTypes]
static constexpr EffectParameter NoiseFloor
static constexpr EffectParameter Threshold_dB
static constexpr EffectParameter Repeats
static constexpr EffectParameter Param1
static constexpr EffectParameter Param2
std::unique_ptr< EffectEditor > MakeEditor(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const override
Called only from PopulateUI, to add controls to effect panel.
Definition: Distortion.cpp:170
EffectSettingsAccess & mAccess
Definition: EffectEditor.h:92
Performs effect computation.
Hold values to send to effect output meters.
void ModifySettings(Function &&function)
Do a correct read-modify-write of settings.
virtual const EffectSettings & Get()=0
static EffectDistortionSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
Definition: Effect.h:166
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
Holds a msgid for the translation catalog; may also bind format arguments.
A Validator is an object which checks whether a wxVariant satisfies a certain criterion....
Definition: Validators.h:54
BuiltinEffectsModule::Registration< EffectDistortion > reg
Definition: Distortion.cpp:57
wxStaticText * mRepeatsTxt
Definition: Distortion.cpp:110
virtual ~Editor()=default
void OnParam2Text(wxCommandEvent &evt)
Definition: Distortion.cpp:466
bool ValidateUI() override
Get settings data from the panel; may make error dialogs and return false.
Definition: Distortion.cpp:131
DistortionBase::Instance & mInstance
Definition: Distortion.cpp:127
void UpdateControl(control id, bool enable, TranslatableString name)
Definition: Distortion.cpp:682
void OnRepeatsText(wxCommandEvent &evt)
Definition: Distortion.cpp:488
void OnRepeatsSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:499
void OnTypeChoice(wxCommandEvent &evt)
Definition: Distortion.cpp:371
wxStaticText * mThresholdTxt
Definition: Distortion.cpp:106
void OnDCBlockCheckbox(wxCommandEvent &evt)
Definition: Distortion.cpp:381
wxStaticText * mParam2Txt
Definition: Distortion.cpp:109
Editor(const EffectUIServices &services, DistortionBase::Instance &instance, EffectSettingsAccess &access, const EffectDistortionSettings &settings)
Definition: Distortion.cpp:63
EffectDistortionSettings mSettings
Definition: Distortion.cpp:118
bool UpdateUI() override
Update appearance of the panel for changes in settings.
Definition: Distortion.cpp:346
wxTextCtrl * mThresholdT
Definition: Distortion.cpp:92
void UpdateControlText(wxTextCtrl *textCtrl, wxString &string, bool enabled)
Definition: Distortion.cpp:777
wxCheckBox * mDCBlockCheckBox
Definition: Distortion.cpp:104
void OnNoiseFloorText(wxCommandEvent &evt)
Definition: Distortion.cpp:421
wxWeakRef< wxWindow > mUIParent
Definition: Distortion.cpp:126
void OnParam2Slider(wxCommandEvent &evt)
Definition: Distortion.cpp:477
void OnThresholdText(wxCommandEvent &evt)
Definition: Distortion.cpp:394
void OnParam1Slider(wxCommandEvent &evt)
Definition: Distortion.cpp:455
void OnParam1Text(wxCommandEvent &evt)
Definition: Distortion.cpp:444
wxStaticText * mParam1Txt
Definition: Distortion.cpp:108
void OnThresholdSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:406
void PopulateOrExchange(ShuttleGui &S)
Definition: Distortion.cpp:182
wxTextCtrl * mNoiseFloorT
Definition: Distortion.cpp:93
wxStaticText * mNoiseFloorTxt
Definition: Distortion.cpp:107
void OnNoiseFloorSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:432
EffectDistortionState & GetState()
Definition: Distortion.cpp:162
const Type scale
Scaling factor, for slider control.
const Type def
Default value.
const Type min
Minimum value.
const Type max
Maximum value.
Message sent by EffectEditor when a setting is changed by the user.
Definition: EffectEditor.h:26
Externalized state of a plug-in.