Audacity 3.2.0
Compressor.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Compressor.cpp
6
7 Dominic Mazzoni
8 Martyn Shaw
9 Steve Jolly
10
11*******************************************************************//****************************************************************//*******************************************************************/
26
27
28#include "Compressor.h"
29#include "LoadEffects.h"
30
31#include <math.h>
32
33#include <wx/brush.h>
34#include <wx/checkbox.h>
35#include <wx/dcclient.h>
36#include <wx/intl.h>
37#include <wx/slider.h>
38#include <wx/stattext.h>
39
40#include "AColor.h"
41#include "Prefs.h"
42#include "../ShuttleGui.h"
43#include "Theme.h"
44#include "float_cast.h"
45#include "../widgets/Ruler.h"
46
47#include "../WaveTrack.h"
48#include "AllThemeResources.h"
49
50enum
51{
52 ID_Threshold = 10000,
57};
58
60{
62 Threshold, NoiseFloor, Ratio, // positive number > 1.0
63 AttackTime, // seconds
64 ReleaseTime, // seconds
66 > parameters;
67 return parameters;
68}
69
70//----------------------------------------------------------------------------
71// EffectCompressor
72//----------------------------------------------------------------------------
73
75{ XO("Compressor") };
76
78
79BEGIN_EVENT_TABLE(EffectCompressor, wxEvtHandler)
80 EVT_SLIDER(wxID_ANY, EffectCompressor::OnSlider)
82
84{
85 Parameters().Reset(*this);
86
87 mThreshold = 0.25;
88 mNoiseFloor = 0.01;
89 mCompression = 0.5;
90 mFollowLen = 0;
91
92 SetLinearEffectFlag(false);
93}
94
96{
97}
98
99// ComponentInterface implementation
100
102{
103 return Symbol;
104}
105
107{
108 return XO("Compresses the dynamic range of audio");
109}
110
112{
113 return L"Compressor";
114}
115
116// EffectDefinitionInterface implementation
117
119{
120 return EffectTypeProcess;
121}
122
123// Effect Implementation
124
125namespace {
126
128 /* i18n-hint: usually leave this as is as dB doesn't get translated*/
129{ return XO("%3d dB").Format(value); }
130
132{ return XO("%.2f secs").Format( value ); }
133
135{ return XO("%.1f secs").Format( value ); }
136
137TranslatableString RatioTextFormat( int sliderValue, double value )
138{
139 auto format = (sliderValue % 10 == 0)
140 /* i18n-hint: Unless your language has a different convention for ratios,
141 * like 8:1, leave as is.*/
142 ? XO("%.0f:1")
143 /* i18n-hint: Unless your language has a different convention for ratios,
144 * like 8:1, leave as is.*/
145 : XO("%.1f:1");
146 return format.Format( value );
147}
148
149TranslatableString RatioLabelFormat( int sliderValue, double value )
150{
151 auto format = (sliderValue % 10 == 0)
152 ? XO("Ratio %.0f to 1")
153 : XO("Ratio %.1f to 1");
154 return format.Format( value );
155}
156
157}
158
159std::unique_ptr<EffectUIValidator> EffectCompressor::PopulateOrExchange(
161{
162 S.SetBorder(5);
163
164 S.StartHorizontalLay(wxEXPAND, true);
165 {
166 S.SetBorder(10);
167 mPanel = safenew EffectCompressorPanel(S.GetParent(), wxID_ANY,
170 mRatio);
171 S.Prop(true)
172 .Position(wxEXPAND | wxALL)
173 .MinSize( { 400, 200 } )
174 .AddWindow(mPanel);
175 S.SetBorder(5);
176 }
177 S.EndHorizontalLay();
178
179 S.StartStatic( {} );
180 {
181 S.StartMultiColumn(3, wxEXPAND);
182 {
183 S.SetStretchyCol(1);
184 mThresholdLabel = S.AddVariableText(XO("&Threshold:"), true,
185 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
187 .Name(XO("Threshold"))
188 .Style(wxSL_HORIZONTAL)
189 .AddSlider( {},
193 mThresholdText = S.AddVariableText(ThresholdFormat(999), true,
194 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
195
196 mNoiseFloorLabel = S.AddVariableText(XO("&Noise Floor:"), true,
197 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
199 .Name(XO("Noise Floor"))
200 .Style(wxSL_HORIZONTAL)
201 .AddSlider( {},
205 mNoiseFloorText = S.AddVariableText(ThresholdFormat(999),
206 true, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
207
208 mRatioLabel = S.AddVariableText(XO("&Ratio:"), true,
209 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
211 .Name(XO("Ratio"))
212 .Style(wxSL_HORIZONTAL)
213 .AddSlider( {},
216 Ratio.min * Ratio.scale);
217 mRatioSlider->SetPageSize(5);
218 mRatioText = S.AddVariableText(RatioTextFormat( 1, 99.9 ), true,
219 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
220
221 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
222 * an 'attack' phase where the sound builds up and a 'decay' where the
223 * sound dies away. So this means 'onset duration'. */
224 mAttackLabel = S.AddVariableText(XO("&Attack Time:"), true,
225 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
227 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
228 * an 'attack' phase where the sound builds up and a 'decay' where the
229 * sound dies away. So this means 'onset duration'. */
230 .Name(XO("Attack Time"))
231 .Style(wxSL_HORIZONTAL)
232 .AddSlider( {},
236 mAttackText = S.AddVariableText(
237 AttackTimeFormat(9.99),
238 true, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
239
240 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
241 * an 'attack' phase where the sound builds up and a 'decay' or 'release' where the
242 * sound dies away. */
243 mDecayLabel = S.AddVariableText(XO("R&elease Time:"), true,
244 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
246 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
247 * an 'attack' phase where the sound builds up and a 'decay' or 'release' where the
248 * sound dies away. */
249 .Name(XO("Release Time"))
250 .Style(wxSL_HORIZONTAL)
251 .AddSlider( {},
255
256 mDecayText = S.AddVariableText(
257 DecayTimeFormat(99.9),
258 true, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
259 }
260 S.EndMultiColumn();
261 }
262 S.EndStatic();
263
264 S.StartHorizontalLay(wxCENTER, false);
265 {
266 /* i18n-hint: Make-up, i.e. correct for any reduction, rather than fabricate it.*/
267 mGainCheckBox = S.AddCheckBox(XXO("Ma&ke-up gain for 0 dB after compressing"),
268 Normalize.def);
269 /* i18n-hint: "Compress" here means reduce variations of sound volume,
270 NOT related to file-size compression; Peaks means extremes in volume */
271 mPeakCheckBox = S.AddCheckBox(XXO("C&ompress based on Peaks"),
272 UsePeak.def);
273 }
274 S.EndHorizontalLay();
275 return nullptr;
276}
277
279{
282 mRatioSlider->SetValue(lrint(mRatio * Ratio.scale));
285 mGainCheckBox->SetValue(mNormalize);
286 mPeakCheckBox->SetValue(mUsePeak);
287
288 UpdateUI();
289
290 return true;
291}
292
294{
296}
297
299{
300 // To do: eliminate this by using control validators instead
301 mThresholdDB = (double) mThresholdSlider->GetValue();
302 mNoiseFloorDB = (double) mNoiseFloorSlider->GetValue() / NoiseFloor.scale;
303 mRatio = (double) mRatioSlider->GetValue() / Ratio.scale;
304 mAttackTime = (double) mAttackSlider->GetValue() / 100.0; //AttackTime.scale;
305 mDecayTime = (double) mDecaySlider->GetValue() / ReleaseTime.scale;
306 mNormalize = mGainCheckBox->GetValue();
307 mUsePeak = mPeakCheckBox->GetValue();
308
309 return true;
310}
311
312// EffectTwoPassSimpleMono implementation
313
315{
318 mNoiseCounter = 100;
319
320 mAttackInverseFactor = exp(log(mThreshold) / (mCurRate * mAttackTime + 0.5));
322 mDecayFactor = exp(log(mThreshold) / (mCurRate * mDecayTime + 0.5));
323
324 if(mRatio > 1)
325 mCompression = 1.0-1.0/mRatio;
326 else
327 mCompression = 0.0;
328
330
331 mCircleSize = 100;
332 mCircle.reinit( mCircleSize, true );
333 mCirclePos = 0;
334 mRMSSum = 0.0;
335
336 return true;
337}
338
340{
341 mMax=0.0;
342 if (!mNormalize)
344
345 // Find the maximum block length required for any track
346 size_t maxlen = inputTracks()->Selected< const WaveTrack >().max(
348 );
349 mFollow1.reset();
350 mFollow2.reset();
351 // Allocate buffers for the envelope
352 if(maxlen > 0) {
353 mFollow1.reinit(maxlen);
354 mFollow2.reinit(maxlen);
355 }
356 mFollowLen = maxlen;
357
358 return true;
359}
360
362{
363 // Actually, this should not even be called, because we call
364 // DisableSecondPass() before, if mNormalize is false.
365 return mNormalize;
366}
367
368// Process the input with 2 buffers available at a time
369// buffer1 will be written upon return
370// buffer2 will be passed as buffer1 on the next call
372 (float *buffer1, size_t len1, float *buffer2, size_t len2)
373{
374 // If buffers are bigger than allocated, then abort
375 // (this should never happen, but if it does, we don't want to crash)
376 if((len1 > mFollowLen) || (len2 > mFollowLen))
377 return false;
378
379 // This makes sure that the initial value is well-chosen
380 // buffer1 == NULL on the first and only the first call
381 if (buffer1 == NULL) {
382 // Initialize the mLastLevel to the peak level in the first buffer
383 // This avoids problems with large spike events near the beginning of the track
385 for(size_t i=0; i<len2; i++) {
386 if(mLastLevel < fabs(buffer2[i]))
387 mLastLevel = fabs(buffer2[i]);
388 }
389 }
390
391 // buffer2 is NULL on the last and only the last call
392 if(buffer2 != NULL) {
393 Follow(buffer2, mFollow2.get(), len2, mFollow1.get(), len1);
394 }
395
396 if(buffer1 != NULL) {
397 for (size_t i = 0; i < len1; i++) {
398 buffer1[i] = DoCompression(buffer1[i], mFollow1[i]);
399 }
400 }
401
402
403#if 0
404 // Copy the envelope over the track data (for debug purposes)
405 memcpy(buffer1, mFollow1, len1*sizeof(float));
406#endif
407
408 // Rotate the buffer pointers
409 mFollow1.swap(mFollow2);
410
411 return true;
412}
413
414bool EffectCompressor::ProcessPass2(float *buffer, size_t len)
415{
416 if (mMax != 0)
417 {
418 for (size_t i = 0; i < len; i++)
419 buffer[i] /= mMax;
420 }
421
422 return true;
423}
424
426{
427 // Recompute the RMS sum periodically to prevent accumulation of rounding errors
428 // during long waveforms
429 mRMSSum = 0;
430 for(size_t i=0; i<mCircleSize; i++)
431 mRMSSum += mCircle[i];
432}
433
435{
436 float level;
437
438 // Calculate current level from root-mean-squared of
439 // circular buffer ("RMS")
441 mCircle[mCirclePos] = value*value;
443 level = sqrt(mRMSSum/mCircleSize);
445
446 return level;
447}
448
449void EffectCompressor::Follow(float *buffer, float *env, size_t len, float *previous, size_t previous_len)
450{
451 /*
452
453 "Follow"ing algorithm by Roger B. Dannenberg, taken from
454 Nyquist. His description follows. -DMM
455
456 Description: this is a sophisticated envelope follower.
457 The input is an envelope, e.g. something produced with
458 the AVG function. The purpose of this function is to
459 generate a smooth envelope that is generally not less
460 than the input signal. In other words, we want to "ride"
461 the peaks of the signal with a smooth function. The
462 algorithm is as follows: keep a current output value
463 (called the "value"). The value is allowed to increase
464 by at most rise_factor and decrease by at most fall_factor.
465 Therefore, the next value should be between
466 value * rise_factor and value * fall_factor. If the input
467 is in this range, then the next value is simply the input.
468 If the input is less than value * fall_factor, then the
469 next value is just value * fall_factor, which will be greater
470 than the input signal. If the input is greater than value *
471 rise_factor, then we compute a rising envelope that meets
472 the input value by working bacwards in time, changing the
473 previous values to input / rise_factor, input / rise_factor^2,
474 input / rise_factor^3, etc. until this NEW envelope intersects
475 the previously computed values. There is only a limited buffer
476 in which we can work backwards, so if the NEW envelope does not
477 intersect the old one, then make yet another pass, this time
478 from the oldest buffered value forward, increasing on each
479 sample by rise_factor to produce a maximal envelope. This will
480 still be less than the input.
481
482 The value has a lower limit of floor to make sure value has a
483 reasonable positive value from which to begin an attack.
484 */
485 double level,last;
486
487 if(!mUsePeak) {
488 // Update RMS sum directly from the circle buffer
489 // to avoid accumulation of rounding errors
491 }
492 // First apply a peak detect with the requested decay rate
493 last = mLastLevel;
494 for(size_t i=0; i<len; i++) {
495 if(mUsePeak)
496 level = fabs(buffer[i]);
497 else // use RMS
498 level = AvgCircle(buffer[i]);
499 // Don't increase gain when signal is continuously below the noise floor
500 if(level < mNoiseFloor) {
502 } else {
503 mNoiseCounter = 0;
504 }
505 if(mNoiseCounter < 100) {
506 last *= mDecayFactor;
507 if(last < mThreshold)
508 last = mThreshold;
509 if(level > last)
510 last = level;
511 }
512 env[i] = last;
513 }
514 mLastLevel = last;
515
516 // Next do the same process in reverse direction to get the requested attack rate
517 last = mLastLevel;
518 for(size_t i = len; i--;) {
519 last *= mAttackInverseFactor;
520 if(last < mThreshold)
521 last = mThreshold;
522 if(env[i] < last)
523 env[i] = last;
524 else
525 last = env[i];
526 }
527
528 if((previous != NULL) && (previous_len > 0)) {
529 // If the previous envelope was passed, propagate the rise back until we intersect
530 for(size_t i = previous_len; i--;) {
531 last *= mAttackInverseFactor;
532 if(last < mThreshold)
533 last = mThreshold;
534 if(previous[i] < last)
535 previous[i] = last;
536 else // Intersected the previous envelope buffer, so we are finished
537 return;
538 }
539 // If we can't back up far enough, project the starting level forward
540 // until we intersect the desired envelope
541 last = previous[0];
542 for(size_t i=1; i<previous_len; i++) {
543 last *= mAttackFactor;
544 if(previous[i] > last)
545 previous[i] = last;
546 else // Intersected the desired envelope, so we are finished
547 return;
548 }
549 // If we still didn't intersect, then continue ramp up into current buffer
550 for(size_t i=0; i<len; i++) {
551 last *= mAttackFactor;
552 if(buffer[i] > last)
553 buffer[i] = last;
554 else // Finally got an intersect
555 return;
556 }
557 // If we still didn't intersect, then reset mLastLevel
558 mLastLevel = last;
559 }
560}
561
562float EffectCompressor::DoCompression(float value, double env)
563{
564 float out;
565 if(mUsePeak) {
566 // Peak values map 1.0 to 1.0 - 'upward' compression
567 out = value * pow(1.0/env, mCompression);
568 } else {
569 // With RMS-based compression don't change values below mThreshold - 'downward' compression
570 out = value * pow(mThreshold/env, mCompression);
571 }
572
573 // Retain the maximum value for use in the normalization pass
574 if(mMax < fabs(out))
575 mMax = fabs(out);
576
577 return out;
578}
579
580void EffectCompressor::OnSlider(wxCommandEvent & WXUNUSED(evt))
581{
583 UpdateUI();
584}
585
587{
588 mThresholdLabel->SetName(wxString::Format(_("Threshold %d dB"), (int) mThresholdDB));
589 mThresholdText->SetLabel(ThresholdFormat((int) mThresholdDB).Translation());
590 mThresholdText->SetName(mThresholdText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
591
592 mNoiseFloorLabel->SetName(wxString::Format(_("Noise Floor %d dB"), (int) mNoiseFloorDB));
593 mNoiseFloorText->SetLabel(ThresholdFormat((int) mNoiseFloorDB).Translation());
594 mNoiseFloorText->SetName(mNoiseFloorText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
595
596 mRatioLabel->SetName(
598 mRatioText->SetLabel(
600 mRatioText->SetName(mRatioText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
601
602 mAttackLabel->SetName(wxString::Format(_("Attack Time %.2f secs"), mAttackTime));
603 mAttackText->SetLabel(AttackTimeFormat(mAttackTime).Translation());
604 mAttackText->SetName(mAttackText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
605
606 mDecayLabel->SetName(wxString::Format(_("Release Time %.1f secs"), mDecayTime));
607 mDecayText->SetLabel(DecayTimeFormat(mDecayTime).Translation());
608 mDecayText->SetName(mDecayText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
609
610 mPanel->Refresh(false);
611
612 return;
613}
614
615//----------------------------------------------------------------------------
616// EffectCompressorPanel
617//----------------------------------------------------------------------------
618
619BEGIN_EVENT_TABLE(EffectCompressorPanel, wxPanelWrapper)
623
624EffectCompressorPanel::EffectCompressorPanel(wxWindow *parent, wxWindowID winid,
625 double & threshold,
626 double & noiseFloor,
627 double & ratio)
628: wxPanelWrapper(parent, winid),
629 threshold(threshold),
630 noiseFloor(noiseFloor),
631 ratio(ratio)
632{
633}
634
635void EffectCompressorPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
636{
637 wxPaintDC dc(this);
638
639 int width, height;
640 GetSize(&width, &height);
641
642 double rangeDB = 60;
643
644 // Ruler
645 int w = 0;
646 int h = 0;
647
648 Ruler vRuler;
649 vRuler.SetBounds(0, 0, width, height);
650 vRuler.SetOrientation(wxVERTICAL);
651 vRuler.SetRange(0, -rangeDB);
653 vRuler.SetUnits(XO("dB"));
654 vRuler.GetMaxSize(&w, NULL);
655
656 Ruler hRuler;
657 hRuler.SetBounds(0, 0, width, height);
658 hRuler.SetOrientation(wxHORIZONTAL);
659 hRuler.SetRange(-rangeDB, 0);
661 hRuler.SetUnits(XO("dB"));
662 hRuler.SetFlip(true);
663 hRuler.GetMaxSize(NULL, &h);
664
665 vRuler.SetBounds(0, 0, w, height - h);
666 hRuler.SetBounds(w, height - h, width, height);
667
668 vRuler.SetTickColour( theTheme.Colour( clrGraphLabels ));
669 hRuler.SetTickColour( theTheme.Colour( clrGraphLabels ));
670
671#if defined(__WXMSW__)
672 dc.Clear();
673#endif
674
675 wxRect border;
676 border.x = w;
677 border.y = 0;
678 border.width = width - w;
679 border.height = height - h + 1;
680
681 dc.SetBrush(*wxWHITE_BRUSH);
682 dc.SetPen(*wxBLACK_PEN);
683 dc.DrawRectangle(border);
684
685 wxRect envRect = border;
686 envRect.Deflate( 2, 2 );
687
688 int kneeX = lrint((rangeDB+threshold)*envRect.width/rangeDB);
689 int kneeY = lrint((rangeDB+threshold/ratio)*envRect.height/rangeDB);
690
691 int finalY = envRect.height;
692 int startY = lrint((threshold*(1.0/ratio-1.0))*envRect.height/rangeDB);
693
694 // Yellow line for threshold
695/* dc.SetPen(wxPen(wxColour(220, 220, 0), 1, wxSOLID));
696 AColor::Line(dc,
697 envRect.x,
698 envRect.y + envRect.height - kneeY,
699 envRect.x + envRect.width - 1,
700 envRect.y + envRect.height - kneeY);*/
701
702 // Was: Nice dark red line for the compression diagram
703// dc.SetPen(wxPen(wxColour(180, 40, 40), 3, wxSOLID));
704
705 // Nice blue line for compressor, same color as used in the waveform envelope.
706 dc.SetPen( AColor::WideEnvelopePen) ;
707
708 AColor::Line(dc,
709 envRect.x,
710 envRect.y + envRect.height - startY,
711 envRect.x + kneeX - 1,
712 envRect.y + envRect.height - kneeY);
713
714 AColor::Line(dc,
715 envRect.x + kneeX,
716 envRect.y + envRect.height - kneeY,
717 envRect.x + envRect.width - 1,
718 envRect.y + envRect.height - finalY);
719
720 // Paint border again
721 dc.SetBrush(*wxTRANSPARENT_BRUSH);
722 dc.SetPen(*wxBLACK_PEN);
723 dc.DrawRectangle(border);
724
725 vRuler.Draw(dc);
726 hRuler.Draw(dc);
727}
728
729void EffectCompressorPanel::OnSize(wxSizeEvent & WXUNUSED(evt))
730{
731 Refresh(false);
732}
END_EVENT_TABLE()
@ ID_Ratio
Definition: Compressor.cpp:54
@ ID_Threshold
Definition: Compressor.cpp:52
@ ID_Attack
Definition: Compressor.cpp:55
@ ID_NoiseFloor
Definition: Compressor.cpp:53
@ ID_Decay
Definition: Compressor.cpp:56
EffectType
@ EffectTypeProcess
int format
Definition: ExportPCM.cpp:56
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:535
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
static wxPen WideEnvelopePen
Definition: AColor.h:111
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
const TrackList * inputTracks() const
Definition: EffectBase.h:102
An Effect derived from EffectTwoPassSimpleMono.
Definition: Compressor.h:29
wxStaticText * mRatioText
Definition: Compressor.h:119
const EffectParameterMethods & Parameters() const override
Definition: Compressor.cpp:59
bool TwoBufferProcessPass1(float *buffer1, size_t len1, float *buffer2, size_t len2) override
Definition: Compressor.cpp:372
wxStaticText * mRatioLabel
Definition: Compressor.h:117
wxCheckBox * mPeakCheckBox
Definition: Compressor.h:130
double mThresholdDB
Definition: Compressor.h:86
static constexpr EffectParameter Ratio
Definition: Compressor.h:139
bool InitPass1() override
Definition: Compressor.cpp:339
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
Definition: Compressor.cpp:293
wxStaticText * mAttackLabel
Definition: Compressor.h:121
static constexpr EffectParameter Threshold
Definition: Compressor.h:135
wxSlider * mDecaySlider
Definition: Compressor.h:126
float AvgCircle(float x)
Definition: Compressor.cpp:434
EffectType GetType() const override
Type determines how it behaves.
Definition: Compressor.cpp:118
bool DoTransferDataFromWindow()
Definition: Compressor.cpp:298
static const ComponentInterfaceSymbol Symbol
Definition: Compressor.h:34
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
Definition: Compressor.cpp:278
Doubles mCircle
Definition: Compressor.h:83
void Follow(float *buffer, float *env, size_t len, float *previous, size_t previous_len)
Definition: Compressor.cpp:449
size_t mCirclePos
Definition: Compressor.h:82
double mAttackFactor
Definition: Compressor.h:93
wxStaticText * mDecayText
Definition: Compressor.h:127
double mNoiseFloor
Definition: Compressor.h:98
double mAttackTime
Definition: Compressor.h:85
wxSlider * mAttackSlider
Definition: Compressor.h:122
size_t mCircleSize
Definition: Compressor.h:81
static constexpr EffectParameter UsePeak
Definition: Compressor.h:147
wxSlider * mNoiseFloorSlider
Definition: Compressor.h:114
float DoCompression(float x, double env)
Definition: Compressor.cpp:562
wxSlider * mThresholdSlider
Definition: Compressor.h:110
ComponentInterfaceSymbol GetSymbol() const override
Definition: Compressor.cpp:101
wxStaticText * mDecayLabel
Definition: Compressor.h:125
double mDecayTime
Definition: Compressor.h:92
TranslatableString GetDescription() const override
Definition: Compressor.cpp:106
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Add controls to effect panel; always succeeds.
Definition: Compressor.cpp:159
double mDecayFactor
Definition: Compressor.h:95
static constexpr EffectParameter NoiseFloor
Definition: Compressor.h:137
static constexpr EffectParameter ReleaseTime
Definition: Compressor.h:143
double mNoiseFloorDB
Definition: Compressor.h:87
static constexpr EffectParameter AttackTime
Definition: Compressor.h:141
void OnSlider(wxCommandEvent &evt)
Definition: Compressor.cpp:580
EffectCompressorPanel * mPanel
Definition: Compressor.h:107
wxStaticText * mNoiseFloorText
Definition: Compressor.h:115
wxStaticText * mAttackText
Definition: Compressor.h:123
bool ProcessPass2(float *buffer, size_t len) override
Definition: Compressor.cpp:414
double mCompression
Definition: Compressor.h:97
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
Definition: Compressor.cpp:111
wxSlider * mRatioSlider
Definition: Compressor.h:118
virtual ~EffectCompressor()
Definition: Compressor.cpp:95
wxCheckBox * mGainCheckBox
Definition: Compressor.h:129
double mAttackInverseFactor
Definition: Compressor.h:94
double mThreshold
Definition: Compressor.h:96
wxStaticText * mThresholdText
Definition: Compressor.h:111
bool InitPass2() override
Definition: Compressor.cpp:361
wxStaticText * mNoiseFloorLabel
Definition: Compressor.h:113
wxStaticText * mThresholdLabel
Definition: Compressor.h:109
bool NewTrackPass1() override
Definition: Compressor.cpp:314
static constexpr EffectParameter Normalize
Definition: Compressor.h:145
void OnSize(wxSizeEvent &evt)
Definition: Compressor.cpp:729
void OnPaint(wxPaintEvent &evt)
Definition: Compressor.cpp:635
Performs effect computation.
Interface for manipulations of an Effect's settings.
Used to display a Ruler.
Definition: Ruler.h:26
void SetTickColour(const wxColour &colour)
Definition: Ruler.h:148
void SetFlip(bool flip)
Definition: Ruler.cpp:239
void SetOrientation(int orient)
Definition: Ruler.cpp:174
void Draw(wxDC &dc) const
Definition: Ruler.cpp:1428
void GetMaxSize(wxCoord *width, wxCoord *height)
Definition: Ruler.cpp:1603
void SetBounds(int left, int top, int right, int bottom)
Definition: Ruler.cpp:332
void SetUnits(const TranslatableString &units)
Definition: Ruler.cpp:153
void SetRange(double min, double max)
Definition: Ruler.cpp:188
void SetFormat(RulerFormat format)
Definition: Ruler.cpp:131
@ LinearDBFormat
Definition: Ruler.h:34
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
wxColour & Colour(int iIndex)
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1452
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1806
#define lrint(dbl)
Definition: float_cast.h:169
TranslatableString DecayTimeFormat(double value)
Definition: Compressor.cpp:134
TranslatableString RatioTextFormat(int sliderValue, double value)
Definition: Compressor.cpp:137
TranslatableString ThresholdFormat(int value)
Definition: Compressor.cpp:127
BuiltinEffectsModule::Registration< EffectCompressor > reg
Definition: Compressor.cpp:77
TranslatableString AttackTimeFormat(double value)
Definition: Compressor.cpp:131
TranslatableString RatioLabelFormat(int sliderValue, double value)
Definition: Compressor.cpp:149
const Type scale
Scaling factor, for slider control.
Definition: Shuttle.h:32
const Type def
Default value.
Definition: Shuttle.h:29
const Type min
Minimum value.
Definition: Shuttle.h:30
const Type max
Maximum value.
Definition: Shuttle.h:31
Externalized state of a plug-in.