24#include <wx/dcclient.h>
25#include <wx/dcmemory.h>
32#include "../widgets/valnum.h"
84 Parameters().Reset(*
this);
86 SetLinearEffectFlag(
true);
106 return XO(
"Reduces (ducks) the volume of one or more tracks whenever the volume of a specified \"control\" track reaches a particular level");
127 bool lastWasSelectedWaveTrack =
false;
128 const WaveTrack *controlTrackCandidate = NULL;
132 if (lastWasSelectedWaveTrack && !t->GetSelected()) {
134 controlTrackCandidate = track_cast<const WaveTrack *>(t);
137 lastWasSelectedWaveTrack =
false;
139 if (t->GetSelected()) {
140 bool ok = t->TypeSwitch<
bool>(
142 lastWasSelectedWaveTrack =
true;
150 XO(
"You selected a track which does not contain audio. AutoDuck can only process audio tracks."),
160 if (!controlTrackCandidate)
166 XO(
"Auto Duck needs a control track which must be placed below the selected track(s)."),
199 auto minSamplesPause =
211 std::vector<AutoDuckRegion> regions;
212 bool inDuckRegion =
false;
219 double duckRegionStart = 0;
230 for (
auto i = pos; i < pos + len; i++)
232 rmsSum -= rmsWindow[rmsPos];
234 auto index = ( i - pos ).as_size_t();
235 rmsWindow[rmsPos] = buf[ index ] * buf[ index ];
236 rmsSum += rmsWindow[rmsPos];
239 bool thresholdExceeded = rmsSum > threshold;
241 if (thresholdExceeded)
256 if (!thresholdExceeded && inDuckRegion)
261 curSamplesPause += 1;
263 if (curSamplesPause >= minSamplesPause)
266 double duckRegionEnd =
273 inDuckRegion =
false;
281 (pos - start).as_double() /
282 (
end - start).as_double() /
294 double duckRegionEnd =
310 for (
size_t i = 0; i < regions.size(); i++)
337 S.StartVerticalLay(
true);
346 S.StartMultiColumn(6, wxCENTER);
351 .NameSuffix(
XO(
"db"))
352 .AddTextBox(
XXO(
"Duck &amount:"),
wxT(
""), 10);
353 S.AddUnits(
XO(
"dB"));
358 .NameSuffix(
XO(
"seconds"))
359 .AddTextBox(
XXO(
"Ma&ximum pause:"),
wxT(
""), 10);
360 S.AddUnits(
XO(
"seconds"));
365 .NameSuffix(
XO(
"seconds"))
366 .AddTextBox(
XXO(
"Outer fade &down length:"),
wxT(
""), 10);
367 S.AddUnits(
XO(
"seconds"));
372 .NameSuffix(
XO(
"seconds"))
373 .AddTextBox(
XXO(
"Outer fade &up length:"),
wxT(
""), 10);
374 S.AddUnits(
XO(
"seconds"));
379 .NameSuffix(
XO(
"seconds"))
380 .AddTextBox(
XXO(
"Inner fade d&own length:"),
wxT(
""), 10);
381 S.AddUnits(
XO(
"seconds"));
386 .NameSuffix(
XO(
"seconds"))
387 .AddTextBox(
XXO(
"Inner &fade up length:"),
wxT(
""), 10);
388 S.AddUnits(
XO(
"seconds"));
392 S.StartMultiColumn(3, wxCENTER);
395 2, &
mThresholdDb, NumValidatorStyle::NO_TRAILING_ZEROES,
397 .NameSuffix(
XO(
"db"))
398 .AddTextBox(
XXO(
"&Threshold:"),
wxT(
""), 10);
399 S.AddUnits(
XO(
"dB"));
439 double t0,
double t1)
451 if (fadeDownSamples < 1)
456 if (fadeUpSamples < 1)
459 float fadeDownStep =
mDuckAmountDb / fadeDownSamples.as_double();
460 float fadeUpStep =
mDuckAmountDb / fadeUpSamples.as_double();
468 for (
auto i = pos; i < pos + len; i++)
470 float gainDown = fadeDownStep * (i - start).as_float();
471 float gainUp = fadeUpStep * (
end - i).as_float();
474 if (gainDown > gainUp)
490 float fractionFinished = (curTime -
mT0) / (
mT1 -
mT0);
511#define CONTROL_POINT_REGION 10
512#define CONTROL_POINT_MIN_MOVE 5
514#define TEXT_DISTANCE 15
516#define FADE_DOWN_START 150
517#define FADE_UP_START 450
518#define DUCK_AMOUNT_START 50
521#define DUCK_AMOUNT_SCALE 8
523static int GetDistance(
const wxPoint& first,
const wxPoint& second)
525 int distanceX = abs(first.x - second.x);
526 int distanceY = abs(first.y - second.y);
527 if (distanceX > distanceY)
544:
wxPanelWrapper(parent, winid, wxDefaultPosition, wxSize(600, 300))
548 mCurrentControlPoint =
none;
549 mBackgroundBitmap = NULL;
551 ResetControlPoints();
562 mControlPoints[innerFadeDown] = wxPoint(-100,-100);
563 mControlPoints[innerFadeUp] = wxPoint(-100,-100);
564 mControlPoints[outerFadeDown] = wxPoint(-100,-100);
565 mControlPoints[outerFadeUp] = wxPoint(-100,-100);
566 mControlPoints[duckAmount] = wxPoint(-100,-100);
571 int clientWidth, clientHeight;
572 GetSize(&clientWidth, &clientHeight);
574 if (!mBackgroundBitmap || mBackgroundBitmap->GetWidth() != clientWidth ||
575 mBackgroundBitmap->GetHeight() != clientHeight)
577 mBackgroundBitmap = std::make_unique<wxBitmap>(clientWidth, clientHeight,24);
581 dc.SelectObject(*mBackgroundBitmap);
583 dc.SetBrush(*wxWHITE_BRUSH);
584 dc.SetPen(*wxBLACK_PEN);
585 dc.DrawRectangle(0, 0, clientWidth, clientHeight);
587 dc.SetFont(wxFont(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL,
588 wxFONTWEIGHT_NORMAL));
589 dc.SetTextForeground(*wxBLACK);
590 dc.SetTextBackground(*wxWHITE);
592 double duckAmountDb = 0;
593 double innerFadeDownLen = 0;
594 double innerFadeUpLen = 0;
595 double outerFadeDownLen = 0;
596 double outerFadeUpLen = 0;
597 mEffect->mDuckAmountDbBox->GetValue().ToDouble(&duckAmountDb);
598 mEffect->mInnerFadeDownLenBox->GetValue().ToDouble(&innerFadeDownLen);
599 mEffect->mInnerFadeUpLenBox->GetValue().ToDouble(&innerFadeUpLen);
600 mEffect->mOuterFadeDownLenBox->GetValue().ToDouble(&outerFadeDownLen);
601 mEffect->mOuterFadeUpLenBox->GetValue().ToDouble(&outerFadeUpLen);
610 wxString message =
_(
"Preview not available");
611 int textWidth = 0, textHeight = 0;
612 dc.GetTextExtent(message, &textWidth, &textHeight);
613 dc.DrawText(message, (clientWidth - textWidth) / 2,
614 (clientHeight - textHeight) / 2);
616 ResetControlPoints();
620 dc.SetBrush(*wxTRANSPARENT_BRUSH);
621 dc.SetPen(wxPen(
theTheme.
Colour(clrGraphLines), 3, wxPENSTYLE_SOLID));
642 points[5].x = clientWidth - 10;
647 dc.SetPen(wxPen(*wxBLACK, 1, wxPENSTYLE_DOT));
653 dc.SetBrush(*wxWHITE_BRUSH);
655 mControlPoints[outerFadeDown] = points[1];
656 mControlPoints[innerFadeDown] = points[2];
657 mControlPoints[innerFadeUp] = points[3];
658 mControlPoints[outerFadeUp] = points[4];
659 mControlPoints[duckAmount] = wxPoint(
660 (points[2].x + points[3].x) / 2, points[2].y);
668 if (cp == innerFadeDown)
670 value = innerFadeDownLen;
673 else if (cp == innerFadeUp)
675 value = innerFadeUpLen;
678 else if (cp == outerFadeDown)
680 value = outerFadeDownLen;
682 }
else if (cp == outerFadeUp)
684 value = outerFadeUpLen;
689 value = duckAmountDb;
694 valueStr +=
wxT(
" ");
696 if (cp == duckAmount)
703 int textWidth = 0, textHeight = 0;
704 GetTextExtent(valueStr, &textWidth, &textHeight);
706 int textPosX = mControlPoints[i].x - textWidth / 2;
707 int textPosY = mControlPoints[i].y;
709 if (cp == duckAmount || cp == outerFadeDown || cp == outerFadeUp)
714 dc.DrawText(valueStr, textPosX, textPosY);
716 dc.DrawEllipse(mControlPoints[i].x - 3,
717 mControlPoints[i].y - 3, 6, 6);
722 wxPaintDC paintDC(
this);
723 paintDC.Blit(0, 0, clientWidth, clientHeight, &dc, 0, 0);
726 dc.SetPen(wxNullPen);
727 dc.SetBrush(wxNullBrush);
728 dc.SetFont(wxNullFont);
729 dc.SelectObject(wxNullBitmap);
733 wxMouseCaptureChangedEvent & WXUNUSED(evt))
735 SetCursor(wxNullCursor);
736 mCurrentControlPoint =
none;
740 wxMouseCaptureLostEvent & WXUNUSED(evt))
742 mCurrentControlPoint =
none;
761 if (dist[i] < dist[curMinimum])
772 EControlPoint nearest = GetNearestControlPoint(evt.GetPosition());
777 mMouseDownPoint = evt.GetPosition();
779 mCurrentControlPoint = nearest;
780 mControlPointMoveActivated =
false;
783 mMoveStartControlPoints[i] = mControlPoints[i];
792 if (mCurrentControlPoint !=
none)
794 mCurrentControlPoint =
none;
801 switch (GetNearestControlPoint(evt.GetPosition()))
804 SetCursor(wxNullCursor);
810 SetCursor(wxCursor(wxCURSOR_SIZEWE));
813 SetCursor(wxCursor(wxCURSOR_SIZENS));
817 if (mCurrentControlPoint !=
none)
819 if (!mControlPointMoveActivated)
823 if (mCurrentControlPoint == duckAmount)
824 dist = abs(evt.GetY() - mMouseDownPoint.y);
826 dist = abs(evt.GetX() - mMouseDownPoint.x);
829 mControlPointMoveActivated =
true;
832 if (mControlPointMoveActivated)
836 switch (mCurrentControlPoint)
861 mEffect->DoTransferDataToWindow();
static const size_t kBufSize
#define CONTROL_POINT_REGION
static const size_t kRMSWindowSize
static int GetDistance(const wxPoint &first, const wxPoint &second)
#define DUCK_AMOUNT_SCALE
#define DUCK_AMOUNT_START
#define CONTROL_POINT_MIN_MOVE
#define AUTO_DUCK_PANEL_NUM_CONTROL_POINTS
XXO("&Cut/Copy/Paste Toolbar")
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
static void Lines(wxDC &dc, size_t nPoints, const wxPoint points[])
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
EControlPoint GetNearestControlPoint(const wxPoint &pt)
void OnMotion(wxMouseEvent &evt)
void OnLeftDown(wxMouseEvent &evt)
void OnMouseCaptureChanged(wxMouseCaptureChangedEvent &evt)
void OnLeftUp(wxMouseEvent &evt)
void ResetControlPoints()
void OnPaint(wxPaintEvent &evt)
void OnMouseCaptureLost(wxMouseCaptureLostEvent &evt)
Implements the Auto Ducking effect.
static constexpr EffectParameter InnerFadeDownLen
wxTextCtrl * mInnerFadeUpLenBox
ComponentInterfaceSymbol GetSymbol() const override
static constexpr EffectParameter InnerFadeUpLen
wxTextCtrl * mInnerFadeDownLenBox
static constexpr EffectParameter OuterFadeDownLen
wxTextCtrl * mOuterFadeDownLenBox
const WaveTrack * mControlTrack
bool ApplyDuckFade(int trackNum, WaveTrack *t, double t0, double t1)
static constexpr EffectParameter MaximumPause
bool DoTransferDataToWindow()
wxTextCtrl * mThresholdDbBox
static constexpr EffectParameter ThresholdDb
wxWeakRef< wxWindow > mUIParent
const EffectParameterMethods & Parameters() const override
bool TransferDataToWindow(const EffectSettings &settings) override
virtual ~EffectAutoDuck()
void OnValueChanged(wxCommandEvent &evt)
static constexpr EffectParameter DuckAmountDb
EffectType GetType() const override
Type determines how it behaves.
bool TransferDataFromWindow(EffectSettings &settings) override
static constexpr EffectParameter OuterFadeUpLen
bool Process(EffectInstance &instance, EffectSettings &settings) override
wxTextCtrl * mMaximumPauseBox
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
static const ComponentInterfaceSymbol Symbol
TranslatableString GetDescription() const override
wxTextCtrl * mOuterFadeUpLenBox
wxTextCtrl * mDuckAmountDbBox
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
std::shared_ptr< TrackList > mOutputTracks
const TrackList * inputTracks() const
void ReplaceProcessedTracks(const bool bGoodResult)
void CopyInputTracks(bool allSyncLockSelected=false)
bool TotalProgress(double frac, const TranslatableString &={}) const
int GetNumWaveTracks() const
Performs effect computation.
Hold values to send to effect output meters.
Interface for manipulations of an Effect's settings.
static int DoMessageBox(const EffectPlugin &plugin, const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
static wxString ToDisplayString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, uses the user's locale's decimal separator.
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Retrieve samples from a track in floating-point format, regardless of the storage format.
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
wxColour & Colour(int iIndex)
Abstract base class for an object holding data associated with points on a time axis.
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
void Set(constSamplePtr buffer, sampleFormat format, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
Positions or offsets within audio files need a wide type.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
BuiltinEffectsModule::Registration< EffectAutoDuck > reg
a struct that holds a start and end time.
AutoDuckRegion(double t0, double t1)
const Type min
Minimum value.
const Type max
Maximum value.
Externalized state of a plug-in.