Audacity 3.2.0
TruncSilenceBase.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 TruncSilenceBase.cpp
6
7 Lynn Allan (from DM's Normalize)
8 Philip Van Baren (more options and boundary fixes)
9
10*******************************************************************//*******************************************************************/
17#include "TruncSilenceBase.h"
18#include "BasicUI.h"
19#include "EffectOutputTracks.h"
20#include "Prefs.h"
21#include "Project.h"
22#include "SyncLock.h"
23#include "WaveTrack.h"
24#include <algorithm>
25#include <cmath>
26#include <limits>
27#include <list>
28
29class Enums
30{
31public:
32 static const size_t NumDbChoices;
33 static const EnumValueSymbol DbChoices[];
34};
35
37 // Table of text values, only for reading what was stored in legacy config
38 // files.
39 // It was inappropriate to make this a discrete choice control.
40 { wxT("-20 dB") }, { wxT("-25 dB") }, { wxT("-30 dB") }, { wxT("-35 dB") },
41 { wxT("-40 dB") }, { wxT("-45 dB") }, { wxT("-50 dB") }, { wxT("-55 dB") },
42 { wxT("-60 dB") }, { wxT("-65 dB") }, { wxT("-70 dB") }, { wxT("-75 dB") },
43 { wxT("-80 dB") }
44};
45
46// Map from position in table above to numerical value.
47static inline double enumToDB(int val)
48{
49 return -(5.0 * val + 20.0);
50}
51
52const size_t Enums::NumDbChoices = WXSIZEOF(Enums::DbChoices);
53
55
56// Declaration of RegionList
57class RegionList : public std::list<Region>
58{
59};
60
62 { XO("Truncate Detected Silence") }, { XO("Compress Excess Silence") }
63};
64
66 // Compatible with 2.1.0 and before
67 { wxT("0"), 0 }, // Remap to Truncate Detected Silence
68 { wxT("1"), 1 }, // Remap to Compress Excess Silence
69};
70
71static const size_t nObsoleteActions = WXSIZEOF(kObsoleteActions);
72
74{
75 static CapturedParameters<
78 parameters;
79 return parameters;
80}
81
82static const size_t DEF_BlendFrameCount = 100;
83
84// Lower bound on the amount of silence to find at a time -- this avoids
85// detecting silence repeatedly in low-frequency sounds.
86static const double DEF_MinTruncMs = 0.001;
87
88// Typical fraction of total time taken by detection (better to guess low)
89const double detectFrac = 0.4;
90
92 "Truncate Silence") };
93
95{
96 Parameters().Reset(*this);
97
99
100 // This used to be changeable via the audacity.cfg/registry. Doubtful that
101 // was ever done.
102 //
103 // Original comment:
104 //
105 // mBlendFrameCount only retrieved from prefs ... not using dialog
106 // Only way to change (for windows) is thru registry
107 // The values should be figured dynamically ... too many frames could be
108 // invalid
110}
111
113{
114}
115
116// ComponentInterface implementation
117
119{
120 return Symbol;
121}
122
124{
125 return XO(
126 "Automatically reduces the length of passages where the volume is below a specified level");
127}
128
130{
131 return L"Truncate_Silence";
132}
133
134// EffectDefinitionInterface implementation
135
137{
138 return EffectTypeProcess;
139}
140
142 const CommandParameters& parms, EffectSettings& settings) const
143{
145
146 // A bit of special treatment for two parameters
147
148 // This control migrated from a choice to a text box in version 2.3.0
149 double myThreshold {};
150 bool newParams = [&] {
151 double temp;
152 if (!parms.ReadAndVerify(
154 return false;
155 myThreshold = temp;
156 return true;
157 }();
158
159 if (!newParams)
160 {
161 int temp;
162 // Use legacy param:
163 if (!parms.ReadAndVerify(
164 L"Db", &temp, 0, Enums::DbChoices, Enums::NumDbChoices))
165 return false;
166 myThreshold = enumToDB(temp);
167 }
168
169 {
170 int temp;
171 if (!parms.ReadAndVerify(
174 return false;
175
176 // TODO: fix this when settings are really externalized
177 const_cast<int&>(mActionIndex) = temp;
178 }
179 // TODO: fix this when settings are really externalized
180 const_cast<double&>(mThresholdDB) = myThreshold;
181 return true;
182}
183
184// Effect implementation
185
187 const EffectSettings&, double /* previewLength */) const
188{
189 double inputLength = mT1 - mT0;
190 double minInputLength = inputLength;
191
192 // Master list of silent regions
193 RegionList silences;
194
195 // Start with the whole selection silent
196 silences.push_back(Region(mT0, mT1));
197
198 int whichTrack = 0;
199
200 for (auto wt : inputTracks()->Selected<const WaveTrack>())
201 {
202 RegionList trackSilences;
203
204 auto index = wt->TimeToLongSamples(mT0);
205 sampleCount silentFrame = 0; // length of the current silence
206
207 Analyze(
208 silences, trackSilences, *wt, &silentFrame, &index, whichTrack,
209 &inputLength, &minInputLength);
210
211 whichTrack += wt->NChannels();
212 }
213 return inputLength;
214}
215
217{
218 const bool success = mbIndependent ? ProcessIndependently() : ProcessAll();
219
220 return success;
221}
222
224{
225 unsigned nGroups = 0;
226
227 const bool syncLock = SyncLockState::Get(*FindProject()).IsSyncLocked();
228
229 // Check if it's permissible
230 {
231 for (auto track : inputTracks()->Selected<const WaveTrack>())
232 {
233 if (syncLock)
234 {
235 auto otherTracks =
236 SyncLock::Group(*track).Filter<const WaveTrack>() +
238 [&](const Track* pTrack) { return pTrack == track; };
239 if (otherTracks)
240 {
242 "When truncating independently, there may only be one selected audio track in each Sync-Locked Track Group."));
243 return false;
244 }
245 }
246
247 ++nGroups;
248 }
249 }
250
251 if (nGroups == 0)
252 // nothing to do
253 return true;
254
255 // Now do the work
256
257 // Copy tracks
258 EffectOutputTracks outputs {
259 *mTracks, GetType(), { { mT0, mT1 } }, true, true
260 };
261 double newT1 = 0.0;
262
263 {
264 unsigned iGroup = 0;
265 for (auto track : outputs.Get().Selected<WaveTrack>())
266 {
267 RegionList silences;
268 if (!FindSilences(
269 silences, TrackList::SingletonRange(&as_const(*track))))
270 return false;
271 // Treat tracks in the sync lock group only
272 Track *groupFirst, *groupLast;
273 auto range = syncLock ? SyncLock::Group(*track) :
274 TrackList::SingletonRange<Track>(track);
275 double totalCutLen = 0.0;
276 if (!DoRemoval(silences, range, iGroup, nGroups, totalCutLen))
277 return false;
278 newT1 = std::max(newT1, mT1 - totalCutLen);
279
280 ++iGroup;
281 }
282 }
283
284 mT1 = newT1;
285
286 outputs.Commit();
287
288 return true;
289}
290
292{
293 // Copy tracks
294 EffectOutputTracks outputs {
295 *mTracks, GetType(), { { mT0, mT1 } }, true, true
296 };
297
298 // Master list of silent regions.
299 // This list should always be kept in order.
300 RegionList silences;
301
302 if (FindSilences(silences, outputs.Get().Selected<const WaveTrack>()))
303 {
304 auto trackRange = outputs.Get().Any();
305 double totalCutLen = 0.0;
306 if (DoRemoval(silences, trackRange, 0, 1, totalCutLen))
307 {
308 mT1 -= totalCutLen;
309 outputs.Commit();
310 return true;
311 }
312 }
313
314 return false;
315}
316
318 RegionList& silences, const TrackIterRange<const WaveTrack>& range)
319{
320 // Start with the whole selection silent
321 silences.push_back(Region(mT0, mT1));
322
323 // Remove non-silent regions in each track
324 int whichTrack = 0;
325 for (auto wt : range)
326 {
327 // Smallest silent region to detect in frames
328 auto minSilenceFrames = sampleCount(
329 std::max(mInitialAllowedSilence, DEF_MinTruncMs) * wt->GetRate());
330
331 //
332 // Scan the track for silences
333 //
334 RegionList trackSilences;
335
336 auto index = wt->TimeToLongSamples(mT0);
337 sampleCount silentFrame = 0;
338
339 // Detect silences
340 bool cancelled = !(Analyze(
341 silences, trackSilences, *wt, &silentFrame, &index, whichTrack));
342
343 // Buffer has been freed, so we're OK to return if cancelled
344 if (cancelled)
345 return false;
346
347 if (silentFrame >= minSilenceFrames)
348 {
349 // Track ended in silence -- record region
350 trackSilences.push_back(Region(
351 wt->LongSamplesToTime(index - silentFrame),
352 wt->LongSamplesToTime(index)));
353 }
354
355 // Intersect with the overall silent region list
356 Intersect(silences, trackSilences);
357 whichTrack++;
358 }
359
360 return true;
361}
362
364 const RegionList& silences, const TrackIterRange<Track>& range,
365 unsigned iGroup, unsigned nGroups, double& totalCutLen)
366{
367 //
368 // Now remove the silent regions from all selected / sync-lock selected
369 // tracks.
370 //
371
372 // Loop over detected regions in reverse (so cuts don't change time values
373 // down the line)
374 int whichReg = 0;
375 RegionList::const_reverse_iterator rit;
376 for (rit = silences.rbegin(); rit != silences.rend(); ++rit)
377 {
378 const Region& region = *rit;
379 const Region* const r = &region;
380
381 // Progress dialog and cancellation. Do additional cleanup before return.
382 const double frac =
383 detectFrac + (1 - detectFrac) *
384 (iGroup + whichReg / double(silences.size())) /
385 nGroups;
386 if (TotalProgress(frac))
387 return false;
388
389 // Intersection may create regions smaller than allowed; ignore them.
390 // Allow one nanosecond extra for consistent results with exact
391 // milliseconds of allowed silence.
392 if ((r->end - r->start) < (mInitialAllowedSilence - 0.000000001))
393 continue;
394
395 // Find NEW silence length as requested
396 double inLength = r->end - r->start;
397 double outLength;
398
399 switch (mActionIndex)
400 {
401 case kTruncate:
402 outLength = std::min(mTruncLongestAllowedSilence, inLength);
403 break;
404 case kCompress:
405 outLength =
408 break;
409 default: // Not currently used.
410 outLength = std::min(
414 }
415
416 const double cutLen = std::max(0.0, inLength - outLength);
417 // Don't waste time cutting nothing.
418 if (cutLen == 0.0)
419 continue;
420
421 totalCutLen += cutLen;
422
423 bool success = true;
424 double cutStart = (r->start + r->end - cutLen) / 2;
425 double cutEnd = cutStart + cutLen;
427 [&](const Track* pTrack) {
428 return
429 // Don't waste time past the end of a track
430 pTrack->GetEndTime() < r->start;
431 })
432 .VisitWhile(
433 success,
434 [&](WaveTrack& wt) {
435 // In WaveTracks, clear with a cross-fade
436 auto blendFrames = mBlendFrameCount;
437 // Round start/end times to frame boundaries
438 cutStart = wt.SnapToSample(cutStart);
439 cutEnd = wt.SnapToSample(cutEnd);
440
441 // Make sure the cross-fade does not affect non-silent frames
442 if (wt.LongSamplesToTime(blendFrames) > inLength)
443 {
444 // Result is not more than blendFrames:
445 blendFrames = wt.TimeToLongSamples(inLength).as_size_t();
446 }
447
448 // Perform cross-fade in memory
449 struct Buffers
450 {
451 Buffers(size_t size)
452 : buf1 { size }
453 , buf2 { size }
454 {
455 }
456 Floats buf1, buf2;
457 };
458 Buffers buffers[2] { blendFrames, blendFrames };
459 auto t1 = wt.TimeToLongSamples(cutStart) - blendFrames / 2;
460 auto t2 = wt.TimeToLongSamples(cutEnd) - blendFrames / 2;
461
462 size_t iChannel = 0;
463 for (const auto pChannel : wt.Channels())
464 {
465 auto& buffer = buffers[iChannel];
466 pChannel->GetFloats(buffer.buf1.get(), t1, blendFrames);
467 pChannel->GetFloats(buffer.buf2.get(), t2, blendFrames);
468
469 for (decltype(blendFrames) i = 0; i < blendFrames; ++i)
470 {
471 buffer.buf1[i] = ((blendFrames - i) * buffer.buf1[i] +
472 i * buffer.buf2[i]) /
473 (double)blendFrames;
474 }
475 ++iChannel;
476 }
477
478 wt.Clear(cutStart, cutEnd);
479
480 iChannel = 0;
481 for (const auto pChannel : wt.Channels())
482 {
483 // Write cross-faded data
484 auto& buffer = buffers[iChannel];
485 success =
486 success &&
487 pChannel->SetFloats(
488 buffer.buf1.get(), t1, blendFrames,
489 // This effect mostly shifts samples to remove silences,
490 // and does only a little bit of floating point
491 // calculations to cross-fade the splices, over a 100
492 // sample interval by default. Don't dither.
494 ++iChannel;
495 }
496 },
497 [&](Track& t) {
498 // Non-wave tracks: just do a sync-lock adjust
499 t.SyncLockAdjust(cutEnd, cutStart);
500 });
501 if (!success)
502 return false;
503 ++whichReg;
504 }
505
506 return true;
507}
508
510 RegionList& silenceList, RegionList& trackSilences, const WaveTrack& wt,
511 sampleCount* silentFrame, sampleCount* index, int whichTrack,
512 double* inputLength, double* minInputLength) const
513{
514 const auto rate = wt.GetRate();
515
516 // Smallest silent region to detect in frames
517 auto minSilenceFrames =
519
520 double truncDbSilenceThreshold = DB_TO_LINEAR(mThresholdDB);
521 auto blockLen = wt.GetMaxBlockSize();
522 auto start = wt.TimeToLongSamples(mT0);
523 auto end = wt.TimeToLongSamples(mT1);
524 sampleCount outLength = 0;
525
526 double previewLength;
527 gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &previewLength, 6.0);
528 // Minimum required length in samples.
529 const sampleCount previewLen(previewLength * rate);
530
531 // Keep position in overall silences list for optimization
532 RegionList::iterator rit(silenceList.begin());
533
534 // Allocate buffers
535 Floats buffers[] { Floats { blockLen }, Floats { blockLen } };
536
537 // Loop through current track
538 while (*index < end)
539 {
540 if (
541 inputLength &&
542 ((outLength >= previewLen) ||
543 (*index - start > wt.TimeToLongSamples(*minInputLength))))
544 {
545 *inputLength = std::min<double>(*inputLength, *minInputLength);
546 if (outLength >= previewLen)
547 {
548 *minInputLength = *inputLength;
549 }
550 return true;
551 }
552
553 if (!inputLength)
554 {
555 // Show progress dialog, test for cancellation
556 bool cancelled = TotalProgress(
557 detectFrac *
558 (whichTrack +
559 (*index - start).as_double() / (end - start).as_double()) /
560 (double)GetNumWaveTracks());
561 if (cancelled)
562 return false;
563 }
564
565 // Optimization: if not in a silent region skip ahead to the next one
566
567 double curTime = wt.LongSamplesToTime(*index);
568 for (; rit != silenceList.end(); ++rit)
569 {
570 // Find the first silent region ending after current time
571 if (rit->end >= curTime)
572 {
573 break;
574 }
575 }
576
577 if (rit == silenceList.end())
578 {
579 // No more regions -- no need to process the rest of the track
580 if (inputLength)
581 {
582 // Add available samples up to previewLength.
583 auto remainingTrackSamples =
584 wt.TimeToLongSamples(wt.GetEndTime()) - *index;
585 auto requiredTrackSamples = previewLen - outLength;
586 outLength += (remainingTrackSamples > requiredTrackSamples) ?
587 requiredTrackSamples :
588 remainingTrackSamples;
589 }
590
591 break;
592 }
593 else if (rit->start > curTime)
594 {
595 // End current silent region, skip ahead
596 if (*silentFrame >= minSilenceFrames)
597 {
598 trackSilences.push_back(Region(
599 wt.LongSamplesToTime(*index - *silentFrame),
600 wt.LongSamplesToTime(*index)));
601 }
602 *silentFrame = 0;
603 auto newIndex = wt.TimeToLongSamples(rit->start);
604 if (inputLength)
605 {
606 auto requiredTrackSamples = previewLen - outLength;
607 // Add non-silent sample to outLength
608 outLength += ((newIndex - *index) > requiredTrackSamples) ?
609 requiredTrackSamples :
610 newIndex - *index;
611 }
612
613 *index = newIndex;
614 }
615 // End of optimization
616
617 // Limit size of current block if we've reached the end
618 auto count = limitSampleBufferSize(blockLen, end - *index);
619
620 // Fill buffers
621 size_t iChannel = 0;
622 for (const auto pChannel : wt.Channels())
623 pChannel->GetFloats(buffers[iChannel++].get(), *index, count);
624
625 // Look for silenceList in current block
626 for (decltype(count) i = 0; i < count; ++i)
627 {
628 if (
629 inputLength &&
630 ((outLength >= previewLen) ||
631 (outLength > wt.TimeToLongSamples(*minInputLength))))
632 {
633 *inputLength =
634 wt.LongSamplesToTime(*index + i) - wt.LongSamplesToTime(start);
635 break;
636 }
637
638 const bool silent =
639 std::all_of(buffers, buffers + iChannel, [&](const Floats& buffer) {
640 return fabs(buffer[i]) < truncDbSilenceThreshold;
641 });
642 if (silent)
643 (*silentFrame)++;
644 else
645 {
646 sampleCount allowed = 0;
647 if (*silentFrame >= minSilenceFrames)
648 {
649 if (inputLength)
650 {
651 switch (mActionIndex)
652 {
653 case kTruncate:
654 outLength +=
656 break;
657 case kCompress:
659 outLength += sampleCount(
660 allowed.as_double() +
661 (*silentFrame - allowed).as_double() *
663 break;
664 // default: // Not currently used.
665 }
666 }
667
668 // Record the silent region
669 trackSilences.push_back(Region(
670 wt.LongSamplesToTime(*index + i - *silentFrame),
671 wt.LongSamplesToTime(*index + i)));
672 }
673 else if (inputLength)
674 { // included as part of non-silence
675 outLength += *silentFrame;
676 }
677 *silentFrame = 0;
678 if (inputLength)
679 {
680 ++outLength; // Add non-silent sample to outLength
681 }
682 }
683 }
684 // Next block
685 *index += count;
686 }
687
688 if (inputLength)
689 {
690 *inputLength = std::min<double>(*inputLength, *minInputLength);
691 if (outLength >= previewLen)
692 {
693 *minInputLength = *inputLength;
694 }
695 }
696
697 return true;
698}
699
700// EffectTruncSilence implementation
701
702// Finds the intersection of the ordered region lists, stores in dest
704{
705 RegionList::iterator destIter;
706 destIter = dest.begin();
707 // Any time we reach the end of the dest list we're finished
708 if (destIter == dest.end())
709 return;
710 RegionList::iterator curDest = destIter;
711
712 // Operation: find non-silent regions in src, remove them from dest.
713 double nsStart = curDest->start;
714 double nsEnd;
715 bool lastRun = false; // must run the loop one extra time
716
717 RegionList::const_iterator srcIter = src.begin();
718
719 // This logic, causing the loop to run once after end of src, must occur
720 // each time srcIter is updated
721 if (srcIter == src.end())
722 {
723 lastRun = true;
724 }
725
726 while (srcIter != src.end() || lastRun)
727 {
728 // Don't use curSrc unless lastRun is false!
729 RegionList::const_iterator curSrc;
730
731 if (lastRun)
732 {
733 // The last non-silent region extends as far as possible
734 nsEnd = std::numeric_limits<double>::max();
735 }
736 else
737 {
738 curSrc = srcIter;
739 nsEnd = curSrc->start;
740 }
741
742 if (nsEnd > nsStart)
743 {
744 // Increment through dest until we have a region that could be affected
745 while (curDest->end <= nsStart)
746 {
747 ++destIter;
748 if (destIter == dest.end())
749 {
750 return;
751 }
752 curDest = destIter;
753 }
754
755 // Check for splitting dest region in two
756 if (nsStart > curDest->start && nsEnd < curDest->end)
757 {
758 // The second region
759 Region r(nsEnd, curDest->end);
760
761 // The first region
762 curDest->end = nsStart;
763
764 // Insert second region after first
765 RegionList::iterator nextIt(destIter);
766 ++nextIt;
767
768 // This should just read: destIter = dest.insert(nextIt, r); but we
769 // work around two two wxList::insert() bugs. First, in some
770 // versions it returns the wrong value. Second, in some versions,
771 // it crashes when you insert at list end.
772 if (nextIt == dest.end())
773 dest.push_back(r);
774 else
775 dest.insert(nextIt, r);
776 ++destIter; // (now points at the newly-inserted region)
777
778 curDest = destIter;
779 }
780
781 // Check for truncating the end of dest region
782 if (
783 nsStart > curDest->start && nsStart < curDest->end &&
784 nsEnd >= curDest->end)
785 {
786 curDest->end = nsStart;
787
788 ++destIter;
789 if (destIter == dest.end())
790 {
791 return;
792 }
793 curDest = destIter;
794 }
795
796 // Check for all dest regions that need to be removed completely
797 while (nsStart <= curDest->start && nsEnd >= curDest->end)
798 {
799 destIter = dest.erase(destIter);
800 if (destIter == dest.end())
801 {
802 return;
803 }
804 curDest = destIter;
805 }
806
807 // Check for truncating the beginning of dest region
808 if (
809 nsStart <= curDest->start && nsEnd > curDest->start &&
810 nsEnd < curDest->end)
811 {
812 curDest->start = nsEnd;
813 }
814 }
815
816 if (lastRun)
817 {
818 // done
819 lastRun = false;
820 }
821 else
822 {
823 // Next non-silent region starts at the end of this silent region
824 nsStart = curSrc->end;
825 ++srcIter;
826 if (srcIter == src.end())
827 {
828 lastRun = true;
829 }
830 }
831 }
832}
833
834/*
835void TruncSilenceBase::BlendFrames(float* buffer, int blendFrameCount, int
836leftIndex, int rightIndex)
837{
838 float* bufOutput = &buffer[leftIndex];
839 float* bufBefore = &buffer[leftIndex];
840 float* bufAfter = &buffer[rightIndex];
841 double beforeFactor = 1.0;
842 double afterFactor = 0.0;
843 double adjFactor = 1.0 / (double)blendFrameCount;
844 for (int j = 0; j < blendFrameCount; ++j)
845 {
846 bufOutput[j] = (float)((bufBefore[j] * beforeFactor) + (bufAfter[j] *
847afterFactor)); beforeFactor -= adjFactor; afterFactor += adjFactor;
848 }
849}
850*/
851
853{
854 return false;
855}
wxT("CloseDown"))
Toolkit-neutral facade for basic user interface services.
int min(int a, int b)
EffectType
@ EffectTypeProcess
XO("Cut/Copy/Paste")
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:338
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
@ narrowestSampleFormat
Two synonyms for previous values that might change if more values were added.
static Settings & settings()
Definition: TrackInfo.cpp:51
static CommandParameters::ObsoleteMap kObsoleteActions[]
static const size_t DEF_BlendFrameCount
WaveTrack::Region Region
static const size_t nObsoleteActions
const double detectFrac
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,...
double mT1
Definition: EffectBase.h:123
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:210
const TrackList * inputTracks() const
Definition: EffectBase.h:102
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:116
double mT0
Definition: EffectBase.h:122
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:220
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
Definition: Effect.cpp:122
bool TotalProgress(double frac, const TranslatableString &={}) const
Definition: Effect.cpp:335
int GetNumWaveTracks() const
Definition: Effect.h:139
Performs effect computation.
Use this object to copy the input tracks to tentative outputTracks.
Interface for manipulations of an Effect's settings.
virtual void Reset(Effect &effect) const =0
static const size_t NumDbChoices
static const EnumValueSymbol DbChoices[]
static TrackIterRange< Track > Group(Track &track)
Definition: SyncLock.cpp:150
static bool IsSelectedOrSyncLockSelectedP(const Track *pTrack)
Definition: SyncLock.h:61
bool IsSyncLocked() const
Definition: SyncLock.cpp:44
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:27
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
bool IsSelected() const
Definition: Track.cpp:258
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:981
Holds a msgid for the translation catalog; may also bind format arguments.
static constexpr EffectParameter Independent
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
bool FindSilences(RegionList &silences, const TrackIterRange< const WaveTrack > &range)
static constexpr EffectParameter Threshold
ComponentInterfaceSymbol GetSymbol() const override
EffectType GetType() const override
Type determines how it behaves.
bool DoRemoval(const RegionList &silences, const TrackIterRange< Track > &range, unsigned iGroup, unsigned nGroups, double &totalCutLen)
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
const EffectParameterMethods & Parameters() const override
static constexpr EffectParameter Truncate
bool Process(EffectInstance &instance, EffectSettings &settings) override
bool Analyze(RegionList &silenceList, RegionList &trackSilences, const WaveTrack &wt, sampleCount *silentFrame, sampleCount *index, int whichTrack, double *inputLength=nullptr, double *minInputLength=nullptr) const
double mSilenceCompressPercent
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
static constexpr EffectParameter Minimum
static constexpr EffectParameter Compress
static constexpr EnumParameter ActIndex
double mInitialAllowedSilence
static const EnumValueSymbol kActionStrings[nActions]
TranslatableString GetDescription() const override
void Intersect(RegionList &dest, const RegionList &src)
double mTruncLongestAllowedSilence
static const ComponentInterfaceSymbol Symbol
bool NeedsDither() const override
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
auto Channels()
Definition: WaveTrack.h:263
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1161
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2613
double GetRate() const override
Definition: WaveTrack.cpp:821
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2279
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.
Definition: SampleCount.h:19
size_t as_size_t() const
Definition: SampleCount.cpp:16
double as_double() const
Definition: SampleCount.h:46
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:287
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
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.
Definition: Track.h:682
Structure to hold region of a wavetrack and a comparison function for sortability.
Definition: WaveTrack.h:217