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 
60 static const wxString kTableTypeStrings[kNumTableTypes] =
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, kNumTableTypes-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 #include <wx/arrimpl.cpp>
151 WX_DEFINE_OBJARRAY(EffectDistortionStateArray);
152 
153 //
154 // EffectDistortion
155 //
156 
157 BEGIN_EVENT_TABLE(EffectDistortion, wxEvtHandler)
158  EVT_CHOICE(ID_Type, EffectDistortion::OnTypeChoice)
159  EVT_CHECKBOX(ID_DCBlock, EffectDistortion::OnDCBlockCheckbox)
160  EVT_TEXT(ID_Threshold, EffectDistortion::OnThresholdText)
161  EVT_SLIDER(ID_Threshold, EffectDistortion::OnThresholdSlider)
162  EVT_TEXT(ID_NoiseFloor, EffectDistortion::OnNoiseFloorText)
163  EVT_SLIDER(ID_NoiseFloor, EffectDistortion::OnNoiseFloorSlider)
164  EVT_TEXT(ID_Param1, EffectDistortion::OnParam1Text)
165  EVT_SLIDER(ID_Param1, EffectDistortion::OnParam1Slider)
166  EVT_TEXT(ID_Param2, EffectDistortion::OnParam2Text)
167  EVT_SLIDER(ID_Param2, EffectDistortion::OnParam2Slider)
168  EVT_TEXT(ID_Repeats, EffectDistortion::OnRepeatsText)
169  EVT_SLIDER(ID_Repeats, EffectDistortion::OnRepeatsSlider)
171 
173 {
174  wxASSERT(kNumTableTypes == WXSIZEOF(kTableTypeStrings));
175 
176  mParams.mTableChoiceIndx = DEF_TableTypeIndx;
177  mParams.mDCBlock = DEF_DCBlock;
178  mParams.mThreshold_dB = DEF_Threshold_dB;
179  mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB);
180  mParams.mNoiseFloor = DEF_NoiseFloor;
181  mParams.mParam1 = DEF_Param1;
182  mParams.mParam2 = DEF_Param2;
183  mParams.mRepeats = DEF_Repeats;
184  mMakeupGain = 1.0;
185  mbSavedFilterState = DEF_DCBlock;
186 
187  SetLinearEffectFlag(false);
188 }
189 
191 {
192 }
193 
194 // IdentInterface implementation
195 
197 {
199 }
200 
202 {
203  return _("Waveshaping distortion effect");
204 }
205 
207 {
208  return wxT("Distortion");
209 }
210 
211 // EffectIdentInterface implementation
212 
214 {
215  return EffectTypeProcess;
216 }
217 
219 {
220 #if defined(EXPERIMENTAL_REALTIME_AUDACITY_EFFECTS)
221  return true;
222 #else
223  return false;
224 #endif
225 }
226 
227 // EffectClientInterface implementation
228 
230 {
231  return 1;
232 }
233 
235 {
236  return 1;
237 }
238 
239 bool EffectDistortion::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
240 {
242  return true;
243 }
244 
245 size_t EffectDistortion::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
246 {
247  return InstanceProcess(mMaster, inBlock, outBlock, blockLen);
248 }
249 
251 {
252  SetBlockSize(512);
253 
254  mSlaves.Clear();
255 
256  return true;
257 }
258 
259 bool EffectDistortion::RealtimeAddProcessor(unsigned WXUNUSED(numChannels), float sampleRate)
260 {
261  EffectDistortionState slave;
262 
263  InstanceInit(slave, sampleRate);
264 
265  mSlaves.Add(slave);
266 
267  return true;
268 }
269 
271 {
272  mSlaves.Clear();
273 
274  return true;
275 }
276 
278  float **inbuf,
279  float **outbuf,
280  size_t numSamples)
281 {
282 
283  return InstanceProcess(mSlaves[group], inbuf, outbuf, numSamples);
284 }
285 
286 bool EffectDistortion::GetAutomationParameters(EffectAutomationParameters & parms)
287 {
288  parms.Write(KEY_TableTypeIndx, kTableTypeStrings[mParams.mTableChoiceIndx]);
289  parms.Write(KEY_DCBlock, mParams.mDCBlock);
290  parms.Write(KEY_Threshold_dB, mParams.mThreshold_dB);
291  parms.Write(KEY_NoiseFloor, mParams.mNoiseFloor);
292  parms.Write(KEY_Param1, mParams.mParam1);
293  parms.Write(KEY_Param2, mParams.mParam2);
294  parms.Write(KEY_Repeats, mParams.mRepeats);
295 
296  return true;
297 }
298 
299 bool EffectDistortion::SetAutomationParameters(EffectAutomationParameters & parms)
300 {
301  ReadAndVerifyEnum(TableTypeIndx, wxArrayString(kNumTableTypes, kTableTypeStrings));
302  ReadAndVerifyBool(DCBlock);
303  ReadAndVerifyDouble(Threshold_dB);
304  ReadAndVerifyDouble(NoiseFloor);
305  ReadAndVerifyDouble(Param1);
306  ReadAndVerifyDouble(Param2);
307  ReadAndVerifyInt(Repeats);
308 
309  mParams.mTableChoiceIndx = TableTypeIndx;
310  mParams.mDCBlock = DCBlock;
311  mParams.mThreshold_dB = Threshold_dB;
312  mParams.mNoiseFloor = NoiseFloor;
313  mParams.mParam1 = Param1;
314  mParams.mParam2 = Param2;
315  mParams.mRepeats = Repeats;
316 
317  return true;
318 }
319 
321 {
322  wxArrayString names;
323 
324  for (size_t i = 0; i < WXSIZEOF(FactoryPresets); i++)
325  {
326  names.Add(wxGetTranslation(FactoryPresets[i].name));
327  }
328 
329  return names;
330 }
331 
333 {
334  if (id < 0 || id >= (int) WXSIZEOF(FactoryPresets))
335  {
336  return false;
337  }
338 
339  mParams = FactoryPresets[id].params;
341 
342  if (mUIDialog)
343  {
345  }
346 
347  return true;
348 }
349 
350 
351 // Effect implementation
352 
354 {
355  for (int i = 0; i < kNumTableTypes; i++)
356  {
357  mTableTypes.Add(wxGetTranslation(kTableTypeStrings[i]));
358  }
359 
360  S.AddSpace(0, 5);
361  S.StartVerticalLay();
362  {
363  S.StartMultiColumn(4, wxCENTER);
364  {
365  mTypeChoiceCtrl = S.Id(ID_Type).AddChoice(_("Distortion type:"), wxT(""), &mTableTypes);
366  mTypeChoiceCtrl->SetValidator(wxGenericValidator(&mParams.mTableChoiceIndx));
367  S.SetSizeHints(-1, -1);
368 
369  mDCBlockCheckBox = S.Id(ID_DCBlock).AddCheckBox(_("DC blocking filter"),
370  DEF_DCBlock ? wxT("true") : wxT("false"));
371  }
372  S.EndMultiColumn();
373  S.AddSpace(0, 10);
374 
375 
376  S.StartStatic(_("Threshold controls"));
377  {
378  S.StartMultiColumn(4, wxEXPAND);
379  S.SetStretchyCol(2);
380  {
381  // Allow space for first Column
382  S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0);
383 
384  // Upper threshold control
385  mThresholdTxt = S.AddVariableText(defaultLabel(0), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
386  FloatingPointValidator<double> vldThreshold(2, &mParams.mThreshold_dB);
387  vldThreshold.SetRange(MIN_Threshold_dB, MAX_Threshold_dB);
388  mThresholdT = S.Id(ID_Threshold).AddTextBox( {}, wxT(""), 10);
389  mThresholdT->SetName(defaultLabel(0));
390  mThresholdT->SetValidator(vldThreshold);
391 
392  S.SetStyle(wxSL_HORIZONTAL);
393  double maxLin = DB_TO_LINEAR(MAX_Threshold_dB) * SCL_Threshold_dB;
394  double minLin = DB_TO_LINEAR(MIN_Threshold_dB) * SCL_Threshold_dB;
395  mThresholdS = S.Id(ID_Threshold).AddSlider( {}, 0, maxLin, minLin);
396  mThresholdS->SetName(defaultLabel(0));
397  S.AddSpace(20, 0);
398 
399  // Noise floor control
400  mNoiseFloorTxt = S.AddVariableText(defaultLabel(1), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
401  FloatingPointValidator<double> vldfloor(2, &mParams.mNoiseFloor);
402  vldfloor.SetRange(MIN_NoiseFloor, MAX_NoiseFloor);
403  mNoiseFloorT = S.Id(ID_NoiseFloor).AddTextBox( {}, wxT(""), 10);
404  mNoiseFloorT->SetName(defaultLabel(1));
405  mNoiseFloorT->SetValidator(vldfloor);
406 
407  S.SetStyle(wxSL_HORIZONTAL);
408  mNoiseFloorS = S.Id(ID_NoiseFloor).AddSlider( {}, 0, MAX_NoiseFloor, MIN_NoiseFloor);
409  mNoiseFloorS->SetName(defaultLabel(1));
410  S.AddSpace(20, 0);
411  }
412  S.EndMultiColumn();
413  }
414  S.EndStatic();
415 
416  S.StartStatic(_("Parameter controls"));
417  {
418  S.StartMultiColumn(4, wxEXPAND);
419  S.SetStretchyCol(2);
420  {
421  // Allow space for first Column
422  S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0);
423 
424  // Parameter1 control
425  mParam1Txt = S.AddVariableText(defaultLabel(2), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
426  FloatingPointValidator<double> vldparam1(2, &mParams.mParam1);
427  vldparam1.SetRange(MIN_Param1, MAX_Param1);
428  mParam1T = S.Id(ID_Param1).AddTextBox( {}, wxT(""), 10);
429  mParam1T->SetName(defaultLabel(2));
430  mParam1T->SetValidator(vldparam1);
431 
432  S.SetStyle(wxSL_HORIZONTAL);
433  mParam1S = S.Id(ID_Param1).AddSlider( {}, 0, MAX_Param1, MIN_Param1);
434  mParam1S->SetName(defaultLabel(2));
435  S.AddSpace(20, 0);
436 
437  // Parameter2 control
438  mParam2Txt = S.AddVariableText(defaultLabel(3), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
439  FloatingPointValidator<double> vldParam2(2, &mParams.mParam2);
440  vldParam2.SetRange(MIN_Param2, MAX_Param2);
441  mParam2T = S.Id(ID_Param2).AddTextBox( {}, wxT(""), 10);
442  mParam2T->SetName(defaultLabel(3));
443  mParam2T->SetValidator(vldParam2);
444 
445  S.SetStyle(wxSL_HORIZONTAL);
446  mParam2S = S.Id(ID_Param2).AddSlider( {}, 0, MAX_Param2, MIN_Param2);
447  mParam2S->SetName(defaultLabel(3));
448  S.AddSpace(20, 0);
449 
450  // Repeats control
451  mRepeatsTxt = S.AddVariableText(defaultLabel(4), false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
452  IntegerValidator<int>vldRepeats(&mParams.mRepeats);
453  vldRepeats.SetRange(MIN_Repeats, MAX_Repeats);
454  mRepeatsT = S.Id(ID_Repeats).AddTextBox( {}, wxT(""), 10);
455  mRepeatsT->SetName(defaultLabel(4));
456  mRepeatsT->SetValidator(vldRepeats);
457 
458  S.SetStyle(wxSL_HORIZONTAL);
459  mRepeatsS = S.Id(ID_Repeats).AddSlider( {}, DEF_Repeats, MAX_Repeats, MIN_Repeats);
460  mRepeatsS->SetName(defaultLabel(4));
461  S.AddSpace(20, 0);
462  }
463  S.EndMultiColumn();
464  }
465  S.EndStatic();
466  }
467  S.EndVerticalLay();
468 
469  return;
470 }
471 
473 {
474  if (!mUIParent->TransferDataToWindow())
475  {
476  return false;
477  }
478 
479  mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5));
480  mDCBlockCheckBox->SetValue(mParams.mDCBlock);
481  mNoiseFloorS->SetValue((int) mParams.mNoiseFloor + 0.5);
482  mParam1S->SetValue((int) mParams.mParam1 + 0.5);
483  mParam2S->SetValue((int) mParams.mParam2 + 0.5);
484  mRepeatsS->SetValue(mParams.mRepeats);
485 
487 
488  UpdateUI();
489 
490  return true;
491 }
492 
494 {
495  if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
496  {
497  return false;
498  }
499 
501 
502  return true;
503 }
504 
506 {
507  data.samplerate = sampleRate;
508  data.skipcount = 0;
510  data.dcblock = mParams.mDCBlock;
513  data.param1 = mParams.mParam1;
514  data.param2 = mParams.mParam2;
515  data.repeats = mParams.mRepeats;
516 
517  // DC block filter variables
518  data.queuetotal = 0.0;
519 
520  //std::queue<float>().swap(data.queuesamples);
521  while (!data.queuesamples.empty())
522  data.queuesamples.pop();
523 
524  MakeTable();
525 
526  return;
527 }
528 
529 size_t EffectDistortion::InstanceProcess(EffectDistortionState& data, float** inBlock, float** outBlock, size_t blockLen)
530 {
531  float *ibuf = inBlock[0];
532  float *obuf = outBlock[0];
533 
534  bool update = (mParams.mTableChoiceIndx == data.tablechoiceindx &&
535  mParams.mNoiseFloor == data.noisefloor &&
536  mParams.mThreshold_dB == data.threshold &&
537  mParams.mParam1 == data.param1 &&
538  mParams.mParam2 == data.param2 &&
539  mParams.mRepeats == data.repeats)? false : true;
540 
541  double p1 = mParams.mParam1 / 100.0;
542  double p2 = mParams.mParam2 / 100.0;
543 
547  data.param1 = mParams.mParam1;
548  data.repeats = mParams.mRepeats;
549 
550  for (decltype(blockLen) i = 0; i < blockLen; i++) {
551  if (update && ((data.skipcount++) % skipsamples == 0)) {
552  MakeTable();
553  }
554 
555  switch (mParams.mTableChoiceIndx)
556  {
557  case kHardClip:
558  // Param2 = make-up gain.
559  obuf[i] = WaveShaper(ibuf[i]) * ((1 - p2) + (mMakeupGain * p2));
560  break;
561  case kSoftClip:
562  // Param2 = make-up gain.
563  obuf[i] = WaveShaper(ibuf[i]) * ((1 - p2) + (mMakeupGain * p2));
564  break;
565  case kHalfSinCurve:
566  obuf[i] = WaveShaper(ibuf[i]) * p2;
567  break;
568  case kExpCurve:
569  obuf[i] = WaveShaper(ibuf[i]) * p2;
570  break;
571  case kLogCurve:
572  obuf[i] = WaveShaper(ibuf[i]) * p2;
573  break;
574  case kCubic:
575  obuf[i] = WaveShaper(ibuf[i]) * p2;
576  break;
577  case kEvenHarmonics:
578  obuf[i] = WaveShaper(ibuf[i]);
579  break;
580  case kSinCurve:
581  obuf[i] = WaveShaper(ibuf[i]) * p2;
582  break;
583  case kLeveller:
584  obuf[i] = WaveShaper(ibuf[i]);
585  break;
586  case kRectifier:
587  obuf[i] = WaveShaper(ibuf[i]);
588  break;
589  case kHardLimiter:
590  // Mix equivalent to LADSPA effect's "Wet / Residual" mix
591  obuf[i] = (WaveShaper(ibuf[i]) * (p1 - p2)) + (ibuf[i] * p2);
592  break;
593  default:
594  obuf[i] = WaveShaper(ibuf[i]);
595  }
596  if (mParams.mDCBlock) {
597  obuf[i] = DCFilter(data, obuf[i]);
598  }
599  }
600 
601  return blockLen;
602 }
603 
604 void EffectDistortion::OnTypeChoice(wxCommandEvent& /*evt*/)
605 {
606  mTypeChoiceCtrl->GetValidator()->TransferFromWindow();
607 
608  UpdateUI();
609 }
610 
611 void EffectDistortion::OnDCBlockCheckbox(wxCommandEvent& /*evt*/)
612 {
613  mParams.mDCBlock = mDCBlockCheckBox->GetValue();
615 }
616 
617 
618 void EffectDistortion::OnThresholdText(wxCommandEvent& /*evt*/)
619 {
620  mThresholdT->GetValidator()->TransferFromWindow();
622  mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5));
623 }
624 
625 void EffectDistortion::OnThresholdSlider(wxCommandEvent& evt)
626 {
627  mThreshold = (double) evt.GetInt() / SCL_Threshold_dB;
628  mParams.mThreshold_dB = wxMax(LINEAR_TO_DB(mThreshold), MIN_Threshold_dB);
629  mThreshold = std::max(MIN_Threshold_Linear, mThreshold);
630  mThresholdT->GetValidator()->TransferToWindow();
631 }
632 
633 void EffectDistortion::OnNoiseFloorText(wxCommandEvent& /*evt*/)
634 {
635  mNoiseFloorT->GetValidator()->TransferFromWindow();
636  mNoiseFloorS->SetValue((int) floor(mParams.mNoiseFloor + 0.5));
637 }
638 
639 void EffectDistortion::OnNoiseFloorSlider(wxCommandEvent& evt)
640 {
641  mParams.mNoiseFloor = (double) evt.GetInt();
642  mNoiseFloorT->GetValidator()->TransferToWindow();
643 }
644 
645 
646 void EffectDistortion::OnParam1Text(wxCommandEvent& /*evt*/)
647 {
648  mParam1T->GetValidator()->TransferFromWindow();
649  mParam1S->SetValue((int) floor(mParams.mParam1 + 0.5));
650 }
651 
652 void EffectDistortion::OnParam1Slider(wxCommandEvent& evt)
653 {
654  mParams.mParam1 = (double) evt.GetInt();
655  mParam1T->GetValidator()->TransferToWindow();
656 }
657 
658 void EffectDistortion::OnParam2Text(wxCommandEvent& /*evt*/)
659 {
660  mParam2T->GetValidator()->TransferFromWindow();
661  mParam2S->SetValue((int) floor(mParams.mParam2 + 0.5));
662 }
663 
664 void EffectDistortion::OnParam2Slider(wxCommandEvent& evt)
665 {
666  mParams.mParam2 = (double) evt.GetInt();
667  mParam2T->GetValidator()->TransferToWindow();
668 }
669 
670 void EffectDistortion::OnRepeatsText(wxCommandEvent& /*evt*/)
671 {
672  mRepeatsT->GetValidator()->TransferFromWindow();
673  mRepeatsS->SetValue(mParams.mRepeats);
674 }
675 
676 void EffectDistortion::OnRepeatsSlider(wxCommandEvent& evt)
677 {
678  mParams.mRepeats = evt.GetInt();
679  mRepeatsT->GetValidator()->TransferToWindow();
680 
681 }
682 
684 {
685  // set control text and names to match distortion type
686  switch (mParams.mTableChoiceIndx)
687  {
688  case kHardClip:
694 
695  UpdateControl(ID_Threshold, true, _("Clipping level"));
697  UpdateControl(ID_Param1, true, _("Drive"));
698  UpdateControl(ID_Param2, true, _("Make-up Gain"));
700  UpdateControl(ID_DCBlock, false, wxEmptyString);
701  break;
702  case kSoftClip:
708 
709  UpdateControl(ID_Threshold, true, _("Clipping threshold"));
711  UpdateControl(ID_Param1, true, _("Hardness"));
712  UpdateControl(ID_Param2, true, _("Make-up Gain"));
714  UpdateControl(ID_DCBlock, false, wxEmptyString);
715  break;
716  case kHalfSinCurve:
722 
725  UpdateControl(ID_Param1, true, _("Distortion amount"));
726  UpdateControl(ID_Param2, true, _("Output level"));
728  UpdateControl(ID_DCBlock, false, wxEmptyString);
729  break;
730  case kExpCurve:
736 
739  UpdateControl(ID_Param1, true, _("Distortion amount"));
740  UpdateControl(ID_Param2, true, _("Output level"));
742  UpdateControl(ID_DCBlock, false, wxEmptyString);
743  break;
744  case kLogCurve:
750 
753  UpdateControl(ID_Param1, true, _("Distortion amount"));
754  UpdateControl(ID_Param2, true, _("Output level"));
756  UpdateControl(ID_DCBlock, false, wxEmptyString);
757  break;
758  case kCubic:
764 
767  UpdateControl(ID_Param1, true, _("Distortion amount"));
768  UpdateControl(ID_Param2, true, _("Output level"));
769  UpdateControl(ID_Repeats, true, _("Repeat processing"));
770  UpdateControl(ID_DCBlock, false, wxEmptyString);
771  break;
772  case kEvenHarmonics:
778 
781  UpdateControl(ID_Param1, true, _("Distortion amount"));
782  UpdateControl(ID_Param2, true, _("Harmonic brightness"));
784  UpdateControl(ID_DCBlock, true, wxEmptyString);
785  break;
786  case kSinCurve:
792 
795  UpdateControl(ID_Param1, true, _("Distortion amount"));
796  UpdateControl(ID_Param2, true, _("Output level"));
798  UpdateControl(ID_DCBlock, false, wxEmptyString);
799  break;
800  case kLeveller:
806 
809  UpdateControl(ID_Param1, true, _("Levelling fine adjustment"));
811  UpdateControl(ID_Repeats, true, _("Degree of Levelling"));
812  UpdateControl(ID_DCBlock, false, wxEmptyString);
813  break;
814  case kRectifier:
820 
823  UpdateControl(ID_Param1, true, _("Distortion amount"));
826  UpdateControl(ID_DCBlock, true, wxEmptyString);
827  break;
828  case kHardLimiter:
834 
835  UpdateControl(ID_Threshold, true, _("dB Limit"));
837  UpdateControl(ID_Param1, true, _("Wet level"));
838  UpdateControl(ID_Param2, true, _("Residual level"));
840  UpdateControl(ID_DCBlock, false, wxEmptyString);
841  break;
842  default:
848  UpdateControl(ID_DCBlock, false, wxEmptyString);
849  }
850 }
851 
852 void EffectDistortion::UpdateControl(control id, bool enabled, wxString name)
853 {
854  wxString suffix = _(" (Not Used):");
855  switch (id)
856  {
857  case ID_Threshold:
858  /* i18n-hint: Control range. */
859  if (enabled) suffix = _(" (-100 to 0 dB):");
860  name += suffix;
861 
862  // Logarithmic slider is set indirectly
864  mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5));
865 
866  mThresholdTxt->SetLabel(name);
867  mThresholdS->SetName(name);
868  mThresholdT->SetName(name);
869  mThresholdS->Enable(enabled);
870  mThresholdT->Enable(enabled);
871  break;
872  case ID_NoiseFloor:
873  /* i18n-hint: Control range. */
874  if (enabled) suffix = _(" (-80 to -20 dB):");
875  name += suffix;
876 
877  mNoiseFloorTxt->SetLabel(name);
878  mNoiseFloorS->SetName(name);
879  mNoiseFloorT->SetName(name);
880  mNoiseFloorS->Enable(enabled);
881  mNoiseFloorT->Enable(enabled);
882  break;
883  case ID_Param1:
884  /* i18n-hint: Control range. */
885  if (enabled) suffix = _(" (0 to 100):");
886  name += suffix;
887 
888  mParam1Txt->SetLabel(name);
889  mParam1S->SetName(name);
890  mParam1T->SetName(name);
891  mParam1S->Enable(enabled);
892  mParam1T->Enable(enabled);
893  break;
894  case ID_Param2:
895  /* i18n-hint: Control range. */
896  if (enabled) suffix = _(" (0 to 100):");
897  name += suffix;
898 
899  mParam2Txt->SetLabel(name);
900  mParam2S->SetName(name);
901  mParam2T->SetName(name);
902  mParam2S->Enable(enabled);
903  mParam2T->Enable(enabled);
904  break;
905  case ID_Repeats:
906  /* i18n-hint: Control range. */
907  if (enabled) suffix = _(" (0 to 5):");
908  name += suffix;
909 
910  mRepeatsTxt->SetLabel(name);
911  mRepeatsS->SetName(name);
912  mRepeatsT->SetName(name);
913  mRepeatsS->Enable(enabled);
914  mRepeatsT->Enable(enabled);
915  break;
916  case ID_DCBlock:
917  if (enabled) {
920  }
921  else {
922  mDCBlockCheckBox->SetValue(false);
923  mParams.mDCBlock = false;
924  }
925 
926  mDCBlockCheckBox->Enable(enabled);
927  break;
928  default: break;
929  }
930 }
931 
932 void EffectDistortion::UpdateControlText(wxTextCtrl* textCtrl, wxString& string, bool enabled)
933 {
934  if (enabled) {
935  if (textCtrl->GetValue() == wxEmptyString)
936  textCtrl->SetValue(string);
937  else
938  string = textCtrl->GetValue();
939  }
940  else {
941  if (textCtrl->GetValue() != wxEmptyString)
942  string = textCtrl->GetValue();
943  textCtrl->SetValue(wxT(""));
944  }
945 }
946 
948 {
949  switch (mParams.mTableChoiceIndx)
950  {
951  case kHardClip:
952  HardClip();
953  break;
954  case kSoftClip:
955  SoftClip();
956  break;
957  case kHalfSinCurve:
958  HalfSinTable();
959  break;
960  case kExpCurve:
962  break;
963  case kLogCurve:
965  break;
966  case kCubic:
967  CubicTable();
968  break;
969  case kEvenHarmonics:
971  break;
972  case kSinCurve:
973  SineTable();
974  break;
975  case kLeveller:
976  Leveller();
977  break;
978  case kRectifier:
979  Rectifier();
980  break;
981  case kHardLimiter:
982  HardLimiter();
983  break;
984  }
985 }
986 
987 
988 //
989 // Preset tables for gain lookup
990 //
991 
993 {
994  double lowThresh = 1 - mThreshold;
995  double highThresh = 1 + mThreshold;
996 
997  for (int n = 0; n < TABLESIZE; n++) {
998  if (n < (STEPS * lowThresh))
999  mTable[n] = - mThreshold;
1000  else if (n > (STEPS * highThresh))
1001  mTable[n] = mThreshold;
1002  else
1003  mTable[n] = n/(double)STEPS - 1;
1004 
1005  mMakeupGain = 1.0 / mThreshold;
1006  }
1007 }
1008 
1010 {
1011  double threshold = 1 + mThreshold;
1012  double amount = std::pow(2.0, 7.0 * mParams.mParam1 / 100.0); // range 1 to 128
1013  double peak = LogCurve(mThreshold, 1.0, amount);
1014  mMakeupGain = 1.0 / peak;
1015  mTable[STEPS] = 0.0; // origin
1016 
1017  // positive half of table
1018  for (int n = STEPS; n < TABLESIZE; n++) {
1019  if (n < (STEPS * threshold)) // origin to threshold
1020  mTable[n] = n/(float)STEPS - 1;
1021  else
1022  mTable[n] = LogCurve(mThreshold, n/(double)STEPS - 1, amount);
1023  }
1024  CopyHalfTable();
1025 }
1026 
1027 float EffectDistortion::LogCurve(double threshold, float value, double ratio)
1028 {
1029  return threshold + ((std::exp(ratio * (threshold - value)) - 1) / -ratio);
1030 }
1031 
1033 {
1034  double amount = std::min(0.999, DB_TO_LINEAR(-1 * mParams.mParam1)); // avoid divide by zero
1035 
1036  for (int n = STEPS; n < TABLESIZE; n++) {
1037  double linVal = n/(float)STEPS;
1038  double scale = -1.0 / (1.0 - amount); // unity gain at 0dB
1039  double curve = std::exp((linVal - 1) * std::log(amount));
1040  mTable[n] = scale * (curve -1);
1041  }
1042  CopyHalfTable();
1043 }
1044 
1046 {
1047  double amount = mParams.mParam1;
1048  double stepsize = 1.0 / STEPS;
1049  double linVal = 0;
1050 
1051  if (amount == 0){
1052  for (int n = STEPS; n < TABLESIZE; n++) {
1053  mTable[n] = linVal;
1054  linVal += stepsize;
1055  }
1056  }
1057  else {
1058  for (int n = STEPS; n < TABLESIZE; n++) {
1059  mTable[n] = std::log(1 + (amount * linVal)) / std::log(1 + amount);
1060  linVal += stepsize;
1061  }
1062  }
1063  CopyHalfTable();
1064 }
1065 
1067 {
1068  int iter = std::floor(mParams.mParam1 / 20.0);
1069  double fractionalpart = (mParams.mParam1 / 20.0) - iter;
1070  double stepsize = 1.0 / STEPS;
1071  double linVal = 0;
1072 
1073  for (int n = STEPS; n < TABLESIZE; n++) {
1074  mTable[n] = linVal;
1075  for (int i = 0; i < iter; i++) {
1076  mTable[n] = std::sin(mTable[n] * M_PI_2);
1077  }
1078  mTable[n] += ((std::sin(mTable[n] * M_PI_2) - mTable[n]) * fractionalpart);
1079  linVal += stepsize;
1080  }
1081  CopyHalfTable();
1082 }
1083 
1085 {
1086  double amount = mParams.mParam1 * std::sqrt(3.0) / 100.0;
1087  double gain = 1.0;
1088  if (amount != 0.0)
1089  gain = 1.0 / Cubic(std::min(amount, 1.0));
1090 
1091  double stepsize = amount / STEPS;
1092  double x = -amount;
1093 
1094  if (amount == 0) {
1095  for (int i = 0; i < TABLESIZE; i++) {
1096  mTable[i] = (i / (double)STEPS) - 1.0;
1097  }
1098  }
1099  else {
1100  for (int i = 0; i < TABLESIZE; i++) {
1101  mTable[i] = gain * Cubic(x);
1102  for (int j = 0; j < mParams.mRepeats; j++) {
1103  mTable[i] = gain * Cubic(mTable[i] * amount);
1104  }
1105  x += stepsize;
1106  }
1107  }
1108 }
1109 
1110 double EffectDistortion::Cubic(double x)
1111 {
1112  if (mParams.mParam1 == 0.0)
1113  return x;
1114 
1115  return x - (std::pow(x, 3.0) / 3.0);
1116 }
1117 
1118 
1120 {
1121  double amount = mParams.mParam1 / -100.0;
1122  // double C = std::sin(std::max(0.001, mParams.mParam2) / 100.0) * 10.0;
1123  double C = std::max(0.001, mParams.mParam2) / 10.0;
1124 
1125  double step = 1.0 / STEPS;
1126  double xval = -1.0;
1127 
1128  for (int i = 0; i < TABLESIZE; i++) {
1129  mTable[i] = ((1 + amount) * xval) -
1130  (xval * (amount / std::tanh(C)) * std::tanh(C * xval));
1131  xval += step;
1132  }
1133 }
1134 
1136 {
1137  int iter = std::floor(mParams.mParam1 / 20.0);
1138  double fractionalpart = (mParams.mParam1 / 20.0) - iter;
1139  double stepsize = 1.0 / STEPS;
1140  double linVal = 0.0;
1141 
1142  for (int n = STEPS; n < TABLESIZE; n++) {
1143  mTable[n] = linVal;
1144  for (int i = 0; i < iter; i++) {
1145  mTable[n] = (1.0 + std::sin((mTable[n] * M_PI) - M_PI_2)) / 2.0;
1146  }
1147  mTable[n] += (((1.0 + std::sin((mTable[n] * M_PI) - M_PI_2)) / 2.0) - mTable[n]) * fractionalpart;
1148  linVal += stepsize;
1149  }
1150  CopyHalfTable();
1151 }
1152 
1154 {
1155  double noiseFloor = DB_TO_LINEAR(mParams.mNoiseFloor);
1156  int numPasses = mParams.mRepeats;
1157  double fractionalPass = mParams.mParam1 / 100.0;
1158 
1159  const int numPoints = 6;
1160  const double gainFactors[numPoints] = { 0.80, 1.00, 1.20, 1.20, 1.00, 0.80 };
1161  double gainLimits[numPoints] = { 0.0001, 0.0, 0.1, 0.3, 0.5, 1.0 };
1162  double addOnValues[numPoints];
1163 
1164  gainLimits[1] = noiseFloor;
1165  /* In the original Leveller effect, behaviour was undefined for threshold > 20 dB.
1166  * If we want to support > 20 dB we need to scale the points to keep them non-decreasing.
1167  *
1168  * if (noiseFloor > gainLimits[2]) {
1169  * for (int i = 3; i < numPoints; i++) {
1170  * gainLimits[i] = noiseFloor + ((1 - noiseFloor)*((gainLimits[i] - 0.1) / 0.9));
1171  * }
1172  * gainLimits[2] = noiseFloor;
1173  * }
1174  */
1175 
1176  // Calculate add-on values
1177  addOnValues[0] = 0.0;
1178  for (int i = 0; i < numPoints-1; i++) {
1179  addOnValues[i+1] = addOnValues[i] + (gainLimits[i] * (gainFactors[i] - gainFactors[1 + i]));
1180  }
1181 
1182  // Positive half of table.
1183  // The original effect increased the 'strength' of the effect by
1184  // repeated passes over the audio data.
1185  // Here we model that more efficiently by repeated passes over a linear table.
1186  for (int n = STEPS; n < TABLESIZE; n++) {
1187  mTable[n] = ((double) (n - STEPS) / (double) STEPS);
1188  for (int i = 0; i < numPasses; i++) {
1189  // Find the highest index for gain adjustment
1190  int index = numPoints - 1;
1191  for (int i = index; i >= 0 && mTable[n] < gainLimits[i]; i--) {
1192  index = i;
1193  }
1194  // the whole number of 'repeats'
1195  mTable[n] = (mTable[n] * gainFactors[index]) + addOnValues[index];
1196  }
1197  // Extrapolate for fine adjustment.
1198  // tiny fractions are not worth the processing time
1199  if (fractionalPass > 0.001) {
1200  int index = numPoints - 1;
1201  for (int i = index; i >= 0 && mTable[n] < gainLimits[i]; i--) {
1202  index = i;
1203  }
1204  mTable[n] += fractionalPass * ((mTable[n] * (gainFactors[index] - 1)) + addOnValues[index]);
1205  }
1206  }
1207  CopyHalfTable();
1208 }
1209 
1211 {
1212  double amount = (mParams.mParam1 / 50.0) - 1;
1213  double stepsize = 1.0 / STEPS;
1214  int index = STEPS;
1215 
1216  // positive half of waveform is passed unaltered.
1217  for (int n = 0; n <= STEPS; n++) {
1218  mTable[index] = n * stepsize;
1219  index += 1;
1220  }
1221 
1222  // negative half of table
1223  index = STEPS - 1;
1224  for (int n = 1; n <= STEPS; n++) {
1225  mTable[index] = n * stepsize * amount;
1226  index--;
1227  }
1228 }
1229 
1231 {
1232  // The LADSPA "hardLimiter 1413" is basically hard clipping,
1233  // but with a 'kind of' wet/dry mix:
1234  // out = ((wet-residual)*clipped) + (residual*in)
1235  HardClip();
1236 }
1237 
1238 
1239 // Helper functions for lookup tables
1240 
1242 {
1243  // Copy negative half of table from positive half
1244  int count = TABLESIZE - 1;
1245  for (int n = 0; n < STEPS; n++) {
1246  mTable[n] = -mTable[count];
1247  count--;
1248  }
1249 }
1250 
1251 
1252 float EffectDistortion::WaveShaper(float sample)
1253 {
1254  float out;
1255  int index;
1256  double xOffset;
1257  double amount = 1;
1258 
1259  switch (mParams.mTableChoiceIndx)
1260  {
1261  // Do any pre-processing here
1262  case kHardClip:
1263  // Pre-gain
1264  amount = mParams.mParam1 / 100.0;
1265  sample *= 1+amount;
1266  break;
1267  default: break;
1268  }
1269 
1270  index = std::floor(sample * STEPS) + STEPS;
1271  index = wxMax<int>(wxMin<int>(index, 2 * STEPS - 1), 0);
1272  xOffset = ((1 + sample) * STEPS) - index;
1273  xOffset = wxMin<double>(wxMax<double>(xOffset, 0.0), 1.0); // Clip at 0dB
1274 
1275  // linear interpolation: y = y0 + (y1-y0)*(x-x0)
1276  out = mTable[index] + (mTable[index + 1] - mTable[index]) * xOffset;
1277 
1278  return out;
1279 }
1280 
1281 
1283 {
1284  // Rolling average gives less offset at the start than an IIR filter.
1285  const unsigned int queueLength = std::floor(data.samplerate / 20.0);
1286 
1287  data.queuetotal += sample;
1288  data.queuesamples.push(sample);
1289 
1290  if (data.queuesamples.size() > queueLength) {
1291  data.queuetotal -= data.queuesamples.front();
1292  data.queuesamples.pop();
1293  }
1294 
1295  return sample - (data.queuetotal / data.queuesamples.size());
1296 }
bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap=NULL) override
Definition: Distortion.cpp:239
kTableType
Definition: Distortion.cpp:44
static wxArrayString names()
Definition: Tags.cpp:697
wxStaticText * mParam1Txt
Definition: Distortion.h:204
unsigned GetAudioOutCount() override
Definition: Distortion.cpp:234
wxStaticText * mNoiseFloorTxt
Definition: Distortion.h:203
#define skipsamples
Definition: Distortion.cpp:88
bool SupportsRealtime() override
Definition: Distortion.cpp:218
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override
Definition: Distortion.cpp:259
wxSlider * mParam1S
Definition: Distortion.h:196
void UpdateControl(control id, bool enable, wxString name)
Definition: Distortion.cpp:852
wxTextCtrl * mNoiseFloorT
Definition: Distortion.h:189
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:366
void OnThresholdSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:625
wxArrayString GetFactoryPresets() override
Definition: Distortion.cpp:320
wxChoice * mTypeChoiceCtrl
Definition: Distortion.h:187
wxString mOldRepeatsTxt
Definition: Distortion.h:212
size_t InstanceProcess(EffectDistortionState &data, float **inBlock, float **outBlock, size_t blockLen)
Definition: Distortion.cpp:529
size_t SetBlockSize(size_t maxBlockSize) override
Definition: Effect.cpp:347
bool mbSavedFilterState
Definition: Distortion.h:178
double Cubic(double x)
void OnParam1Text(wxCommandEvent &evt)
Definition: Distortion.cpp:646
EffectType GetType() override
Definition: Distortion.cpp:213
bool RealtimeInitialize() override
Definition: Distortion.cpp:250
void EndMultiColumn()
Param(TableTypeIndx, int, wxT("Type"), 0, 0, kNumTableTypes-1, 1)
WX_DEFINE_OBJARRAY(EffectDistortionStateArray)
#define XO(s)
Definition: Internat.h:30
#define ReadAndVerifyEnum(name, list)
Definition: Effect.h:781
wxString GetDescription() override
Definition: Distortion.cpp:201
void OnRepeatsSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:676
double mSampleRate
Definition: Effect.h:455
void OnTypeChoice(wxCommandEvent &evt)
Definition: Distortion.cpp:604
#define TABLESIZE
Definition: Distortion.h:28
wxTextCtrl * mParam1T
Definition: Distortion.h:190
wxSlider * mRepeatsS
Definition: Distortion.h:198
#define DISTORTION_PLUGIN_SYMBOL
Definition: Distortion.h:26
sampleCount skipcount
Definition: Distortion.h:34
void OnParam2Slider(wxCommandEvent &evt)
Definition: Distortion.cpp:664
float LogCurve(double threshold, float value, double ratio)
void EndVerticalLay()
Definition: ShuttleGui.cpp:991
void SetSizeHints(int minX=-1, int minY=-1)
wxTextCtrl * mThresholdT
Definition: Distortion.h:188
bool GetAutomationParameters(EffectAutomationParameters &parms) override
Definition: Distortion.cpp:286
void OnDCBlockCheckbox(wxCommandEvent &evt)
Definition: Distortion.cpp:611
wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:493
A WaveShaper distortion effect.
Definition: Distortion.h:50
wxCheckBox * AddCheckBox(const wxString &Prompt, const wxString &Selected)
Definition: ShuttleGui.cpp:267
#define ReadAndVerifyInt(name)
Definition: Effect.h:786
wxString defaultLabel(int index)
Definition: Distortion.cpp:126
void EvenHarmonicTable()
wxStaticText * mParam2Txt
Definition: Distortion.h:205
static const wxString kTableTypeStrings[kNumTableTypes]
Definition: Distortion.cpp:60
bool RealtimeFinalize() override
Definition: Distortion.cpp:270
virtual ~EffectDistortion()
Definition: Distortion.cpp:190
wxString ManualPage() override
Definition: Distortion.cpp:206
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:998
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:331
wxSlider * mThresholdS
Definition: Distortion.h:194
ShuttleGui & Id(int id)
double mTable[TABLESIZE]
Definition: Distortion.h:176
#define STEPS
Definition: Distortion.h:27
void SetStyle(int Style)
Definition: ShuttleGui.h:252
unsigned GetAudioInCount() override
Definition: Distortion.cpp:229
#define ReadAndVerifyDouble(name)
Definition: Effect.h:787
wxTextCtrl * mParam2T
Definition: Distortion.h:191
wxSlider * mParam2S
Definition: Distortion.h:197
int min(int a, int b)
void InstanceInit(EffectDistortionState &data, float sampleRate)
Definition: Distortion.cpp:505
float DCFilter(EffectDistortionState &data, float sample)
wxString mOldParam2Txt
Definition: Distortion.h:211
bool LoadFactoryPreset(int id) override
Definition: Distortion.cpp:332
float WaveShaper(float sample)
wxWindow * mUIParent
Definition: Effect.h:471
EffectDistortionState mMaster
Definition: Distortion.h:173
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
wxStaticText * mRepeatsTxt
Definition: Distortion.h:206
double mMakeupGain
Definition: Distortion.h:182
#define LINEAR_TO_DB(x)
Definition: Audacity.h:210
void OnNoiseFloorText(wxCommandEvent &evt)
Definition: Distortion.cpp:633
void OnNoiseFloorSlider(wxCommandEvent &evt)
Definition: Distortion.cpp:639
wxStaticText * mThresholdTxt
Definition: Distortion.h:202
wxDialog * mUIDialog
Definition: Effect.h:470
void OnRepeatsText(wxCommandEvent &evt)
Definition: Distortion.cpp:670
const wxChar * name
Definition: Distortion.cpp:94
wxSlider * mNoiseFloorS
Definition: Distortion.h:195
static const struct @17 FactoryPresets[]
wxString GetSymbol() override
Definition: Distortion.cpp:196
void OnParam2Text(wxCommandEvent &evt)
Definition: Distortion.cpp:658
#define M_PI
Definition: Distortion.cpp:28
wxArrayString mTableTypes
Definition: Distortion.h:185
wxStaticText * AddVariableText(const wxString &Str, bool bCenter=false, int PositionFlags=0)
Definition: ShuttleGui.cpp:373
bool TransferDataToWindow() override
Definition: Distortion.cpp:472
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:701
#define ReadAndVerifyBool(name)
Definition: Effect.h:789
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override
Definition: Distortion.cpp:277
bool SetAutomationParameters(EffectAutomationParameters &parms) override
Definition: Distortion.cpp:299
wxCheckBox * mDCBlockCheckBox
Definition: Distortion.h:200
std::queue< float > queuesamples
Definition: Distortion.h:44
size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override
Definition: Distortion.cpp:245
void PopulateOrExchange(ShuttleGui &S) override
Definition: Distortion.cpp:353
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:209
EffectDistortion::Params params
Definition: Distortion.cpp:95
wxTextCtrl * mRepeatsT
Definition: Distortion.h:192
const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB)
void UpdateControlText(wxTextCtrl *textCtrl, wxString &string, bool enabled)
Definition: Distortion.cpp:932
void OnThresholdText(wxCommandEvent &evt)
Definition: Distortion.cpp:618
bool TransferDataFromWindow() override
Definition: Distortion.cpp:493
EffectDistortionStateArray mSlaves
Definition: Distortion.h:174
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:192
wxString mOldThresholdTxt
Definition: Distortion.h:208
wxString mOldParam1Txt
Definition: Distortion.h:210
void OnParam1Slider(wxCommandEvent &evt)
Definition: Distortion.cpp:652
wxSlider * AddSlider(const wxString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:456
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:982