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 const EffectOutputs *)
162{
163 S.SetBorder(5);
164
165 S.StartHorizontalLay(wxEXPAND, true);
166 {
167 S.SetBorder(10);
168 mPanel = safenew EffectCompressorPanel(S.GetParent(), wxID_ANY,
171 mRatio);
172 S.Prop(true)
173 .Position(wxEXPAND | wxALL)
174 .MinSize( { 400, 200 } )
175 .AddWindow(mPanel);
176 S.SetBorder(5);
177 }
178 S.EndHorizontalLay();
179
180 S.StartStatic( {} );
181 {
182 S.StartMultiColumn(3, wxEXPAND);
183 {
184 S.SetStretchyCol(1);
185 mThresholdLabel = S.AddVariableText(XO("&Threshold:"), true,
186 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
188 .Name(XO("Threshold"))
189 .Style(wxSL_HORIZONTAL)
190 .AddSlider( {},
194 mThresholdText = S.AddVariableText(ThresholdFormat(999), true,
195 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
196
197 mNoiseFloorLabel = S.AddVariableText(XO("&Noise Floor:"), true,
198 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
200 .Name(XO("Noise Floor"))
201 .Style(wxSL_HORIZONTAL)
202 .AddSlider( {},
206 mNoiseFloorText = S.AddVariableText(ThresholdFormat(999),
207 true, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
208
209 mRatioLabel = S.AddVariableText(XO("&Ratio:"), true,
210 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
212 .Name(XO("Ratio"))
213 .Style(wxSL_HORIZONTAL)
214 .AddSlider( {},
217 Ratio.min * Ratio.scale);
218 mRatioSlider->SetPageSize(5);
219 mRatioText = S.AddVariableText(RatioTextFormat( 1, 99.9 ), true,
220 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
221
222 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
223 * an 'attack' phase where the sound builds up and a 'decay' where the
224 * sound dies away. So this means 'onset duration'. */
225 mAttackLabel = S.AddVariableText(XO("&Attack Time:"), true,
226 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
228 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
229 * an 'attack' phase where the sound builds up and a 'decay' where the
230 * sound dies away. So this means 'onset duration'. */
231 .Name(XO("Attack Time"))
232 .Style(wxSL_HORIZONTAL)
233 .AddSlider( {},
237 mAttackText = S.AddVariableText(
238 AttackTimeFormat(9.99),
239 true, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
240
241 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
242 * an 'attack' phase where the sound builds up and a 'decay' or 'release' where the
243 * sound dies away. */
244 mDecayLabel = S.AddVariableText(XO("R&elease Time:"), true,
245 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
247 /* i18n-hint: Particularly in percussion, sounds can be regarded as having
248 * an 'attack' phase where the sound builds up and a 'decay' or 'release' where the
249 * sound dies away. */
250 .Name(XO("Release Time"))
251 .Style(wxSL_HORIZONTAL)
252 .AddSlider( {},
256
257 mDecayText = S.AddVariableText(
258 DecayTimeFormat(99.9),
259 true, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
260 }
261 S.EndMultiColumn();
262 }
263 S.EndStatic();
264
265 S.StartHorizontalLay(wxCENTER, false);
266 {
267 /* i18n-hint: Make-up, i.e. correct for any reduction, rather than fabricate it.*/
268 mGainCheckBox = S.AddCheckBox(XXO("Ma&ke-up gain for 0 dB after compressing"),
269 Normalize.def);
270 /* i18n-hint: "Compress" here means reduce variations of sound volume,
271 NOT related to file-size compression; Peaks means extremes in volume */
272 mPeakCheckBox = S.AddCheckBox(XXO("C&ompress based on Peaks"),
273 UsePeak.def);
274 }
275 S.EndHorizontalLay();
276 return nullptr;
277}
278
280{
283 mRatioSlider->SetValue(lrint(mRatio * Ratio.scale));
286 mGainCheckBox->SetValue(mNormalize);
287 mPeakCheckBox->SetValue(mUsePeak);
288
289 UpdateUI();
290
291 return true;
292}
293
295{
296 if (!mUIParent->Validate())
297 {
298 return false;
299 }
301}
302
304{
305 // To do: eliminate this by using control validators instead
306 mThresholdDB = (double) mThresholdSlider->GetValue();
307 mNoiseFloorDB = (double) mNoiseFloorSlider->GetValue() / NoiseFloor.scale;
308 mRatio = (double) mRatioSlider->GetValue() / Ratio.scale;
309 mAttackTime = (double) mAttackSlider->GetValue() / 100.0; //AttackTime.scale;
310 mDecayTime = (double) mDecaySlider->GetValue() / ReleaseTime.scale;
311 mNormalize = mGainCheckBox->GetValue();
312 mUsePeak = mPeakCheckBox->GetValue();
313
314 return true;
315}
316
317// EffectTwoPassSimpleMono implementation
318
320{
323 mNoiseCounter = 100;
324
325 mAttackInverseFactor = exp(log(mThreshold) / (mCurRate * mAttackTime + 0.5));
327 mDecayFactor = exp(log(mThreshold) / (mCurRate * mDecayTime + 0.5));
328
329 if(mRatio > 1)
330 mCompression = 1.0-1.0/mRatio;
331 else
332 mCompression = 0.0;
333
335
336 mCircleSize = 100;
337 mCircle.reinit( mCircleSize, true );
338 mCirclePos = 0;
339 mRMSSum = 0.0;
340
341 return true;
342}
343
345{
346 mMax=0.0;
347 if (!mNormalize)
349
350 // Find the maximum block length required for any track
351 size_t maxlen = inputTracks()->Selected< const WaveTrack >().max(
353 );
354 mFollow1.reset();
355 mFollow2.reset();
356 // Allocate buffers for the envelope
357 if(maxlen > 0) {
358 mFollow1.reinit(maxlen);
359 mFollow2.reinit(maxlen);
360 }
361 mFollowLen = maxlen;
362
363 return true;
364}
365
367{
368 // Actually, this should not even be called, because we call
369 // DisableSecondPass() before, if mNormalize is false.
370 return mNormalize;
371}
372
373// Process the input with 2 buffers available at a time
374// buffer1 will be written upon return
375// buffer2 will be passed as buffer1 on the next call
377 (float *buffer1, size_t len1, float *buffer2, size_t len2)
378{
379 // If buffers are bigger than allocated, then abort
380 // (this should never happen, but if it does, we don't want to crash)
381 if((len1 > mFollowLen) || (len2 > mFollowLen))
382 return false;
383
384 // This makes sure that the initial value is well-chosen
385 // buffer1 == NULL on the first and only the first call
386 if (buffer1 == NULL) {
387 // Initialize the mLastLevel to the peak level in the first buffer
388 // This avoids problems with large spike events near the beginning of the track
390 for(size_t i=0; i<len2; i++) {
391 if(mLastLevel < fabs(buffer2[i]))
392 mLastLevel = fabs(buffer2[i]);
393 }
394 }
395
396 // buffer2 is NULL on the last and only the last call
397 if(buffer2 != NULL) {
398 Follow(buffer2, mFollow2.get(), len2, mFollow1.get(), len1);
399 }
400
401 if(buffer1 != NULL) {
402 for (size_t i = 0; i < len1; i++) {
403 buffer1[i] = DoCompression(buffer1[i], mFollow1[i]);
404 }
405 }
406
407
408#if 0
409 // Copy the envelope over the track data (for debug purposes)
410 memcpy(buffer1, mFollow1, len1*sizeof(float));
411#endif
412
413 // Rotate the buffer pointers
414 mFollow1.swap(mFollow2);
415
416 return true;
417}
418
419bool EffectCompressor::ProcessPass2(float *buffer, size_t len)
420{
421 if (mMax != 0)
422 {
423 for (size_t i = 0; i < len; i++)
424 buffer[i] /= mMax;
425 }
426
427 return true;
428}
429
431{
432 // Recompute the RMS sum periodically to prevent accumulation of rounding errors
433 // during long waveforms
434 mRMSSum = 0;
435 for(size_t i=0; i<mCircleSize; i++)
436 mRMSSum += mCircle[i];
437}
438
440{
441 float level;
442
443 // Calculate current level from root-mean-squared of
444 // circular buffer ("RMS")
446 mCircle[mCirclePos] = value*value;
448 level = sqrt(mRMSSum/mCircleSize);
450
451 return level;
452}
453
454void EffectCompressor::Follow(float *buffer, float *env, size_t len, float *previous, size_t previous_len)
455{
456 /*
457
458 "Follow"ing algorithm by Roger B. Dannenberg, taken from
459 Nyquist. His description follows. -DMM
460
461 Description: this is a sophisticated envelope follower.
462 The input is an envelope, e.g. something produced with
463 the AVG function. The purpose of this function is to
464 generate a smooth envelope that is generally not less
465 than the input signal. In other words, we want to "ride"
466 the peaks of the signal with a smooth function. The
467 algorithm is as follows: keep a current output value
468 (called the "value"). The value is allowed to increase
469 by at most rise_factor and decrease by at most fall_factor.
470 Therefore, the next value should be between
471 value * rise_factor and value * fall_factor. If the input
472 is in this range, then the next value is simply the input.
473 If the input is less than value * fall_factor, then the
474 next value is just value * fall_factor, which will be greater
475 than the input signal. If the input is greater than value *
476 rise_factor, then we compute a rising envelope that meets
477 the input value by working bacwards in time, changing the
478 previous values to input / rise_factor, input / rise_factor^2,
479 input / rise_factor^3, etc. until this NEW envelope intersects
480 the previously computed values. There is only a limited buffer
481 in which we can work backwards, so if the NEW envelope does not
482 intersect the old one, then make yet another pass, this time
483 from the oldest buffered value forward, increasing on each
484 sample by rise_factor to produce a maximal envelope. This will
485 still be less than the input.
486
487 The value has a lower limit of floor to make sure value has a
488 reasonable positive value from which to begin an attack.
489 */
490 double level,last;
491
492 if(!mUsePeak) {
493 // Update RMS sum directly from the circle buffer
494 // to avoid accumulation of rounding errors
496 }
497 // First apply a peak detect with the requested decay rate
498 last = mLastLevel;
499 for(size_t i=0; i<len; i++) {
500 if(mUsePeak)
501 level = fabs(buffer[i]);
502 else // use RMS
503 level = AvgCircle(buffer[i]);
504 // Don't increase gain when signal is continuously below the noise floor
505 if(level < mNoiseFloor) {
507 } else {
508 mNoiseCounter = 0;
509 }
510 if(mNoiseCounter < 100) {
511 last *= mDecayFactor;
512 if(last < mThreshold)
513 last = mThreshold;
514 if(level > last)
515 last = level;
516 }
517 env[i] = last;
518 }
519 mLastLevel = last;
520
521 // Next do the same process in reverse direction to get the requested attack rate
522 last = mLastLevel;
523 for(size_t i = len; i--;) {
524 last *= mAttackInverseFactor;
525 if(last < mThreshold)
526 last = mThreshold;
527 if(env[i] < last)
528 env[i] = last;
529 else
530 last = env[i];
531 }
532
533 if((previous != NULL) && (previous_len > 0)) {
534 // If the previous envelope was passed, propagate the rise back until we intersect
535 for(size_t i = previous_len; i--;) {
536 last *= mAttackInverseFactor;
537 if(last < mThreshold)
538 last = mThreshold;
539 if(previous[i] < last)
540 previous[i] = last;
541 else // Intersected the previous envelope buffer, so we are finished
542 return;
543 }
544 // If we can't back up far enough, project the starting level forward
545 // until we intersect the desired envelope
546 last = previous[0];
547 for(size_t i=1; i<previous_len; i++) {
548 last *= mAttackFactor;
549 if(previous[i] > last)
550 previous[i] = last;
551 else // Intersected the desired envelope, so we are finished
552 return;
553 }
554 // If we still didn't intersect, then continue ramp up into current buffer
555 for(size_t i=0; i<len; i++) {
556 last *= mAttackFactor;
557 if(buffer[i] > last)
558 buffer[i] = last;
559 else // Finally got an intersect
560 return;
561 }
562 // If we still didn't intersect, then reset mLastLevel
563 mLastLevel = last;
564 }
565}
566
567float EffectCompressor::DoCompression(float value, double env)
568{
569 float out;
570 if(mUsePeak) {
571 // Peak values map 1.0 to 1.0 - 'upward' compression
572 out = value * pow(1.0/env, mCompression);
573 } else {
574 // With RMS-based compression don't change values below mThreshold - 'downward' compression
575 out = value * pow(mThreshold/env, mCompression);
576 }
577
578 // Retain the maximum value for use in the normalization pass
579 if(mMax < fabs(out))
580 mMax = fabs(out);
581
582 return out;
583}
584
585void EffectCompressor::OnSlider(wxCommandEvent & WXUNUSED(evt))
586{
588 UpdateUI();
589}
590
592{
593 mThresholdLabel->SetName(wxString::Format(_("Threshold %d dB"), (int) mThresholdDB));
594 mThresholdText->SetLabel(ThresholdFormat((int) mThresholdDB).Translation());
595 mThresholdText->SetName(mThresholdText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
596
597 mNoiseFloorLabel->SetName(wxString::Format(_("Noise Floor %d dB"), (int) mNoiseFloorDB));
598 mNoiseFloorText->SetLabel(ThresholdFormat((int) mNoiseFloorDB).Translation());
599 mNoiseFloorText->SetName(mNoiseFloorText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
600
601 mRatioLabel->SetName(
603 mRatioText->SetLabel(
605 mRatioText->SetName(mRatioText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
606
607 mAttackLabel->SetName(wxString::Format(_("Attack Time %.2f secs"), mAttackTime));
608 mAttackText->SetLabel(AttackTimeFormat(mAttackTime).Translation());
609 mAttackText->SetName(mAttackText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
610
611 mDecayLabel->SetName(wxString::Format(_("Release Time %.1f secs"), mDecayTime));
612 mDecayText->SetLabel(DecayTimeFormat(mDecayTime).Translation());
613 mDecayText->SetName(mDecayText->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
614
615 mPanel->Refresh(false);
616
617 return;
618}
619
620//----------------------------------------------------------------------------
621// EffectCompressorPanel
622//----------------------------------------------------------------------------
623
624BEGIN_EVENT_TABLE(EffectCompressorPanel, wxPanelWrapper)
628
629EffectCompressorPanel::EffectCompressorPanel(wxWindow *parent, wxWindowID winid,
630 double & threshold,
631 double & noiseFloor,
632 double & ratio)
633: wxPanelWrapper(parent, winid),
634 threshold(threshold),
635 noiseFloor(noiseFloor),
636 ratio(ratio)
637{
638}
639
640void EffectCompressorPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
641{
642 wxPaintDC dc(this);
643
644 int width, height;
645 GetSize(&width, &height);
646
647 double rangeDB = 60;
648
649 // Ruler
650 int w = 0;
651 int h = 0;
652
653 Ruler vRuler;
654 vRuler.SetBounds(0, 0, width, height);
655 vRuler.SetOrientation(wxVERTICAL);
656 vRuler.SetRange(0, -rangeDB);
658 vRuler.SetUnits(XO("dB"));
659 vRuler.GetMaxSize(&w, NULL);
660
661 Ruler hRuler;
662 hRuler.SetBounds(0, 0, width, height);
663 hRuler.SetOrientation(wxHORIZONTAL);
664 hRuler.SetRange(-rangeDB, 0);
666 hRuler.SetUnits(XO("dB"));
667 hRuler.SetFlip(true);
668 hRuler.GetMaxSize(NULL, &h);
669
670 vRuler.SetBounds(0, 0, w, height - h);
671 hRuler.SetBounds(w, height - h, width, height);
672
673 vRuler.SetTickColour( theTheme.Colour( clrGraphLabels ));
674 hRuler.SetTickColour( theTheme.Colour( clrGraphLabels ));
675
676#if defined(__WXMSW__)
677 dc.Clear();
678#endif
679
680 wxRect border;
681 border.x = w;
682 border.y = 0;
683 border.width = width - w;
684 border.height = height - h + 1;
685
686 dc.SetBrush(*wxWHITE_BRUSH);
687 dc.SetPen(*wxBLACK_PEN);
688 dc.DrawRectangle(border);
689
690 wxRect envRect = border;
691 envRect.Deflate( 2, 2 );
692
693 int kneeX = lrint((rangeDB+threshold)*envRect.width/rangeDB);
694 int kneeY = lrint((rangeDB+threshold/ratio)*envRect.height/rangeDB);
695
696 int finalY = envRect.height;
697 int startY = lrint((threshold*(1.0/ratio-1.0))*envRect.height/rangeDB);
698
699 // Yellow line for threshold
700/* dc.SetPen(wxPen(wxColour(220, 220, 0), 1, wxSOLID));
701 AColor::Line(dc,
702 envRect.x,
703 envRect.y + envRect.height - kneeY,
704 envRect.x + envRect.width - 1,
705 envRect.y + envRect.height - kneeY);*/
706
707 // Was: Nice dark red line for the compression diagram
708// dc.SetPen(wxPen(wxColour(180, 40, 40), 3, wxSOLID));
709
710 // Nice blue line for compressor, same color as used in the waveform envelope.
711 dc.SetPen( AColor::WideEnvelopePen) ;
712
713 AColor::Line(dc,
714 envRect.x,
715 envRect.y + envRect.height - startY,
716 envRect.x + kneeX - 1,
717 envRect.y + envRect.height - kneeY);
718
719 AColor::Line(dc,
720 envRect.x + kneeX,
721 envRect.y + envRect.height - kneeY,
722 envRect.x + envRect.width - 1,
723 envRect.y + envRect.height - finalY);
724
725 // Paint border again
726 dc.SetBrush(*wxTRANSPARENT_BRUSH);
727 dc.SetPen(*wxBLACK_PEN);
728 dc.DrawRectangle(border);
729
730 vRuler.Draw(dc);
731 hRuler.Draw(dc);
732}
733
734void EffectCompressorPanel::OnSize(wxSizeEvent & WXUNUSED(evt))
735{
736 Refresh(false);
737}
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:543
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
static wxPen WideEnvelopePen
Definition: AColor.h:116
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:104
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:377
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:344
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
Definition: Compressor.cpp:294
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:439
EffectType GetType() const override
Type determines how it behaves.
Definition: Compressor.cpp:118
bool DoTransferDataFromWindow()
Definition: Compressor.cpp:303
static const ComponentInterfaceSymbol Symbol
Definition: Compressor.h:34
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
Definition: Compressor.cpp:279
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
Definition: Compressor.cpp:159
Doubles mCircle
Definition: Compressor.h:83
void Follow(float *buffer, float *env, size_t len, float *previous, size_t previous_len)
Definition: Compressor.cpp:454
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:567
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
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:585
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:419
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:366
wxStaticText * mNoiseFloorLabel
Definition: Compressor.h:113
wxStaticText * mThresholdLabel
Definition: Compressor.h:109
bool NewTrackPass1() override
Definition: Compressor.cpp:319
static constexpr EffectParameter Normalize
Definition: Compressor.h:145
void OnSize(wxSizeEvent &evt)
Definition: Compressor.cpp:734
void OnPaint(wxPaintEvent &evt)
Definition: Compressor.cpp:640
wxWindow * mUIParent
Definition: Effect.h:307
Performs effect computation.
Hold values to send to effect output meters.
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:1454
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:1816
#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.