Audacity  2.2.2
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  // TODO: Add a graph display of the waveshaper equation.
10  // TODO: Allow the user to draw the graph.
11 
12 ******************************************************************//*******************************************************************/
18 
19 #include "../Audacity.h"
20 #include "Distortion.h"
21 
22 #include <cmath>
23 #include <algorithm>
24 #define _USE_MATH_DEFINES
25 
26 // Belt and braces
27 #ifndef M_PI
28 #define M_PI 3.1415926535897932384626433832795
29 #endif
30 #ifndef M_PI_2
31 #define M_PI_2 1.57079632679489661923132169163975
32 #endif
33 
34 #include <wx/choice.h>
35 #include <wx/intl.h>
36 #include <wx/valgen.h>
37 #include <wx/log.h>
38 
39 #include "../Prefs.h"
40 #include "../ShuttleGui.h"
41 #include "../widgets/valnum.h"
42 #include "../TranslatableStringArray.h"
43 
45 {
58 };
59 
61 {
62  { XO("Hard Clipping") },
63  { XO("Soft Clipping") },
64  { XO("Soft Overdrive") },
65  { XO("Medium Overdrive") },
66  { XO("Hard Overdrive") },
67  { XO("Cubic Curve (odd harmonics)") },
68  { XO("Even Harmonics") },
69  { XO("Expand and Compress") },
70  { XO("Leveller") },
71  { XO("Rectifier Distortion") },
72  { XO("Hard Limiter 1413") }
73 };
74 
75 // Define keys, defaults, minimums, and maximums for the effect parameters
76 // (Note: 'Repeats' is the total number of times the effect is applied.)
77 //
78 // Name Type Key Def Min Max Scale
79 Param( TableTypeIndx, int, wxT("Type"), 0, 0, nTableTypes-1, 1 );
80 Param( DCBlock, bool, wxT("DC Block"), false, false, true, 1 );
81 Param( Threshold_dB, double, wxT("Threshold dB"), -6.0, -100.0, 0.0, 1000.0f );
82 Param( NoiseFloor, double, wxT("Noise Floor"), -70.0, -80.0, -20.0, 1 );
83 Param( Param1, double, wxT("Parameter 1"), 50.0, 0.0, 100.0, 1 );
84 Param( Param2, double, wxT("Parameter 2"), 50.0, 0.0, 100.0, 1 );
85 Param( Repeats, int, wxT("Repeats"), 1, 0, 5, 1 );
86 
87 // How many samples are processed before recomputing the lookup table again
88 #define skipsamples 1000
89 
90 const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB);
91 
92 static const struct
93 {
94  const wxChar *name;
96 }
98 {
99  // Table DCBlock threshold floor Param1 Param2 Repeats
100  // Defaults: 0 false -6.0 -70.0(off) 50.0 50.0 1
101  //
102  // xgettext:no-c-format
103  { XO("Hard clip -12dB, 80% make-up gain"), { 0, 0, -12.0, -70.0, 0.0, 80.0, 0 } },
104  // xgettext:no-c-format
105  { XO("Soft clip -12dB, 80% make-up gain"), { 1, 0, -12.0, -70.0, 50.0, 80.0, 0 } },
106  { XO("Fuzz Box"), { 1, 0, -30.0, -70.0, 80.0, 80.0, 0 } },
107  { XO("Walkie-talkie"), { 1, 0, -50.0, -70.0, 60.0, 80.0, 0 } },
108  { XO("Blues drive sustain"), { 2, 0, -6.0, -70.0, 30.0, 80.0, 0 } },
109  { XO("Light Crunch Overdrive"), { 3, 0, -6.0, -70.0, 20.0, 80.0, 0 } },
110  { XO("Heavy Overdrive"), { 4, 0, -6.0, -70.0, 90.0, 80.0, 0 } },
111  { XO("3rd Harmonic (Perfect Fifth)"), { 5, 0, -6.0, -70.0, 100.0, 60.0, 0 } },
112  { XO("Valve Overdrive"), { 6, 1, -6.0, -70.0, 30.0, 40.0, 0 } },
113  { XO("2nd Harmonic (Octave)"), { 6, 1, -6.0, -70.0, 50.0, 0.0, 0 } },
114  { XO("Gated Expansion Distortion"), { 7, 0, -6.0, -70.0, 30.0, 80.0, 0 } },
115  { XO("Leveller, Light, -70dB noise floor"), { 8, 0, -6.0, -70.0, 0.0, 50.0, 1 } },
116  { XO("Leveller, Moderate, -70dB noise floor"), { 8, 0, -6.0, -70.0, 0.0, 50.0, 2 } },
117  { XO("Leveller, Heavy, -70dB noise floor"), { 8, 0, -6.0, -70.0, 0.0, 50.0, 3 } },
118  { XO("Leveller, Heavier, -70dB noise floor"), { 8, 0, -6.0, -70.0, 0.0, 50.0, 4 } },
119  { XO("Leveller, Heaviest, -70dB noise floor"), { 8, 0, -6.0, -70.0, 0.0, 50.0, 5 } },
120  { XO("Half-wave Rectifier"), { 9, 0, -6.0, -70.0, 50.0, 50.0, 0 } },
121  { XO("Full-wave Rectifier"), { 9, 0, -6.0, -70.0, 100.0, 50.0, 0 } },
122  { XO("Full-wave Rectifier (DC blocked)"), { 9, 1, -6.0, -70.0, 100.0, 50.0, 0 } },
123  { XO("Percussion Limiter"), {10, 0, -12.0, -70.0, 100.0, 30.0, 0 } },
124 };
125 
126 wxString defaultLabel(int index)
127 {
128  static const wxString names[] = {
129  XO("Upper Threshold"),
130  XO("Noise Floor"),
131  XO("Parameter 1"),
132  XO("Parameter 2"),
133  XO("Number of repeats"),
134  };
135 
136  class NamesArray final : public TranslatableStringArray
137  {
138  void Populate() override
139  {
140  for (auto &name : names)
141  mContents.push_back( wxGetTranslation( name ) );
142  }
143  };
144 
145  static NamesArray theArray;
146 
147  return theArray.Get()[ index ];
148 }
149 
150 //
151 // EffectDistortion
152 //
153 
154 BEGIN_EVENT_TABLE(EffectDistortion, wxEvtHandler)
155  EVT_CHOICE(ID_Type, EffectDistortion::OnTypeChoice)
156  EVT_CHECKBOX(ID_DCBlock, EffectDistortion::OnDCBlockCheckbox)
157  EVT_TEXT(ID_Threshold, EffectDistortion::OnThresholdText)
158  EVT_SLIDER(ID_Threshold, EffectDistortion::OnThresholdSlider)
159  EVT_TEXT(ID_NoiseFloor, EffectDistortion::OnNoiseFloorText)
160  EVT_SLIDER(ID_NoiseFloor, EffectDistortion::OnNoiseFloorSlider)
161  EVT_TEXT(ID_Param1, EffectDistortion::OnParam1Text)
162  EVT_SLIDER(ID_Param1, EffectDistortion::OnParam1Slider)
163  EVT_TEXT(ID_Param2, EffectDistortion::OnParam2Text)
164  EVT_SLIDER(ID_Param2, EffectDistortion::OnParam2Slider)
165  EVT_TEXT(ID_Repeats, EffectDistortion::OnRepeatsText)
166  EVT_SLIDER(ID_Repeats, EffectDistortion::OnRepeatsSlider)
168 
170 {
171  wxASSERT(nTableTypes == WXSIZEOF(kTableTypeStrings));
172 
173  mParams.mTableChoiceIndx = DEF_TableTypeIndx;
174  mParams.mDCBlock = DEF_DCBlock;
175  mParams.mThreshold_dB = DEF_Threshold_dB;
176  mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB);
177  mParams.mNoiseFloor = DEF_NoiseFloor;
178  mParams.mParam1 = DEF_Param1;
179  mParams.mParam2 = DEF_Param2;
180  mParams.mRepeats = DEF_Repeats;
181  mMakeupGain = 1.0;
182  mbSavedFilterState = DEF_DCBlock;
183 
184  SetLinearEffectFlag(false);
185 }
186 
188 {
189 }
190 
191 // IdentInterface implementation
192 
194 {
196 }
197 
199 {
200  return _("Waveshaping distortion effect");
201 }
202 
204 {
205  return wxT("Distortion");
206 }
207 
208 // EffectDefinitionInterface implementation
209 
211 {
212  return EffectTypeProcess;
213 }
214 
216 {
217 #if defined(EXPERIMENTAL_REALTIME_AUDACITY_EFFECTS)
218  return true;
219 #else
220  return false;
221 #endif
222 }
223 
224 // EffectClientInterface implementation
225 
227 {
228  return 1;
229 }
230 
232 {
233  return 1;
234 }
235 
236 bool EffectDistortion::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
237 {
239  return true;
240 }
241 
242 size_t EffectDistortion::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
243 {
244  return InstanceProcess(mMaster, inBlock, outBlock, blockLen);
245 }
246 
248 {
249  SetBlockSize(512);
250 
251  mSlaves.clear();
252 
253  return true;
254 }
255 
256 bool EffectDistortion::RealtimeAddProcessor(unsigned WXUNUSED(numChannels), float sampleRate)
257 {
258  EffectDistortionState slave;
259 
260  InstanceInit(slave, sampleRate);
261 
262  mSlaves.push_back(slave);
263 
264  return true;
265 }
266 
268 {
269  mSlaves.clear();
270 
271  return true;
272 }
273 
275  float **inbuf,
276  float **outbuf,
277  size_t numSamples)
278 {
279 
280  return InstanceProcess(mSlaves[group], inbuf, outbuf, numSamples);
281 }
283  S.SHUTTLE_ENUM_PARAM( mParams.mTableChoiceIndx, TableTypeIndx,
284  kTableTypeStrings, nTableTypes );
285  S.SHUTTLE_PARAM( mParams.mDCBlock, DCBlock );
286  S.SHUTTLE_PARAM( mParams.mThreshold_dB, Threshold_dB );
287  S.SHUTTLE_PARAM( mParams.mNoiseFloor, NoiseFloor );
288  S.SHUTTLE_PARAM( mParams.mParam1, Param1 );
289  S.SHUTTLE_PARAM( mParams.mParam2, Param2 );
290  S.SHUTTLE_PARAM( mParams.mRepeats, Repeats );
291  return true;
292 }
293 
295 {
296  parms.Write(KEY_TableTypeIndx,
297  kTableTypeStrings[mParams.mTableChoiceIndx].Internal());
298  parms.Write(KEY_DCBlock, mParams.mDCBlock);
299  parms.Write(KEY_Threshold_dB, mParams.mThreshold_dB);
300  parms.Write(KEY_NoiseFloor, mParams.mNoiseFloor);
301  parms.Write(KEY_Param1, mParams.mParam1);
302  parms.Write(KEY_Param2, mParams.mParam2);
303  parms.Write(KEY_Repeats, mParams.mRepeats);
304 
305  return true;
306 }
307 
309 {
310  ReadAndVerifyEnum(TableTypeIndx, kTableTypeStrings, nTableTypes);
311  ReadAndVerifyBool(DCBlock);
312  ReadAndVerifyDouble(Threshold_dB);
313  ReadAndVerifyDouble(NoiseFloor);
314  ReadAndVerifyDouble(Param1);
315  ReadAndVerifyDouble(Param2);
316  ReadAndVerifyInt(Repeats);
317 
318  mParams.mTableChoiceIndx = TableTypeIndx;
319  mParams.mDCBlock = DCBlock;
320  mParams.mThreshold_dB = Threshold_dB;
321  mParams.mNoiseFloor = NoiseFloor;
322  mParams.mParam1 = Param1;
323  mParams.mParam2 = Param2;
324  mParams.mRepeats = Repeats;
325 
326  return true;
327 }
328 
330 {
331  wxArrayString names;
332 
333  for (size_t i = 0; i < WXSIZEOF(FactoryPresets); i++)
334  {
335  names.Add(wxGetTranslation(FactoryPresets[i].name));
336  }
337 
338  return names;
339 }
340 
342 {
343  if (id < 0 || id >= (int) WXSIZEOF(FactoryPresets))
344  {
345  return false;
346  }
347 
348  mParams = FactoryPresets[id].params;
350 
351  if (mUIDialog)
352  {
354  }
355 
356  return true;
357 }
358 
359 
360 // Effect implementation
361 
363 {
364  S.AddSpace(0, 5);
365  S.StartVerticalLay();
366  {
367  S.StartMultiColumn(4, wxCENTER);
368  {
369  auto tableTypes = LocalizedStrings(kTableTypeStrings, nTableTypes);
370  mTypeChoiceCtrl = S.Id(ID_Type).AddChoice(_("Distortion type:"), wxT(""), &tableTypes);
371  mTypeChoiceCtrl->SetValidator(wxGenericValidator(&mParams.mTableChoiceIndx));
372  S.SetSizeHints(-1, -1);
373 
374  mDCBlockCheckBox = S.Id(ID_DCBlock).AddCheckBox(_("DC blocking filter"),
375  DEF_DCBlock ? wxT("true") : wxT("false"));
376  }
377  S.EndMultiColumn();
378  S.AddSpace(0, 10);
379 
380 
381  S.StartStatic(_("Threshold controls"));
382  {
383  S.StartMultiColumn(4, wxEXPAND);
384  S.SetStretchyCol(2);
385  {
386  // Allow space for first Column
387  S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0);
388 
389  // Upper threshold control
390  mThresholdTxt = S.AddVariableText(defaultLabel(0), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
391  FloatingPointValidator<double> vldThreshold(2, &mParams.mThreshold_dB);
392  vldThreshold.SetRange(MIN_Threshold_dB, MAX_Threshold_dB);
393  mThresholdT = S.Id(ID_Threshold).AddTextBox( {}, wxT(""), 10);
394  mThresholdT->SetName(defaultLabel(0));
395  mThresholdT->SetValidator(vldThreshold);
396 
397  S.SetStyle(wxSL_HORIZONTAL);
398  double maxLin = DB_TO_LINEAR(MAX_Threshold_dB) * SCL_Threshold_dB;
399  double minLin = DB_TO_LINEAR(MIN_Threshold_dB) * SCL_Threshold_dB;
400  mThresholdS = S.Id(ID_Threshold).AddSlider( {}, 0, maxLin, minLin);
401  mThresholdS->SetName(defaultLabel(0));
402  S.AddSpace(20, 0);
403 
404  // Noise floor control
405  mNoiseFloorTxt = S.AddVariableText(defaultLabel(1), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
406  FloatingPointValidator<double> vldfloor(2, &mParams.mNoiseFloor);
407  vldfloor.SetRange(MIN_NoiseFloor, MAX_NoiseFloor);
408  mNoiseFloorT = S.Id(ID_NoiseFloor).AddTextBox( {}, wxT(""), 10);
409  mNoiseFloorT->SetName(defaultLabel(1));
410  mNoiseFloorT->SetValidator(vldfloor);
411 
412  S.SetStyle(wxSL_HORIZONTAL);
413  mNoiseFloorS = S.Id(ID_NoiseFloor).AddSlider( {}, 0, MAX_NoiseFloor, MIN_NoiseFloor);
414  mNoiseFloorS->SetName(defaultLabel(1));
415  S.AddSpace(20, 0);
416  }
417  S.EndMultiColumn();
418  }
419  S.EndStatic();
420 
421  S.StartStatic(_("Parameter controls"));
422  {
423  S.StartMultiColumn(4, wxEXPAND);
424  S.SetStretchyCol(2);
425  {
426  // Allow space for first Column
427  S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0);
428 
429  // Parameter1 control
430  mParam1Txt = S.AddVariableText(defaultLabel(2), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
431  FloatingPointValidator<double> vldparam1(2, &mParams.mParam1);
432  vldparam1.SetRange(MIN_Param1, MAX_Param1);
433  mParam1T = S.Id(ID_Param1).AddTextBox( {}, wxT(""), 10);
434  mParam1T->SetName(defaultLabel(2));
435  mParam1T->SetValidator(vldparam1);
436 
437  S.SetStyle(wxSL_HORIZONTAL);
438  mParam1S = S.Id(ID_Param1).AddSlider( {}, 0, MAX_Param1, MIN_Param1);
439  mParam1S->SetName(defaultLabel(2));
440  S.AddSpace(20, 0);
441 
442  // Parameter2 control
443  mParam2Txt = S.AddVariableText(defaultLabel(3), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
444  FloatingPointValidator<double> vldParam2(2, &mParams.mParam2);
445  vldParam2.SetRange(MIN_Param2, MAX_Param2);
446  mParam2T = S.Id(ID_Param2).AddTextBox( {}, wxT(""), 10);
447  mParam2T->SetName(defaultLabel(3));
448  mParam2T->SetValidator(vldParam2);
449 
450  S.SetStyle(wxSL_HORIZONTAL);
451  mParam2S = S.Id(ID_Param2).AddSlider( {}, 0, MAX_Param2, MIN_Param2);
452  mParam2S->SetName(defaultLabel(3));
453  S.AddSpace(20, 0);
454 
455  // Repeats control
456  mRepeatsTxt = S.AddVariableText(defaultLabel(4), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
457  IntegerValidator<int>vldRepeats(&mParams.mRepeats);
458  vldRepeats.SetRange(MIN_Repeats, MAX_Repeats);
459  mRepeatsT = S.Id(ID_Repeats).AddTextBox( {}, wxT(""), 10);
460  mRepeatsT->SetName(defaultLabel(4));
461  mRepeatsT->SetValidator(vldRepeats);
462 
463  S.SetStyle(wxSL_HORIZONTAL);
464  mRepeatsS = S.Id(ID_Repeats).AddSlider( {}, DEF_Repeats, MAX_Repeats, MIN_Repeats);
465  mRepeatsS->SetName(defaultLabel(4));
466  S.AddSpace(20, 0);
467  }
468  S.EndMultiColumn();
469  }
470  S.EndStatic();
471  }
472  S.EndVerticalLay();
473 
474  return;
475 }
476 
478 {
479  if (!mUIParent->TransferDataToWindow())
480  {
481  return false;
482  }
483 
484  mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5));
485  mDCBlockCheckBox->SetValue(mParams.mDCBlock);
486  mNoiseFloorS->SetValue((int) mParams.mNoiseFloor + 0.5);
487  mParam1S->SetValue((int) mParams.mParam1 + 0.5);
488  mParam2S->SetValue((int) mParams.mParam2 + 0.5);
489  mRepeatsS->SetValue(mParams.mRepeats);
490 
492 
493  UpdateUI();
494 
495  return true;
496 }
497 
499 {
500  if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
501  {
502  return false;
503  }
504 
506 
507  return true;
508 }
509 
511 {
512  data.samplerate = sampleRate;
513  data.skipcount = 0;
515  data.dcblock = mParams.mDCBlock;
518  data.param1 = mParams.mParam1;
519  data.param2 = mParams.mParam2;
520  data.repeats = mParams.mRepeats;
521 
522  // DC block filter variables
523  data.queuetotal = 0.0;
524 
525  //std::queue<float>().swap(data.queuesamples);
526  while (!data.queuesamples.empty())
527  data.queuesamples.pop();
528 
529  MakeTable();
530 
531  return;
532 }
533 
534 size_t EffectDistortion::InstanceProcess(EffectDistortionState& data, float** inBlock, float** outBlock, size_t blockLen)
535 {
536  float *ibuf = inBlock[0];
537  float *obuf = outBlock[0];
538 
539  bool update = (mParams.mTableChoiceIndx == data.tablechoiceindx &&
540  mParams.mNoiseFloor == data.noisefloor &&
541  mParams.mThreshold_dB == data.threshold &&
542  mParams.mParam1 == data.param1 &&
543  mParams.mParam2 == data.param2 &&
544  mParams.mRepeats == data.repeats)? false : true;
545 
546  double p1 = mParams.mParam1 / 100.0;
547  double p2 = mParams.mParam2 / 100.0;
548 
552  data.param1 = mParams.mParam1;
553  data.repeats = mParams.mRepeats;
554 
555  for (decltype(blockLen) i = 0; i < blockLen; i++) {
556  if (update && ((data.skipcount++) % skipsamples == 0)) {
557  MakeTable();
558  }
559 
560  switch (mParams.mTableChoiceIndx)
561  {
562  case kHardClip:
563  // Param2 = make-up gain.
564  obuf[i] = WaveShaper(ibuf[i]) * ((1 - p2) + (mMakeupGain * p2));
565  break;
566  case kSoftClip:
567  // Param2 = make-up gain.
568  obuf[i] = WaveShaper(ibuf[i]) * ((1 - p2) + (mMakeupGain * p2));
569  break;
570  case kHalfSinCurve:
571  obuf[i] = WaveShaper(ibuf[i]) * p2;
572  break;
573  case kExpCurve:
574  obuf[i] = WaveShaper(ibuf[i]) * p2;
575  break;
576  case kLogCurve:
577  obuf[i] = WaveShaper(ibuf[i]) * p2;
578  break;
579  case kCubic:
580  obuf[i] = WaveShaper(ibuf[i]) * p2;
581  break;
582  case kEvenHarmonics:
583  obuf[i] = WaveShaper(ibuf[i]);
584  break;
585  case kSinCurve:
586  obuf[i] = WaveShaper(ibuf[i]) * p2;
587  break;
588  case kLeveller:
589  obuf[i] = WaveShaper(ibuf[i]);
590  break;
591  case kRectifier:
592  obuf[i] = WaveShaper(ibuf[i]);
593  break;
594  case kHardLimiter:
595  // Mix equivalent to LADSPA effect's "Wet / Residual" mix
596  obuf[i] = (WaveShaper(ibuf[i]) * (p1 - p2)) + (ibuf[i] * p2);
597  break;
598  default:
599  obuf[i] = WaveShaper(ibuf[i]);
600  }
601  if (mParams.mDCBlock) {
602  obuf[i] = DCFilter(data, obuf[i]);
603  }
604  }
605 
606  return blockLen;
607 }
608 
609 void EffectDistortion::OnTypeChoice(wxCommandEvent& /*evt*/)
610 {
611  mTypeChoiceCtrl->GetValidator()->TransferFromWindow();
612 
613  UpdateUI();
614 }
615 
616 void EffectDistortion::OnDCBlockCheckbox(wxCommandEvent& /*evt*/)
617 {
618  mParams.mDCBlock = mDCBlockCheckBox->GetValue();
620 }
621 
622 
623 void EffectDistortion::OnThresholdText(wxCommandEvent& /*evt*/)
624 {
625  mThresholdT->GetValidator()->TransferFromWindow();
627  mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5));
628 }
629 
630 void EffectDistortion::OnThresholdSlider(wxCommandEvent& evt)
631 {
632  mThreshold = (double) evt.GetInt() / SCL_Threshold_dB;
633  mParams.mThreshold_dB = wxMax(LINEAR_TO_DB(mThreshold), MIN_Threshold_dB);
634  mThreshold = std::max(MIN_Threshold_Linear, mThreshold);
635  mThresholdT->GetValidator()->TransferToWindow();
636 }
637 
638 void EffectDistortion::OnNoiseFloorText(wxCommandEvent& /*evt*/)
639 {
640  mNoiseFloorT->GetValidator()->TransferFromWindow();
641  mNoiseFloorS->SetValue((int) floor(mParams.mNoiseFloor + 0.5));
642 }
643 
644 void EffectDistortion::OnNoiseFloorSlider(wxCommandEvent& evt)
645 {
646  mParams.mNoiseFloor = (double) evt.GetInt();
647  mNoiseFloorT->GetValidator()->TransferToWindow();
648 }
649 
650 
651 void EffectDistortion::OnParam1Text(wxCommandEvent& /*evt*/)
652 {
653  mParam1T->GetValidator()->TransferFromWindow();
654  mParam1S->SetValue((int) floor(mParams.mParam1 + 0.5));
655 }
656 
657 void EffectDistortion::OnParam1Slider(wxCommandEvent& evt)
658 {
659  mParams.mParam1 = (double) evt.GetInt();
660  mParam1T->GetValidator()->TransferToWindow();
661 }
662 
663 void EffectDistortion::OnParam2Text(wxCommandEvent& /*evt*/)
664 {
665  mParam2T->GetValidator()->TransferFromWindow();
666  mParam2S->SetValue((int) floor(mParams.mParam2 + 0.5));
667 }
668 
669 void EffectDistortion::OnParam2Slider(wxCommandEvent& evt)
670 {
671  mParams.mParam2 = (double) evt.GetInt();
672  mParam2T->GetValidator()->TransferToWindow();
673 }
674 
675 void EffectDistortion::OnRepeatsText(wxCommandEvent& /*evt*/)
676 {
677  mRepeatsT->GetValidator()->TransferFromWindow();
678  mRepeatsS->SetValue(mParams.mRepeats);
679 }
680 
681 void EffectDistortion::OnRepeatsSlider(wxCommandEvent& evt)
682 {
683  mParams.mRepeats = evt.GetInt();
684  mRepeatsT->GetValidator()->TransferToWindow();
685 
686 }
687 
689 {
690  // set control text and names to match distortion type
691  switch (mParams.mTableChoiceIndx)
692  {
693  case kHardClip:
699 
700  UpdateControl(ID_Threshold, true, _("Clipping level"));
702  UpdateControl(ID_Param1, true, _("Drive"));
703  UpdateControl(ID_Param2, true, _("Make-up Gain"));
705  UpdateControl(ID_DCBlock, false, wxEmptyString);
706  break;
707  case kSoftClip:
713 
714  UpdateControl(ID_Threshold, true, _("Clipping threshold"));
716  UpdateControl(ID_Param1, true, _("Hardness"));
717  UpdateControl(ID_Param2, true, _("Make-up Gain"));
719  UpdateControl(ID_DCBlock, false, wxEmptyString);
720  break;
721  case kHalfSinCurve:
727 
730  UpdateControl(ID_Param1, true, _("Distortion amount"));
731  UpdateControl(ID_Param2, true, _("Output level"));
733  UpdateControl(ID_DCBlock, false, wxEmptyString);
734  break;
735  case kExpCurve:
741 
744  UpdateControl(ID_Param1, true, _("Distortion amount"));
745  UpdateControl(ID_Param2, true, _("Output level"));
747  UpdateControl(ID_DCBlock, false, wxEmptyString);
748  break;
749  case kLogCurve:
755 
758  UpdateControl(ID_Param1, true, _("Distortion amount"));
759  UpdateControl(ID_Param2, true, _("Output level"));
761  UpdateControl(ID_DCBlock, false, wxEmptyString);
762  break;
763  case kCubic:
769 
772  UpdateControl(ID_Param1, true, _("Distortion amount"));
773  UpdateControl(ID_Param2, true, _("Output level"));
774  UpdateControl(ID_Repeats, true, _("Repeat processing"));
775  UpdateControl(ID_DCBlock, false, wxEmptyString);
776  break;
777  case kEvenHarmonics:
783 
786  UpdateControl(ID_Param1, true, _("Distortion amount"));
787  UpdateControl(ID_Param2, true, _("Harmonic brightness"));
789  UpdateControl(ID_DCBlock, true, wxEmptyString);
790  break;
791  case kSinCurve:
797 
800  UpdateControl(ID_Param1, true, _("Distortion amount"));
801  UpdateControl(ID_Param2, true, _("Output level"));
803  UpdateControl(ID_DCBlock, false, wxEmptyString);
804  break;
805  case kLeveller:
811 
814  UpdateControl(ID_Param1, true, _("Levelling fine adjustment"));
816  UpdateControl(ID_Repeats, true, _("Degree of Levelling"));
817  UpdateControl(ID_DCBlock, false, wxEmptyString);
818  break;
819  case kRectifier:
825 
828  UpdateControl(ID_Param1, true, _("Distortion amount"));
831  UpdateControl(ID_DCBlock, true, wxEmptyString);
832  break;
833  case kHardLimiter:
839 
840  UpdateControl(ID_Threshold, true, _("dB Limit"));
842  UpdateControl(ID_Param1, true, _("Wet level"));
843  UpdateControl(ID_Param2, true, _("Residual level"));
845  UpdateControl(ID_DCBlock, false, wxEmptyString);
846  break;
847  default:
853  UpdateControl(ID_DCBlock, false, wxEmptyString);
854  }
855 }
856 
857 void EffectDistortion::UpdateControl(control id, bool enabled, wxString name)
858 {
859  wxString suffix = _(" (Not Used):");
860  switch (id)
861  {
862  case ID_Threshold:
863  /* i18n-hint: Control range. */
864  if (enabled) suffix = _(" (-100 to 0 dB):");
865  name += suffix;
866 
867  // Logarithmic slider is set indirectly
869  mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5));
870 
871  mThresholdTxt->SetLabel(name);
872  mThresholdS->SetName(name);
873  mThresholdT->SetName(name);
874  mThresholdS->Enable(enabled);
875  mThresholdT->Enable(enabled);
876  break;
877  case ID_NoiseFloor:
878  /* i18n-hint: Control range. */
879  if (enabled) suffix = _(" (-80 to -20 dB):");
880  name += suffix;
881 
882  mNoiseFloorTxt->SetLabel(name);
883  mNoiseFloorS->SetName(name);
884  mNoiseFloorT->SetName(name);
885  mNoiseFloorS->Enable(enabled);
886  mNoiseFloorT->Enable(enabled);
887  break;
888  case ID_Param1:
889  /* i18n-hint: Control range. */
890  if (enabled) suffix = _(" (0 to 100):");
891  name += suffix;
892 
893  mParam1Txt->SetLabel(name);
894  mParam1S->SetName(name);
895  mParam1T->SetName(name);
896  mParam1S->Enable(enabled);
897  mParam1T->Enable(enabled);
898  break;
899  case ID_Param2:
900  /* i18n-hint: Control range. */
901  if (enabled) suffix = _(" (0 to 100):");
902  name += suffix;
903 
904  mParam2Txt->SetLabel(name);
905  mParam2S->SetName(name);
906  mParam2T->SetName(name);
907  mParam2S->Enable(enabled);
908  mParam2T->Enable(enabled);
909  break;
910  case ID_Repeats:
911  /* i18n-hint: Control range. */
912  if (enabled) suffix = _(" (0 to 5):");
913  name += suffix;
914 
915  mRepeatsTxt->SetLabel(name);
916  mRepeatsS->SetName(name);
917  mRepeatsT->SetName(name);
918  mRepeatsS->Enable(enabled);
919  mRepeatsT->Enable(enabled);
920  break;
921  case ID_DCBlock:
922  if (enabled) {
925  }
926  else {
927  mDCBlockCheckBox->SetValue(false);
928  mParams.mDCBlock = false;
929  }
930 
931  mDCBlockCheckBox->Enable(enabled);
932  break;
933  default: break;
934  }
935 }
936 
937 void EffectDistortion::UpdateControlText(wxTextCtrl* textCtrl, wxString& string, bool enabled)
938 {
939  if (enabled) {
940  if (textCtrl->GetValue() == wxEmptyString)
941  textCtrl->SetValue(string);
942  else
943  string = textCtrl->GetValue();
944  }
945  else {
946  if (textCtrl->GetValue() != wxEmptyString)
947  string = textCtrl->GetValue();
948  textCtrl->SetValue(wxT(""));
949  }
950 }
951 
953 {
954  switch (mParams.mTableChoiceIndx)
955  {
956  case kHardClip:
957  HardClip();
958  break;
959  case kSoftClip:
960  SoftClip();
961  break;
962  case kHalfSinCurve:
963  HalfSinTable();
964  break;
965  case kExpCurve:
967  break;
968  case kLogCurve:
970  break;
971  case kCubic:
972  CubicTable();
973  break;
974  case kEvenHarmonics:
976  break;
977  case kSinCurve:
978  SineTable();
979  break;
980  case kLeveller:
981  Leveller();
982  break;
983  case kRectifier:
984  Rectifier();
985  break;
986  case kHardLimiter:
987  HardLimiter();
988  break;
989  }
990 }
991 
992 
993 //
994 // Preset tables for gain lookup
995 //
996 
998 {
999  double lowThresh = 1 - mThreshold;
1000  double highThresh = 1 + mThreshold;
1001 
1002  for (int n = 0; n < TABLESIZE; n++) {
1003  if (n < (STEPS * lowThresh))
1004  mTable[n] = - mThreshold;
1005  else if (n > (STEPS * highThresh))
1006  mTable[n] = mThreshold;
1007  else
1008  mTable[n] = n/(double)STEPS - 1;
1009 
1010  mMakeupGain = 1.0 / mThreshold;
1011  }
1012 }
1013 
1015 {
1016  double threshold = 1 + mThreshold;
1017  double amount = std::pow(2.0, 7.0 * mParams.mParam1 / 100.0); // range 1 to 128
1018  double peak = LogCurve(mThreshold, 1.0, amount);
1019  mMakeupGain = 1.0 / peak;
1020  mTable[STEPS] = 0.0; // origin
1021 
1022  // positive half of table
1023  for (int n = STEPS; n < TABLESIZE; n++) {
1024  if (n < (STEPS * threshold)) // origin to threshold
1025  mTable[n] = n/(float)STEPS - 1;
1026  else
1027  mTable[n] = LogCurve(mThreshold, n/(double)STEPS - 1, amount);
1028  }
1029  CopyHalfTable();
1030 }
1031 
1032 float EffectDistortion::LogCurve(double threshold, float value, double ratio)
1033 {
1034  return threshold + ((std::exp(ratio * (threshold - value)) - 1) / -ratio);
1035 }
1036 
1038 {
1039  double amount = std::min(0.999, DB_TO_LINEAR(-1 * mParams.mParam1)); // avoid divide by zero
1040 
1041  for (int n = STEPS; n < TABLESIZE; n++) {
1042  double linVal = n/(float)STEPS;
1043  double scale = -1.0 / (1.0 - amount); // unity gain at 0dB
1044  double curve = std::exp((linVal - 1) * std::log(amount));
1045  mTable[n] = scale * (curve -1);
1046  }
1047  CopyHalfTable();
1048 }
1049 
1051 {
1052  double amount = mParams.mParam1;
1053  double stepsize = 1.0 / STEPS;
1054  double linVal = 0;
1055 
1056  if (amount == 0){
1057  for (int n = STEPS; n < TABLESIZE; n++) {
1058  mTable[n] = linVal;
1059  linVal += stepsize;
1060  }
1061  }
1062  else {
1063  for (int n = STEPS; n < TABLESIZE; n++) {
1064  mTable[n] = std::log(1 + (amount * linVal)) / std::log(1 + amount);
1065  linVal += stepsize;
1066  }
1067  }
1068  CopyHalfTable();
1069 }
1070 
1072 {
1073  int iter = std::floor(mParams.mParam1 / 20.0);
1074  double fractionalpart = (mParams.mParam1 / 20.0) - iter;
1075  double stepsize = 1.0 / STEPS;
1076  double linVal = 0;
1077 
1078  for (int n = STEPS; n < TABLESIZE; n++) {
1079  mTable[n] = linVal;
1080  for (int i = 0; i < iter; i++) {
1081  mTable[n] = std::sin(mTable[n] * M_PI_2);
1082  }
1083  mTable[n] += ((std::sin(mTable[n] * M_PI_2) - mTable[n]) * fractionalpart);
1084  linVal += stepsize;
1085  }
1086  CopyHalfTable();
1087 }
1088 
1090 {
1091  double amount = mParams.mParam1 * std::sqrt(3.0) / 100.0;
1092  double gain = 1.0;
1093  if (amount != 0.0)
1094  gain = 1.0 / Cubic(std::min(amount, 1.0));
1095 
1096  double stepsize = amount / STEPS;
1097  double x = -amount;
1098 
1099  if (amount == 0) {
1100  for (int i = 0; i < TABLESIZE; i++) {
1101  mTable[i] = (i / (double)STEPS) - 1.0;
1102  }
1103  }
1104  else {
1105  for (int i = 0; i < TABLESIZE; i++) {
1106  mTable[i] = gain * Cubic(x);
1107  for (int j = 0; j < mParams.mRepeats; j++) {
1108  mTable[i] = gain * Cubic(mTable[i] * amount);
1109  }
1110  x += stepsize;
1111  }
1112  }
1113 }
1114 
1115 double EffectDistortion::Cubic(double x)
1116 {
1117  if (mParams.mParam1 == 0.0)
1118  return x;
1119 
1120  return x - (std::pow(x, 3.0) / 3.0);
1121 }
1122 
1123 
1125 {
1126  double amount = mParams.mParam1 / -100.0;
1127  // double C = std::sin(std::max(0.001, mParams.mParam2) / 100.0) * 10.0;
1128  double C = std::max(0.001, mParams.mParam2) / 10.0;
1129 
1130  double step = 1.0 / STEPS;
1131  double xval = -1.0;
1132 
1133  for (int i = 0; i < TABLESIZE; i++) {
1134  mTable[i] = ((1 + amount) * xval) -
1135  (xval * (amount / std::tanh(C)) * std::tanh(C * xval));
1136  xval += step;
1137  }
1138 }
1139 
1141 {
1142  int iter = std::floor(mParams.mParam1 / 20.0);
1143  double fractionalpart = (mParams.mParam1 / 20.0) - iter;
1144  double stepsize = 1.0 / STEPS;
1145  double linVal = 0.0;
1146 
1147  for (int n = STEPS; n < TABLESIZE; n++) {
1148  mTable[n] = linVal;
1149  for (int i = 0; i < iter; i++) {
1150  mTable[n] = (1.0 + std::sin((mTable[n] * M_PI) - M_PI_2)) / 2.0;
1151  }
1152  mTable[n] += (((1.0 + std::sin((mTable[n] * M_PI) - M_PI_2)) / 2.0) - mTable[n]) * fractionalpart;
1153  linVal += stepsize;
1154  }
1155  CopyHalfTable();
1156 }
1157 
1159 {
1160  double noiseFloor = DB_TO_LINEAR(mParams.mNoiseFloor);
1161  int numPasses = mParams.mRepeats;
1162  double fractionalPass = mParams.mParam1 / 100.0;
1163 
1164  const int numPoints = 6;
1165  const double gainFactors[numPoints] = { 0.80, 1.00, 1.20, 1.20, 1.00, 0.80 };
1166  double gainLimits[numPoints] = { 0.0001, 0.0, 0.1, 0.3, 0.5, 1.0 };
1167  double addOnValues[numPoints];
1168 
1169  gainLimits[1] = noiseFloor;
1170  /* In the original Leveller effect, behaviour was undefined for threshold > 20 dB.
1171  * If we want to support > 20 dB we need to scale the points to keep them non-decreasing.
1172  *
1173  * if (noiseFloor > gainLimits[2]) {
1174  * for (int i = 3; i < numPoints; i++) {
1175  * gainLimits[i] = noiseFloor + ((1 - noiseFloor)*((gainLimits[i] - 0.1) / 0.9));
1176  * }
1177  * gainLimits[2] = noiseFloor;
1178  * }
1179  */
1180 
1181  // Calculate add-on values
1182  addOnValues[0] = 0.0;
1183  for (int i = 0; i < numPoints-1; i++) {
1184  addOnValues[i+1] = addOnValues[i] + (gainLimits[i] * (gainFactors[i] - gainFactors[1 + i]));
1185  }
1186 
1187  // Positive half of table.
1188  // The original effect increased the 'strength' of the effect by
1189  // repeated passes over the audio data.
1190  // Here we model that more efficiently by repeated passes over a linear table.
1191  for (int n = STEPS; n < TABLESIZE; n++) {
1192  mTable[n] = ((double) (n - STEPS) / (double) STEPS);
1193  for (int j = 0; j < numPasses; j++) {
1194  // Find the highest index for gain adjustment
1195  int index = numPoints - 1;
1196  for (int i = index; i >= 0 && mTable[n] < gainLimits[i]; i--) {
1197  index = i;
1198  }
1199  // the whole number of 'repeats'
1200  mTable[n] = (mTable[n] * gainFactors[index]) + addOnValues[index];
1201  }
1202  // Extrapolate for fine adjustment.
1203  // tiny fractions are not worth the processing time
1204  if (fractionalPass > 0.001) {
1205  int index = numPoints - 1;
1206  for (int i = index; i >= 0 && mTable[n] < gainLimits[i]; i--) {
1207  index = i;
1208  }
1209  mTable[n] += fractionalPass * ((mTable[n] * (gainFactors[index] - 1)) + addOnValues[index]);
1210  }
1211  }
1212  CopyHalfTable();
1213 }
1214 
1216 {
1217  double amount = (mParams.mParam1 / 50.0) - 1;
1218  double stepsize = 1.0 / STEPS;
1219  int index = STEPS;
1220 
1221  // positive half of waveform is passed unaltered.
1222  for (int n = 0; n <= STEPS; n++) {
1223  mTable[index] = n * stepsize;
1224  index += 1;
1225  }
1226 
1227  // negative half of table
1228  index = STEPS - 1;
1229  for (int n = 1; n <= STEPS; n++) {
1230  mTable[index] = n * stepsize * amount;
1231  index--;
1232  }
1233 }
1234 
1236 {
1237  // The LADSPA "hardLimiter 1413" is basically hard clipping,
1238  // but with a 'kind of' wet/dry mix:
1239  // out = ((wet-residual)*clipped) + (residual*in)
1240  HardClip();
1241 }
1242 
1243 
1244 // Helper functions for lookup tables
1245 
1247 {
1248  // Copy negative half of table from positive half
1249  int count = TABLESIZE - 1;
1250  for (int n = 0; n < STEPS; n++) {
1251  mTable[n] = -mTable[count];
1252  count--;
1253  }
1254 }
1255 
1256 
1257 float EffectDistortion::WaveShaper(float sample)
1258 {
1259  float out;
1260  int index;
1261  double xOffset;
1262  double amount = 1;
1263 
1264  switch (mParams.mTableChoiceIndx)
1265  {
1266  // Do any pre-processing here
1267  case kHardClip:
1268  // Pre-gain
1269  amount = mParams.mParam1 / 100.0;
1270  sample *= 1+amount;
1271  break;
1272  default: break;
1273  }
1274 
1275  index = std::floor(sample * STEPS) + STEPS;
1276  index = wxMax<int>(wxMin<int>(index, 2 * STEPS - 1), 0);
1277  xOffset = ((1 + sample) * STEPS) - index;
1278  xOffset = wxMin<double>(wxMax<double>(xOffset, 0.0), 1.0); // Clip at 0dB
1279 
1280  // linear interpolation: y = y0 + (y1-y0)*(x-x0)
1281  out = mTable[index] + (mTable[index + 1] - mTable[index]) * xOffset;
1282 
1283  return out;
1284 }
1285 
1286 
1288 {
1289  // Rolling average gives less offset at the start than an IIR filter.
1290  const unsigned int queueLength = std::floor(data.samplerate / 20.0);
1291 
1292  data.queuetotal += sample;
1293  data.queuesamples.push(sample);
1294 
1295  if (data.queuesamples.size() > queueLength) {
1296  data.queuetotal -= data.queuesamples.front();
1297  data.queuesamples.pop();
1298  }
1299 
1300  return sample - (data.queuetotal / data.queuesamples.size());
1301 }
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
Definition: Distortion.cpp:236
kTableType
Definition: Distortion.cpp:44
static wxArrayString names()
Definition: Tags.cpp:703
wxStaticText * mParam1Txt
Definition: Distortion.h:202
void SetSizeHints(int minX, int minY)
Used to modify an already placed Window.
Definition: ShuttleGui.cpp:194
unsigned GetAudioOutCount() override
Definition: Distortion.cpp:231
wxStaticText * mNoiseFloorTxt
Definition: Distortion.h:201
#define skipsamples
Definition: Distortion.cpp:88
bool SupportsRealtime() override
Definition: Distortion.cpp:215
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override
Definition: Distortion.cpp:256
wxSlider * mParam1S
Definition: Distortion.h:194
void UpdateControl(control id, bool enable, wxString name)
Definition: Distortion.cpp:857
wxTextCtrl * mNoiseFloorT
Definition: Distortion.h:187
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
void OnThresholdSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:630
wxArrayString GetFactoryPresets() override
Definition: Distortion.cpp:329
bool GetAutomationParameters(CommandParameters &parms) override
Definition: Distortion.cpp:294
wxChoice * mTypeChoiceCtrl
Definition: Distortion.h:185
wxString mOldRepeatsTxt
Definition: Distortion.h:210
size_t InstanceProcess(EffectDistortionState &data, float **inBlock, float **outBlock, size_t blockLen)
Definition: Distortion.cpp:534
size_t SetBlockSize(size_t maxBlockSize) override
Definition: Effect.cpp:335
Param(TableTypeIndx, int, wxT("Type"), 0, 0, nTableTypes-1, 1)
wxArrayString LocalizedStrings(const IdentInterfaceSymbol strings[], size_t nStrings)
Definition: Internat.cpp:303
bool mbSavedFilterState
Definition: Distortion.h:177
double Cubic(double x)
void OnParam1Text(wxCommandEvent &evt)
Definition: Distortion.cpp:651
EffectType GetType() override
Definition: Distortion.cpp:210
bool RealtimeInitialize() override
Definition: Distortion.cpp:247
void EndMultiColumn()
IdentInterfaceSymbol GetSymbol() override
Definition: Distortion.cpp:193
#define XO(s)
Definition: Internat.h:33
wxString GetDescription() override
Definition: Distortion.cpp:198
Shuttle that deals with parameters. This is a base class with lots of virtual functions that do nothi...
Definition: Shuttle.h:60
void OnRepeatsSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:681
static const IdentInterfaceSymbol kTableTypeStrings[nTableTypes]
Definition: Distortion.cpp:60
double mSampleRate
Definition: Effect.h:459
void OnTypeChoice(wxCommandEvent &evt)
Definition: Distortion.cpp:609
#define TABLESIZE
Definition: Distortion.h:28
wxTextCtrl * mParam1T
Definition: Distortion.h:188
static const struct @22 FactoryPresets[]
wxSlider * mRepeatsS
Definition: Distortion.h:196
#define DISTORTION_PLUGIN_SYMBOL
Definition: Distortion.h:26
sampleCount skipcount
Definition: Distortion.h:34
void OnParam2Slider(wxCommandEvent &evt)
Definition: Distortion.cpp:669
float LogCurve(double threshold, float value, double ratio)
void EndVerticalLay()
wxTextCtrl * mThresholdT
Definition: Distortion.h:186
void OnDCBlockCheckbox(wxCommandEvent &evt)
Definition: Distortion.cpp:616
wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:540
A WaveShaper distortion effect.
Definition: Distortion.h:48
#define ReadAndVerifyEnum(name, list, listSize)
Definition: Effect.h:790
wxCheckBox * AddCheckBox(const wxString &Prompt, const wxString &Selected)
Definition: ShuttleGui.cpp:298
#define ReadAndVerifyInt(name)
Definition: Effect.h:801
wxString defaultLabel(int index)
Definition: Distortion.cpp:126
void EvenHarmonicTable()
wxStaticText * mParam2Txt
Definition: Distortion.h:203
bool RealtimeFinalize() override
Definition: Distortion.cpp:267
virtual ~EffectDistortion()
Definition: Distortion.cpp:187
wxString ManualPage() override
Definition: Distortion.cpp:203
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:371
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
wxSlider * mThresholdS
Definition: Distortion.h:192
ShuttleGui & Id(int id)
double mTable[TABLESIZE]
Definition: Distortion.h:175
#define STEPS
Definition: Distortion.h:27
void SetStyle(int Style)
Definition: ShuttleGui.h:287
unsigned GetAudioInCount() override
Definition: Distortion.cpp:226
#define ReadAndVerifyDouble(name)
Definition: Effect.h:802
wxTextCtrl * mParam2T
Definition: Distortion.h:189
wxSlider * mParam2S
Definition: Distortion.h:195
int min(int a, int b)
void InstanceInit(EffectDistortionState &data, float sampleRate)
Definition: Distortion.cpp:510
float DCFilter(EffectDistortionState &data, float sample)
IdentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
std::vector< EffectDistortionState > mSlaves
Definition: Distortion.h:173
wxString mOldParam2Txt
Definition: Distortion.h:209
enum ChannelName * ChannelNames
bool LoadFactoryPreset(int id) override
Definition: Distortion.cpp:341
float WaveShaper(float sample)
wxWindow * mUIParent
Definition: Effect.h:476
EffectDistortionState mMaster
Definition: Distortion.h:172
bool DefineParams(ShuttleParams &S) override
Definition: Distortion.cpp:282
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxStaticText * mRepeatsTxt
Definition: Distortion.h:204
double mMakeupGain
Definition: Distortion.h:181
#define LINEAR_TO_DB(x)
Definition: Audacity.h:217
void OnNoiseFloorText(wxCommandEvent &evt)
Definition: Distortion.cpp:638
void OnNoiseFloorSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:644
EffectType
wxStaticText * mThresholdTxt
Definition: Distortion.h:200
wxDialog * mUIDialog
Definition: Effect.h:475
void OnRepeatsText(wxCommandEvent &evt)
Definition: Distortion.cpp:675
const wxChar * name
Definition: Distortion.cpp:94
wxSlider * mNoiseFloorS
Definition: Distortion.h:193
void OnParam2Text(wxCommandEvent &evt)
Definition: Distortion.cpp:663
#define M_PI
Definition: Distortion.cpp:28
const wxString & Internal() const
bool SetAutomationParameters(CommandParameters &parms) override
Definition: Distortion.cpp:308
wxStaticText * AddVariableText(const wxString &Str, bool bCenter=false, int PositionFlags=0)
Definition: ShuttleGui.cpp:414
bool TransferDataToWindow() override
Definition: Distortion.cpp:477
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:763
#define ReadAndVerifyBool(name)
Definition: Effect.h:804
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override
Definition: Distortion.cpp:274
wxCheckBox * mDCBlockCheckBox
Definition: Distortion.h:198
std::queue< float > queuesamples
Definition: Distortion.h:44
size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override
Definition: Distortion.cpp:242
void PopulateOrExchange(ShuttleGui &S) override
Definition: Distortion.cpp:362
END_EVENT_TABLE()
wxSizerItem * AddSpace(int width, int height)
#define M_PI_2
Definition: Distortion.cpp:31
virtual void Populate()=0
wxString mOldmNoiseFloorTxt
Definition: Distortion.h:207
EffectDistortion::Params params
Definition: Distortion.cpp:95
wxTextCtrl * mRepeatsT
Definition: Distortion.h:190
const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB)
void UpdateControlText(wxTextCtrl *textCtrl, wxString &string, bool enabled)
Definition: Distortion.cpp:937
void OnThresholdText(wxCommandEvent &evt)
Definition: Distortion.cpp:623
bool TransferDataFromWindow() override
Definition: Distortion.cpp:498
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:203
wxString mOldThresholdTxt
Definition: Distortion.h:206
wxString mOldParam1Txt
Definition: Distortion.h:208
void OnParam1Slider(wxCommandEvent &evt)
Definition: Distortion.cpp:657
wxSlider * AddSlider(const wxString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:497
void StartVerticalLay(int iProp=1)