28#include <wx/checkbox.h>
37#include "../widgets/valnum.h"
66static inline double enumToDB(
int val ) {
return -( 5.0 * val + 20.0 ); }
77 {
XO(
"Truncate Detected Silence") },
78 {
XO(
"Compress Excess Silence") }
107{
XO(
"Truncate Silence") };
118 Parameters().Reset(*
this);
120 SetLinearEffectFlag(
false);
146 return XO(
"Automatically reduces the length of passages where the volume is below a specified level");
151 return L
"Truncate_Silence";
169 double myThreshold {};
170 bool newParams = [&] {
207 double inputLength =
mT1 -
mT0;
208 double minInputLength = inputLength;
218 for (
auto wt :
inputTracks()->Selected<const WaveTrack>()) {
221 auto index = wt->TimeToLongSamples(
mT0);
224 Analyze(silences, trackSilences, *wt, &silentFrame, &index, whichTrack,
225 &inputLength, &minInputLength);
227 whichTrack += wt->NChannels();
245 unsigned nGroups = 0;
251 for (
auto track :
inputTracks()->Selected<const WaveTrack>()) {
256 - [&](
const Track *pTrack){
return pTrack == track; };
260"When truncating independently, there may only be one selected audio track in each Sync-Locked Track Group.") );
283 for (
auto track : outputs.Get().Selected<
WaveTrack>()) {
289 Track *groupFirst, *groupLast;
290 auto range = syncLock
292 : TrackList::SingletonRange<Track>(track);
293 double totalCutLen = 0.0;
294 if (!
DoRemoval(silences, range, iGroup, nGroups, totalCutLen))
296 newT1 = std::max(newT1,
mT1 - totalCutLen);
322 auto trackRange = outputs.Get().Any();
323 double totalCutLen = 0.0;
324 if (
DoRemoval(silences, trackRange, 0, 1, totalCutLen)) {
342 for (
auto wt : range) {
344 auto minSilenceFrames =
353 auto index = wt->TimeToLongSamples(
mT0);
358 silences, trackSilences, *wt, &silentFrame, &index, whichTrack));
364 if (silentFrame >= minSilenceFrames)
367 trackSilences.push_back(
Region(
368 wt->LongSamplesToTime(index - silentFrame),
369 wt->LongSamplesToTime(index)
383 unsigned iGroup,
unsigned nGroups,
393 RegionList::const_reverse_iterator rit;
394 for (rit = silences.rbegin(); rit != silences.rend(); ++rit)
396 const Region ®ion = *rit;
397 const Region *
const r = ®ion;
401 (1 -
detectFrac) * (iGroup + whichReg /
double(silences.size())) / nGroups;
411 double inLength = r->
end - r->
start;
429 const double cutLen = std::max(0.0, inLength - outLength);
434 totalCutLen += cutLen;
437 double cutStart = (r->
start + r->
end - cutLen) / 2;
438 double cutEnd = cutStart + cutLen;
441 - [&](
const Track *pTrack) {
return
443 pTrack->GetEndTime() < r->
start;
445 ).VisitWhile(success,
466 Buffers buffers[2]{ blendFrames, blendFrames };
471 for (
const auto pChannel : wt.
Channels()) {
473 pChannel->GetFloats(buffer.buf1.get(), t1, blendFrames);
474 pChannel->GetFloats(buffer.buf2.get(), t2, blendFrames);
476 for (
decltype(blendFrames) i = 0; i < blendFrames; ++i) {
478 ((blendFrames - i) * buffer.buf1[i] + i * buffer.buf2[i]) /
484 wt.
Clear(cutStart, cutEnd);
487 for (
const auto pChannel : wt.
Channels()) {
491 pChannel->SetFloats(buffer.buf1.get(), t1,
503 t.SyncLockAdjust(cutEnd, cutStart);
516 sampleCount* index,
int whichTrack,
double* inputLength,
517 double* minInputLength)
const
519 const auto rate = wt.
GetRate();
522 auto minSilenceFrames =
531 double previewLength;
532 gPrefs->
Read(
wxT(
"/AudioIO/EffectsPreviewLen"), &previewLength, 6.0);
534 const sampleCount previewLen(previewLength * rate);
537 RegionList::iterator rit(silenceList.begin());
546 while (*index <
end) {
547 if (inputLength && ((outLength >= previewLen) ||
550 *inputLength = std::min<double>(*inputLength, *minInputLength);
551 if (outLength >= previewLen) {
552 *minInputLength = *inputLength;
561 (*index - start).as_double() /
562 (
end - start).as_double()) /
571 for ( ; rit != silenceList.end(); ++rit) {
573 if (rit->end >= curTime) {
578 if (rit == silenceList.end()) {
582 auto remainingTrackSamples =
584 auto requiredTrackSamples = previewLen - outLength;
585 outLength += (remainingTrackSamples > requiredTrackSamples)
586 ? requiredTrackSamples
587 : remainingTrackSamples;
592 else if (rit->start > curTime) {
594 if (*silentFrame >= minSilenceFrames) {
595 trackSilences.push_back(
Region(
603 auto requiredTrackSamples = previewLen - outLength;
605 outLength += ((newIndex - *index) > requiredTrackSamples)
606 ? requiredTrackSamples
619 for (
const auto pChannel : wt.
Channels())
620 pChannel->GetFloats(buffers[
iChannel++].get(), *index, count);
623 for (
decltype(count) i = 0; i < count; ++i) {
624 if (inputLength && ((outLength >= previewLen) ||
632 const bool silent = std::all_of(buffers, buffers +
iChannel,
633 [&](
const Floats &buffer){
634 return fabs(buffer[i]) < truncDbSilenceThreshold;
640 if (*silentFrame >= minSilenceFrames) {
652 (*silentFrame - allowed).as_double()
661 trackSilences.push_back(
Region(
666 else if (inputLength) {
667 outLength += *silentFrame;
680 *inputLength = std::min<double>(*inputLength, *minInputLength);
681 if (outLength >= previewLen) {
682 *minInputLength = *inputLength;
699 S.StartStatic(
XO(
"Detect Silence"));
701 S.StartMultiColumn(3, wxALIGN_CENTER_HORIZONTAL);
705 .Validator<FloatingPointValidator<double>>(
706 3, &
mThresholdDB, NumValidatorStyle::NO_TRAILING_ZEROES,
708 .NameSuffix(
XO(
"db"))
709 .AddTextBox(
XXO(
"&Threshold:"),
wxT(
""), 0);
710 S.AddUnits(
XO(
"dB"));
715 NumValidatorStyle::NO_TRAILING_ZEROES,
717 .NameSuffix(
XO(
"seconds"))
718 .AddTextBox(
XXO(
"&Duration:"),
wxT(
""), 12);
719 S.AddUnits(
XO(
"seconds"));
725 S.StartStatic(
XO(
"Action"));
727 S.StartHorizontalLay();
733 .MinSize( { -1, -1 } )
734 .AddChoice( {}, actionChoices );
736 S.EndHorizontalLay();
737 S.StartMultiColumn(3, wxALIGN_CENTER_HORIZONTAL);
743 NumValidatorStyle::NO_TRAILING_ZEROES,
745 .NameSuffix(
XO(
"seconds"))
746 .AddTextBox(
XXO(
"Tr&uncate to:"),
wxT(
""), 12);
747 S.AddUnits(
XO(
"seconds"));
751 NumValidatorStyle::NO_TRAILING_ZEROES,
754 .AddTextBox(
XXO(
"C&ompress to:"),
wxT(
""), 12);
759 S.StartMultiColumn(2, wxALIGN_CENTER_HORIZONTAL);
799 RegionList::iterator destIter;
800 destIter = dest.begin();
802 if (destIter == dest.end())
804 RegionList::iterator curDest = destIter;
807 double nsStart = curDest->start;
809 bool lastRun =
false;
811 RegionList::const_iterator srcIter = src.begin();
815 if (srcIter == src.end())
820 while (srcIter != src.end() || lastRun)
823 RegionList::const_iterator curSrc;
828 nsEnd = std::numeric_limits<double>::max();
833 nsEnd = curSrc->start;
839 while (curDest->end <= nsStart)
842 if (destIter == dest.end())
850 if (nsStart > curDest->start && nsEnd < curDest->
end)
853 Region r(nsEnd, curDest->end);
856 curDest->end = nsStart;
859 RegionList::iterator nextIt(destIter);
866 if (nextIt == dest.end())
869 dest.insert(nextIt, r);
876 if (nsStart > curDest->start && nsStart < curDest->
end &&
877 nsEnd >= curDest->end)
879 curDest->end = nsStart;
882 if (destIter == dest.end())
890 while (nsStart <= curDest->start && nsEnd >= curDest->end)
892 destIter = dest.erase(destIter);
893 if (destIter == dest.end())
901 if (nsStart <= curDest->start &&
902 nsEnd > curDest->start && nsEnd < curDest->
end)
904 curDest->start = nsEnd;
916 nsStart = curSrc->end;
918 if (srcIter == src.end())
Toolkit-neutral facade for basic user interface services.
XXO("&Cut/Copy/Paste Toolbar")
audacity::BasicSettings * gPrefs
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,...
const TrackList * inputTracks() const
std::shared_ptr< TrackList > mTracks
const AudacityProject * FindProject() const
static bool EnableApply(wxWindow *parent, bool enable=true)
Enable or disable the Apply button of the dialog that contains parent.
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.
Use this object to copy the input tracks to tentative outputTracks.
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
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
void OnControlChange(wxCommandEvent &evt)
static constexpr EffectParameter Minimum
bool FindSilences(RegionList &silences, const TrackIterRange< const WaveTrack > &range)
bool Analyze(RegionList &silenceList, RegionList &trackSilences, const WaveTrack &wt, sampleCount *silentFrame, sampleCount *index, int whichTrack, double *inputLength=nullptr, double *minInputLength=nullptr) const
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 LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
wxTextCtrl * mInitialAllowedSilenceT
wxTextCtrl * mSilenceCompressPercentT
static constexpr EffectParameter Compress
bool DoRemoval(const RegionList &silences, const TrackIterRange< Track > &range, unsigned iGroup, unsigned nGroups, double &totalCutLen)
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[]
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
static TrackIterRange< Track > Group(Track &track)
static bool IsSelectedOrSyncLockSelectedP(const 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.
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
void Clear(double t0, double t1) override
double GetEndTime() const override
Implement WideSampleSequence.
double GetRate() const override
size_t GetMaxBlockSize() const
double LongSamplesToTime(sampleCount pos) const
sampleCount TimeToLongSamples(double t0) const
double SnapToSample(double t) const
virtual bool Read(const wxString &key, bool *value) const =0
Positions or offsets within audio files need a wide type.
BuiltinEffectsModule::Registration< EffectTruncSilence > reg
const char * end(const char *str) noexcept
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.
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Structure to hold region of a wavetrack and a comparison function for sortability.