26#include <wx/checkbox.h>
35#include "../widgets/valnum.h"
64static inline double enumToDB(
int val ) {
return -( 5.0 * val + 20.0 ); }
75 {
XO(
"Truncate Detected Silence") },
76 {
XO(
"Compress Excess Silence") }
105{
XO(
"Truncate Silence") };
116 Parameters().Reset(*
this);
118 SetLinearEffectFlag(
false);
144 return XO(
"Automatically reduces the length of passages where the volume is below a specified level");
149 return L
"Truncate_Silence";
167 double myThreshold {};
168 bool newParams = [&] {
205 double inputLength =
mT1 -
mT0;
206 double minInputLength = inputLength;
216 for (
auto wt :
inputTracks()->Selected< const WaveTrack >()) {
219 auto index = wt->TimeToLongSamples(
mT0);
222 Analyze(silences, trackSilences, wt, &silentFrame, &index, whichTrack, &inputLength, &minInputLength);
245 unsigned nGroups = 0;
251 for (
auto track :
inputTracks()->SelectedLeaders< const WaveTrack >() ) {
257 - [&](
const Track *pTrack){
258 return channels.contains(pTrack); };
262"When truncating independently, there may only be one selected audio track in each Sync-Locked Track Group.") );
291 Track *groupFirst, *groupLast;
294 groupFirst = *trackRange.begin();
295 groupLast = *trackRange.rbegin();
301 double totalCutLen = 0.0;
302 if (!
DoRemoval(silences, iGroup, nGroups, groupFirst, groupLast, totalCutLen))
304 newT1 = std::max(newT1,
mT1 - totalCutLen);
328 double totalCutLen = 0.0;
330 *trackRange.begin(), *trackRange.rbegin(), totalCutLen)) {
341 const Track *firstTrack,
const Track *lastTrack)
350 .StartingWith( firstTrack ).EndingAfter( lastTrack ) )
353 auto minSilenceFrames =
361 auto index = wt->TimeToLongSamples(
mT0);
365 bool cancelled = !(
Analyze(silences, trackSilences, wt, &silentFrame, &index, whichTrack));
374 if (silentFrame >= minSilenceFrames)
377 trackSilences.push_back(
Region(
378 wt->LongSamplesToTime(index - silentFrame),
379 wt->LongSamplesToTime(index)
392(
const RegionList &silences,
unsigned iGroup,
unsigned nGroups,
Track *firstTrack,
Track *lastTrack,
402 RegionList::const_reverse_iterator rit;
403 for (rit = silences.rbegin(); rit != silences.rend(); ++rit)
405 const Region ®ion = *rit;
406 const Region *
const r = ®ion;
410 (1 -
detectFrac) * (iGroup + whichReg /
double(silences.size())) / nGroups;
423 double inLength = r->
end - r->
start;
441 const double cutLen = std::max(0.0, inLength - outLength);
446 totalCutLen += cutLen;
448 double cutStart = (r->
start + r->
end - cutLen) / 2;
449 double cutEnd = cutStart + cutLen;
451 .StartingWith(firstTrack).EndingAfter(lastTrack)
453 - [&](
const Track *pTrack) {
return
455 pTrack->GetEndTime() < r->
start;
474 Floats buf1{ blendFrames };
475 Floats buf2{ blendFrames };
479 wt->
GetFloats(buf1.get(), t1, blendFrames);
480 wt->
GetFloats(buf2.get(), t2, blendFrames);
482 for (
decltype(blendFrames) i = 0; i < blendFrames; ++i)
484 buf1[i] = ((blendFrames-i) * buf1[i] + i * buf2[i]) /
489 wt->
Clear(cutStart, cutEnd);
501 t->SyncLockAdjust(cutEnd, cutStart);
516 double* inputLength ,
517 double* minInputLength )
const
528 double previewLength;
529 gPrefs->Read(
wxT(
"/AudioIO/EffectsPreviewLen"), &previewLength, 6.0);
534 RegionList::iterator rit(silenceList.begin());
537 Floats buffer{ blockLen };
540 while (*index <
end) {
541 if (inputLength && ((outLength >= previewLen) || (*index - start > wt->
TimeToLongSamples(*minInputLength)))) {
542 *inputLength = std::min<double>(*inputLength, *minInputLength);
543 if (outLength >= previewLen) {
544 *minInputLength = *inputLength;
553 (*index - start).as_double() /
554 (
end - start).as_double()) /
563 for ( ; rit != silenceList.end(); ++rit) {
565 if (rit->end >= curTime) {
570 if (rit == silenceList.end()) {
575 auto requiredTrackSamples = previewLen - outLength;
576 outLength += (remainingTrackSamples > requiredTrackSamples)? requiredTrackSamples : remainingTrackSamples;
581 else if (rit->start > curTime) {
583 if (*silentFrame >= minSilenceFrames) {
584 trackSilences.push_back(
Region(
592 auto requiredTrackSamples = previewLen - outLength;
594 outLength += ((newIndex - *index) > requiredTrackSamples)? requiredTrackSamples : newIndex - *index;
605 wt->
GetFloats((buffer.get()), *index, count);
608 for (
decltype(count) i = 0; i < count; ++i) {
609 if (inputLength && ((outLength >= previewLen) || (outLength > wt->
TimeToLongSamples(*minInputLength)))) {
614 if (fabs(buffer[i]) < truncDbSilenceThreshold) {
619 if (*silentFrame >= minSilenceFrames) {
629 (*silentFrame - allowed).as_double()
638 trackSilences.push_back(
Region(
643 else if (inputLength) {
644 outLength += *silentFrame;
657 *inputLength = std::min<double>(*inputLength, *minInputLength);
658 if (outLength >= previewLen) {
659 *minInputLength = *inputLength;
676 S.StartStatic(
XO(
"Detect Silence"));
678 S.StartMultiColumn(3, wxALIGN_CENTER_HORIZONTAL);
682 .Validator<FloatingPointValidator<double>>(
683 3, &
mThresholdDB, NumValidatorStyle::NO_TRAILING_ZEROES,
685 .NameSuffix(
XO(
"db"))
686 .AddTextBox(
XXO(
"&Threshold:"),
wxT(
""), 0);
687 S.AddUnits(
XO(
"dB"));
692 NumValidatorStyle::NO_TRAILING_ZEROES,
694 .NameSuffix(
XO(
"seconds"))
695 .AddTextBox(
XXO(
"&Duration:"),
wxT(
""), 12);
696 S.AddUnits(
XO(
"seconds"));
702 S.StartStatic(
XO(
"Action"));
704 S.StartHorizontalLay();
710 .MinSize( { -1, -1 } )
711 .AddChoice( {}, actionChoices );
713 S.EndHorizontalLay();
714 S.StartMultiColumn(3, wxALIGN_CENTER_HORIZONTAL);
720 NumValidatorStyle::NO_TRAILING_ZEROES,
722 .NameSuffix(
XO(
"seconds"))
723 .AddTextBox(
XXO(
"Tr&uncate to:"),
wxT(
""), 12);
724 S.AddUnits(
XO(
"seconds"));
728 NumValidatorStyle::NO_TRAILING_ZEROES,
731 .AddTextBox(
XXO(
"C&ompress to:"),
wxT(
""), 12);
736 S.StartMultiColumn(2, wxALIGN_CENTER_HORIZONTAL);
776 RegionList::iterator destIter;
777 destIter = dest.begin();
779 if (destIter == dest.end())
781 RegionList::iterator curDest = destIter;
784 double nsStart = curDest->start;
786 bool lastRun =
false;
788 RegionList::const_iterator srcIter = src.begin();
792 if (srcIter == src.end())
797 while (srcIter != src.end() || lastRun)
800 RegionList::const_iterator curSrc;
805 nsEnd = std::numeric_limits<double>::max();
810 nsEnd = curSrc->start;
816 while (curDest->end <= nsStart)
819 if (destIter == dest.end())
827 if (nsStart > curDest->start && nsEnd < curDest->
end)
830 Region r(nsEnd, curDest->end);
833 curDest->end = nsStart;
836 RegionList::iterator nextIt(destIter);
843 if (nextIt == dest.end())
846 dest.insert(nextIt, r);
853 if (nsStart > curDest->start && nsStart < curDest->
end &&
854 nsEnd >= curDest->end)
856 curDest->end = nsStart;
859 if (destIter == dest.end())
867 while (nsStart <= curDest->start && nsEnd >= curDest->end)
869 destIter = dest.erase(destIter);
870 if (destIter == dest.end())
878 if (nsStart <= curDest->start &&
879 nsEnd > curDest->start && nsEnd < curDest->
end)
881 curDest->start = nsEnd;
893 nsStart = curSrc->end;
895 if (srcIter == src.end())
XXO("&Cut/Copy/Paste Toolbar")
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
static Settings & settings()
static CommandParameters::ObsoleteMap kObsoleteActions[]
static const size_t DEF_BlendFrameCount
static const size_t nObsoleteActions
static const double DEF_MinTruncMs
static double enumToDB(int val)
Generates EffectParameterMethods overrides from variadic template arguments.
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
bool ReadAndVerify(const wxString &key, float *val, float defVal, float min, float max) const
std::pair< wxString, size_t > ObsoleteMap
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
std::shared_ptr< TrackList > mOutputTracks
const TrackList * inputTracks() const
void ReplaceProcessedTracks(const bool bGoodResult)
const AudacityProject * FindProject() const
static bool EnableApply(wxWindow *parent, bool enable=true)
Enable or disable the Apply button of the dialog that contains parent.
void CopyInputTracks(bool allSyncLockSelected=false)
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
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.
Truncate Silence automatically reduces the length of passages where the volume is below a set thresho...
bool TransferDataToWindow(const EffectSettings &settings) override
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
bool Process(EffectInstance &instance, EffectSettings &settings) override
bool FindSilences(RegionList &silences, const TrackList *list, const Track *firstTrack, const Track *lastTrack)
static constexpr EnumParameter ActIndex
static constexpr EffectParameter Independent
wxWeakRef< wxWindow > mUIParent
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
wxTextCtrl * mThresholdText
double mInitialAllowedSilence
bool NeedsDither() const override
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
bool Analyze(RegionList &silenceList, RegionList &trackSilences, const WaveTrack *wt, sampleCount *silentFrame, sampleCount *index, int whichTrack, double *inputLength=NULL, double *minInputLength=NULL) const
void OnControlChange(wxCommandEvent &evt)
static constexpr EffectParameter Minimum
virtual ~EffectTruncSilence()
wxCheckBox * mIndependent
bool TransferDataFromWindow(EffectSettings &settings) override
double mSilenceCompressPercent
static constexpr EffectParameter Truncate
EffectType GetType() const override
Type determines how it behaves.
static const EnumValueSymbol kActionStrings[nActions]
double mTruncLongestAllowedSilence
static constexpr EffectParameter Threshold
bool ProcessIndependently()
wxTextCtrl * mTruncLongestAllowedSilenceT
static const ComponentInterfaceSymbol Symbol
const EffectParameterMethods & Parameters() const override
TranslatableString GetDescription() const override
ComponentInterfaceSymbol GetSymbol() const override
bool DoRemoval(const RegionList &silences, unsigned iGroup, unsigned nGroups, Track *firstTrack, Track *lastTrack, double &totalCutLen)
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
wxTextCtrl * mInitialAllowedSilenceT
wxTextCtrl * mSilenceCompressPercentT
static constexpr EffectParameter Compress
void Intersect(RegionList &dest, const RegionList &src)
static int DoMessageBox(const EffectPlugin &plugin, const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
static const size_t NumDbChoices
static const EnumValueSymbol DbChoices[]
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.
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
static TrackIterRange< Track > Group(Track *pTrack)
bool IsSyncLocked() const
static SyncLockState & Get(AudacityProject &project)
Abstract base class for an object holding data associated with points on a time axis.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
auto Selected() -> TrackIterRange< TrackType >
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
void Clear(double t0, double t1) override
double GetEndTime() const override
Get the time at which the last clip in the track ends, plus recorded stuff.
double GetRate() const override
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< EffectTruncSilence > reg
const wxChar *const key
Identifier in configuration file.
const Type def
Default value.
const Type min
Minimum value.
const Type max
Maximum value.
Externalized state of a plug-in.
Structure to hold region of a wavetrack and a comparison function for sortability.