Audacity 3.2.0
ChangeSpeed.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ChangeSpeed.cpp
6
7 Vaughan Johnson, Dominic Mazzoni
8
9*******************************************************************//*******************************************************************/
15
16
17#include "ChangeSpeed.h"
18#include "EffectEditor.h"
19#include "EffectOutputTracks.h"
20#include "LoadEffects.h"
21
22#include <math.h>
23
24#include <wx/choice.h>
25#include <wx/slider.h>
26
27#include "ConfigInterface.h"
28#include "../LabelTrack.h"
29#include "Prefs.h"
30#include "Resample.h"
31#include "ShuttleGui.h"
32#include "SyncLock.h"
33#include "../widgets/NumericTextCtrl.h"
34#include "../widgets/valnum.h"
35
36#include "TimeWarper.h"
37#include "WaveClip.h"
38#include "WaveTrack.h"
39
41
42enum
43{
49};
50
51// the standard vinyl rpm choices
52// If the percent change is not one of these ratios, the choice control gets "n/a".
54{
59};
60
62 XO("33\u2153"),
63 XO("45"),
64 XO("78"),
65 /* i18n-hint: n/a is an English abbreviation meaning "not applicable". */
66 XO("n/a"),
67};
68
69// Soundtouch is not reasonable below -99% or above 3000%.
70
72{
75 > parameters;
76 return parameters;
77}
78
79// We warp the slider to go up to 400%, but user can enter higher values
80static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
81static const double kSliderWarp = 1.30105; // warp power takes max from 100 to 400.
82
83//
84// EffectChangeSpeed
85//
86
88{ XO("Change Speed and Pitch") };
89
91
92BEGIN_EVENT_TABLE(EffectChangeSpeed, wxEvtHandler)
101
103{
104 Parameters().Reset(*this);
105
106 mFromVinyl = kVinyl_33AndAThird;
107 mToVinyl = kVinyl_33AndAThird;
108 mFromLength = 0.0;
109 mToLength = 0.0;
111 mbLoopDetect = false;
112
113 SetLinearEffectFlag(true);
114}
115
117{
118}
119
120// ComponentInterface implementation
121
123{
124 return Symbol;
125}
126
128{
129 return XO("Changes the speed of a track, also changing its pitch");
130}
131
133{
134 return L"Change_Speed";
135}
136
137
138// EffectDefinitionInterface implementation
139
141{
142 return EffectTypeProcess;
143}
144
146{
147 // To do: externalize state so const_cast isn't needed
148 return const_cast<EffectChangeSpeed&>(*this).DoLoadFactoryDefaults(settings);
149}
150
153{
156
158}
159
160// Effect implementation
161
163{
164 return (m_PercentChange == 0.0);
165}
166
168 const EffectSettings &, double previewLength) const
169{
170 return previewLength * (100.0 + m_PercentChange) / 100.0;
171}
172
174{
175 // The selection might have changed since the last time EffectChangeSpeed
176 // was invoked, so recalculate the Length parameters.
177 mFromLength = mT1 - mT0;
178 return true;
179}
180
182 const WaveTrack &track, const double curT0, const double curT1) -> Gaps
183{
184 // Silenced samples will be inserted in gaps between clips, so capture where
185 // these gaps are for later deletion
186 Gaps gaps;
187 const auto newGap = [&](double st, double et){
188 gaps.emplace_back(track.SnapToSample(st), track.SnapToSample(et));
189 };
190 double last = curT0;
191 auto clips = track.SortedClipArray();
192 auto front = clips.front();
193 auto back = clips.back();
194 for (auto &clip : clips) {
195 auto st = clip->GetPlayStartTime();
196 auto et = clip->GetPlayEndTime();
197 if (st >= curT0 || et < curT1) {
198 if (curT0 < st && clip == front)
199 newGap(curT0, st);
200 else if (last < st && curT0 <= last)
201 newGap(last, st);
202 if (et < curT1 && clip == back)
203 newGap(et, curT1);
204 }
205 last = et;
206 }
207 return gaps;
208}
209
211{
212 // Similar to EffectSoundTouch::Process()
213
214 // Iterate over each track.
215 // All needed because this effect needs to introduce
216 // silence in the sync-lock group tracks to keep sync
217 EffectOutputTracks outputs { *mTracks, GetType(), { { mT0, mT1 } }, true };
218 bool bGoodResult = true;
219
220 mCurTrackNum = 0;
221
222 mFactor = 100.0 / (100.0 + m_PercentChange);
223
224 outputs.Get().Any().VisitWhile(bGoodResult,
225 [&](LabelTrack &lt) {
227 if (!ProcessLabelTrack(&lt))
228 bGoodResult = false;
229 }
230 },
231 [&](auto &&fallthrough){ return [&](WaveTrack &outWaveTrack) {
232 if (!outWaveTrack.GetSelected())
233 return fallthrough();
234
235 //Get start and end times from track
236 mCurT0 = outWaveTrack.GetStartTime();
237 mCurT1 = outWaveTrack.GetEndTime();
238
239 //Set the current bounds to whichever left marker is
240 //greater and whichever right marker is less:
241 mCurT0 = std::max(mT0, mCurT0);
243
244 // Process only if the right marker is to the right of the left marker
245 if (mCurT1 > mCurT0) {
246 //Transform the marker timepoints to samples
247 auto start = outWaveTrack.TimeToLongSamples(mCurT0);
248 auto end = outWaveTrack.TimeToLongSamples(mCurT1);
249
250 const auto gaps = FindGaps(outWaveTrack, mCurT0, mCurT1);
251
252 auto newTracks = outWaveTrack.WideEmptyCopy();
253 auto iter =
254 (*newTracks->Any<WaveTrack>().begin())->Channels().begin();
255 for (const auto pChannel : outWaveTrack.Channels()) {
256 // ProcessOne() (implemented below) processes a single channel
257 if (ProcessOne(*pChannel, **iter++, start, end))
258 ++mCurTrackNum;
259 else {
260 newTracks.reset();
261 break;
262 }
263 }
264 if (!newTracks) {
265 bGoodResult = false;
266 return;
267 }
268 const auto pNewTrack = *newTracks->Any<WaveTrack>().begin();
269 pNewTrack->Flush();
270
271 const double newLength = pNewTrack->GetEndTime();
272 const LinearTimeWarper warper{
273 mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
274
275 outWaveTrack.ClearAndPaste(mCurT0, mCurT1,
276 *newTracks, true, true, &warper);
277
278 // Finally, recreate the gaps
279 for (const auto [st, et] : gaps)
280 if (st >= mCurT0 && et <= mCurT1 && st != et)
281 outWaveTrack.SplitDelete(warper.Warp(st), warper.Warp(et));
282 }
283 else
284 mCurTrackNum += outWaveTrack.NChannels();
285 }; },
286 [&](Track &t) {
288 t.SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
289 }
290 );
291
292 if (bGoodResult)
293 outputs.Commit();
294
295 // Update selection.
296 mT1 = mT0 + (((mT1 - mT0) * 100.0) / (100.0 + m_PercentChange));
297
298 return bGoodResult;
299}
300
301std::unique_ptr<EffectEditor> EffectChangeSpeed::PopulateOrExchange(
303 const EffectOutputs *)
304{
305 mUIParent = S.GetParent();
306
307 {
308 wxString formatId;
311 wxT("TimeFormat"), formatId, mFormat.GET());
314 NumericConverterType_TIME(), formatId).Internal();
315 }
318 wxT("VinylChoice"), mFromVinyl, mFromVinyl);
319
320 S.SetBorder(5);
321
322 S.StartVerticalLay(0);
323 {
324 // Speed multiplier and percent change controls.
325 S.StartMultiColumn(4, wxCENTER);
326 {
328 .Validator<FloatingPointValidator<double>>(
329 3, &mMultiplier,
330 NumValidatorStyle::THREE_TRAILING_ZEROES,
331 Percentage.min / 100.0, ((Percentage.max / 100.0) + 1) )
332 .AddTextBox(XXO("&Speed Multiplier:"), L"", 12);
333
335 .Validator<FloatingPointValidator<double>>(
336 3, &m_PercentChange,
337 NumValidatorStyle::THREE_TRAILING_ZEROES,
339 .AddTextBox(XXO("Percent C&hange:"), L"", 12);
340 }
341 S.EndMultiColumn();
342
343 // Percent change slider.
344 S.StartHorizontalLay(wxEXPAND);
345 {
347 .Name(XO("Percent Change"))
348 .Style(wxSL_HORIZONTAL)
349 .AddSlider( {}, 0, (int)kSliderMax, (int)Percentage.min);
350 }
351 S.EndHorizontalLay();
352
353 // Vinyl rpm controls.
354 S.StartMultiColumn(5, wxCENTER);
355 {
356 /* i18n-hint: "rpm" is an English abbreviation meaning "revolutions per minute".
357 "vinyl" refers to old-fashioned phonograph records */
358 S.AddUnits(XO("Standard Vinyl rpm:"));
359
361 /* i18n-hint: changing speed of audio "from" one value "to" another
362 "rpm" means "revolutions per minute" as on a vinyl record turntable
363 */
364 .Name(XO("From rpm"))
365 .MinSize( { 100, -1 } )
366 /* i18n-hint: changing speed of audio "from" one value "to" another */
367 .AddChoice(XXC("&from", "change speed"), kVinylStrings);
368
370 /* i18n-hint: changing speed of audio "from" one value "to" another
371 "rpm" means "revolutions per minute" as on a vinyl record turntable
372 */
373 .Name(XO("To rpm"))
374 .MinSize( { 100, -1 } )
375 /* i18n-hint: changing speed of audio "from" one value "to" another */
376 .AddChoice(XXC("&to", "change speed"), kVinylStrings);
377 }
378 S.EndMultiColumn();
379
380 // From/To time controls.
381 S.StartStatic(XO("Selection Length"), 0);
382 {
383 S.StartMultiColumn(2, wxALIGN_LEFT);
384 {
385 S.AddPrompt(XXO("C&urrent Length:"));
386
389 S.GetParent(), wxID_ANY,
391 mFormat,
394 .ReadOnly(true)
395 .MenuEnabled(false));
396
397 S.ToolTip(XO("Current length of selection."))
398 /* i18n-hint: changing speed of audio "from" one value "to" another */
399 .Name(XC("from", "change speed"))
400 .Position(wxALIGN_LEFT)
401 .AddWindow(mpFromLengthCtrl);
402
403 S.AddPrompt(XXO("&New Length:"));
404
407 S.GetParent(), ID_ToLength,
409 mFormat,
410 mToLength);
411
412 /* i18n-hint: changing speed of audio "from" one value "to" another */
413 S.Name(XC("to", "change speed"))
414 .Position(wxALIGN_LEFT)
415 .AddWindow(mpToLengthCtrl);
416 }
417 S.EndMultiColumn();
418 }
419 S.EndStatic();
420 }
421 S.EndVerticalLay();
422 return nullptr;
423}
424
426{
427 mbLoopDetect = true;
428
429 if (!mUIParent->TransferDataToWindow())
430 {
431 return false;
432 }
433
434 if (mFromVinyl == kVinyl_NA)
435 {
437 }
438
443
444 // Set from/to Vinyl controls - mFromVinyl must be set first.
445 mpChoice_FromVinyl->SetSelection(mFromVinyl);
446 // Then update to get correct mToVinyl.
447 Update_Vinyl();
448 // Then update ToVinyl control.
449 mpChoice_ToVinyl->SetSelection(mToVinyl);
450
451 // Set From Length control.
452 // Set the format first so we can get sample accuracy.
455
456 mbLoopDetect = false;
457
458 return true;
459}
460
462{
463 // mUIParent->TransferDataFromWindow() loses some precision, so save and restore it.
464 double exactPercent = m_PercentChange;
465 if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
466 {
467 return false;
468 }
469 m_PercentChange = exactPercent;
470
471 // TODO: just visit these effect settings the default way
473 CurrentSettingsGroup(), wxT("TimeFormat"), mFormat.GET());
475 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
476
477 return true;
478}
479
480// EffectChangeSpeed implementation
481
482// Labels are time-scaled linearly inside the affected region, and labels after
483// the region are shifted along according to how the region size changed.
485{
486 RegionTimeWarper warper { mT0, mT1,
487 std::make_unique<LinearTimeWarper>(mT0, mT0,
488 mT1, mT0 + (mT1-mT0)*mFactor) };
489 lt->WarpLabels(warper);
490 return true;
491}
492
493// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
494// and calls libsamplerate code on these blocks.
496 const WaveChannel &track, WaveChannel &outputTrack,
498{
499 //Get the length of the selection (as double). len is
500 //used simple to calculate a progress meter, so it is easier
501 //to make it a double now than it is to do it later
502 auto len = (end - start).as_double();
503
504 // Initiate processing buffers, most likely shorter than
505 // the length of the selection being processed.
506 auto inBufferSize = track.GetMaxBlockSize();
507
508 Floats inBuffer{ inBufferSize };
509
510 // mFactor is at most 100-fold so this shouldn't overflow size_t
511 auto outBufferSize = size_t( mFactor * inBufferSize + 10 );
512 Floats outBuffer{ outBufferSize };
513
514 // Set up the resampling stuff for this track.
515 Resample resample(true, mFactor, mFactor); // constant rate resampling
516
517 //Go through the track one buffer at a time. samplePos counts which
518 //sample the current buffer starts at.
519 bool bResult = true;
520 auto samplePos = start;
521 while (samplePos < end) {
522 //Get a blockSize of samples (smaller than the size of the buffer)
523 auto blockSize = limitSampleBufferSize(
524 track.GetBestBlockSize(samplePos),
525 end - samplePos
526 );
527
528 //Get the samples from the track and put them in the buffer
529 track.GetFloats(inBuffer.get(), samplePos, blockSize);
530
531 const auto results = resample.Process(mFactor,
532 inBuffer.get(),
533 blockSize,
534 ((samplePos + blockSize) >= end),
535 outBuffer.get(),
536 outBufferSize);
537 const auto outgen = results.second;
538
539 if (outgen > 0)
540 outputTrack.Append((samplePtr)outBuffer.get(), floatSample,
541 outgen);
542
543 // Increment samplePos
544 samplePos += results.first;
545
546 // Update the Progress meter
547 if (TrackProgress(mCurTrackNum, (samplePos - start).as_double() / len)) {
548 bResult = false;
549 break;
550 }
551 }
552
553 return bResult;
554}
555
556// handler implementations for EffectChangeSpeed
557
558void EffectChangeSpeed::OnText_PercentChange(wxCommandEvent & WXUNUSED(evt))
559{
560 if (mbLoopDetect)
561 return;
562
563 mpTextCtrl_PercentChange->GetValidator()->TransferFromWindow();
564 UpdateUI();
565
566 mbLoopDetect = true;
569 Update_Vinyl();
571 mbLoopDetect = false;
572}
573
574void EffectChangeSpeed::OnText_Multiplier(wxCommandEvent & WXUNUSED(evt))
575{
576 if (mbLoopDetect)
577 return;
578
579 mpTextCtrl_Multiplier->GetValidator()->TransferFromWindow();
580 m_PercentChange = 100 * (mMultiplier - 1);
581 UpdateUI();
582
583 mbLoopDetect = true;
586 Update_Vinyl();
588 mbLoopDetect = false;
589}
590
591void EffectChangeSpeed::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(evt))
592{
593 if (mbLoopDetect)
594 return;
595
596 m_PercentChange = (double)(mpSlider_PercentChange->GetValue());
597 // Warp positive values to actually go up faster & further than negatives.
598 if (m_PercentChange > 0.0)
600 UpdateUI();
601
602 mbLoopDetect = true;
605 Update_Vinyl();
607 mbLoopDetect = false;
608}
609
610void EffectChangeSpeed::OnChoice_Vinyl(wxCommandEvent & WXUNUSED(evt))
611{
612 // Treat mpChoice_FromVinyl and mpChoice_ToVinyl as one control since we need
613 // both to calculate Percent Change.
614 mFromVinyl = mpChoice_FromVinyl->GetSelection();
615 mToVinyl = mpChoice_ToVinyl->GetSelection();
616 // Use this as the 'preferred' choice.
617 if (mFromVinyl != kVinyl_NA) {
619 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
620 }
621
622 // If mFromVinyl & mToVinyl are set, then there's a NEW percent change.
623 if ((mFromVinyl != kVinyl_NA) && (mToVinyl != kVinyl_NA))
624 {
625 double fromRPM;
626 double toRPM;
627 switch (mFromVinyl) {
628 default:
629 case kVinyl_33AndAThird: fromRPM = 33.0 + (1.0 / 3.0); break;
630 case kVinyl_45: fromRPM = 45.0; break;
631 case kVinyl_78: fromRPM = 78; break;
632 }
633 switch (mToVinyl) {
634 default:
635 case kVinyl_33AndAThird: toRPM = 33.0 + (1.0 / 3.0); break;
636 case kVinyl_45: toRPM = 45.0; break;
637 case kVinyl_78: toRPM = 78; break;
638 }
639 m_PercentChange = ((toRPM * 100.0) / fromRPM) - 100.0;
640 UpdateUI();
641
642 mbLoopDetect = true;
647 }
648 mbLoopDetect = false;
649}
650
651void EffectChangeSpeed::OnTimeCtrl_ToLength(wxCommandEvent & WXUNUSED(evt))
652{
653 if (mbLoopDetect)
654 return;
655
657 // Division by (double) 0.0 is not an error and we want to show "infinite" in
658 // text controls, so take care that we handle infinite values when they occur.
659 m_PercentChange = ((mFromLength * 100.0) / mToLength) - 100.0;
660 UpdateUI();
661
662 mbLoopDetect = true;
663
667 Update_Vinyl();
668
669 mbLoopDetect = false;
670}
671
672void EffectChangeSpeed::OnTimeCtrlUpdate(wxCommandEvent & evt)
673{
676 NumericConverterType_TIME(), evt.GetString()).Internal();
677
679 // Update From/To Length controls (precision has changed).
682}
683
684// helper functions
685
687// Update Text Percent control from percent change.
688{
689 mpTextCtrl_PercentChange->GetValidator()->TransferToWindow();
690}
691
693// Update Multiplier control from percent change.
694{
695 mMultiplier = 1 + (m_PercentChange) / 100.0;
696 mpTextCtrl_Multiplier->GetValidator()->TransferToWindow();
697}
698
700// Update Slider Percent control from percent change.
701{
702 auto unwarped = std::min<double>(m_PercentChange, Percentage.max);
703 if (unwarped > 0.0)
704 // Un-warp values above zero to actually go up to kSliderMax.
705 unwarped = pow(m_PercentChange, (1.0 / kSliderWarp));
706
707 // Caution: m_PercentChange could be infinite.
708 int unwarpedi = (int)(unwarped + 0.5);
709 unwarpedi = std::min<int>(unwarpedi, (int)kSliderMax);
710
711 mpSlider_PercentChange->SetValue(unwarpedi);
712}
713
715// Update Vinyl controls from percent change.
716{
717 // Match Vinyl rpm when within 0.01% of a standard ratio.
718 // Ratios calculated as: ((toRPM / fromRPM) - 1) * 100 * 100
719
720 // Caution: m_PercentChange could be infinite
721 int ratio = (int)((m_PercentChange * 100) + 0.5);
722
723 switch (ratio)
724 {
725 case 0: // toRPM is the same as fromRPM
726 if (mFromVinyl != kVinyl_NA) {
727 mpChoice_ToVinyl->SetSelection(mpChoice_FromVinyl->GetSelection());
728 } else {
729 // Use the last saved option.
731 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl, 0);
732 mpChoice_FromVinyl->SetSelection(mFromVinyl);
733 mpChoice_ToVinyl->SetSelection(mFromVinyl);
734 }
735 break;
736 case 3500:
738 mpChoice_ToVinyl->SetSelection(kVinyl_45);
739 break;
740 case 13400:
742 mpChoice_ToVinyl->SetSelection(kVinyl_78);
743 break;
744 case -2593:
745 mpChoice_FromVinyl->SetSelection(kVinyl_45);
747 break;
748 case 7333:
749 mpChoice_FromVinyl->SetSelection(kVinyl_45);
750 mpChoice_ToVinyl->SetSelection(kVinyl_78);
751 break;
752 case -5727:
753 mpChoice_FromVinyl->SetSelection(kVinyl_78);
755 break;
756 case -4231:
757 mpChoice_FromVinyl->SetSelection(kVinyl_78);
758 mpChoice_ToVinyl->SetSelection(kVinyl_45);
759 break;
760 default:
761 mpChoice_ToVinyl->SetSelection(kVinyl_NA);
762 }
763 // and update variables.
764 mFromVinyl = mpChoice_FromVinyl->GetSelection();
765 mToVinyl = mpChoice_ToVinyl->GetSelection();
766}
767
769// Update ToLength control from percent change.
770{
771 mToLength = (mFromLength * 100.0) / (100.0 + m_PercentChange);
772
773 // Set the format first so we can get sample accuracy.
775 // Negative times do not make sense.
776 // 359999 = 99h:59m:59s which is a little less disturbing than overflow characters
777 // though it may still look a bit strange with some formats.
778 mToLength = std::clamp<double>(mToLength, 0.0, 359999.0);
780}
781
783// Disable OK and Preview if not in sensible range.
784{
787}
wxT("CloseDown"))
END_EVENT_TABLE()
static const double kSliderMax
Definition: ChangeSpeed.cpp:80
kVinyl
Definition: ChangeSpeed.cpp:54
@ kVinyl_78
Definition: ChangeSpeed.cpp:57
@ kVinyl_45
Definition: ChangeSpeed.cpp:56
@ kVinyl_33AndAThird
Definition: ChangeSpeed.cpp:55
@ kVinyl_NA
Definition: ChangeSpeed.cpp:58
static const TranslatableStrings kVinylStrings
Definition: ChangeSpeed.cpp:61
@ ID_ToLength
Definition: ChangeSpeed.cpp:48
@ ID_FromVinyl
Definition: ChangeSpeed.cpp:46
@ ID_ToVinyl
Definition: ChangeSpeed.cpp:47
@ ID_Multiplier
Definition: ChangeSpeed.cpp:45
@ ID_PercentChange
Definition: ChangeSpeed.cpp:44
static const double kSliderWarp
Definition: ChangeSpeed.cpp:81
int min(int a, int b)
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
EffectType
@ EffectTypeProcess
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define XXC(s, c)
Definition: Internat.h:47
#define XC(s, c)
Definition: Internat.h:37
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:89
#define safenew
Definition: MemoryX.h:9
const NumericConverterType & NumericConverterType_TIME()
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
char * samplePtr
Definition: SampleFormat.h:57
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:69
std::vector< TranslatableString > TranslatableStrings
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
const wxString & Internal() const
double mT1
Definition: EffectBase.h:116
double mProjectRate
Definition: EffectBase.h:112
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:109
double mT0
Definition: EffectBase.h:115
An Effect that affects both pitch & speed.
Definition: ChangeSpeed.h:29
void OnText_PercentChange(wxCommandEvent &evt)
NumericFormatID mFormat
Definition: ChangeSpeed.h:123
NumericTextCtrl * mpToLengthCtrl
Definition: ChangeSpeed.h:117
EffectType GetType() const override
Type determines how it behaves.
bool CheckWhetherSkipEffect(const EffectSettings &settings) const override
After Init(), tell whether Process() should be skipped.
virtual ~EffectChangeSpeed()
static const ComponentInterfaceSymbol Symbol
Definition: ChangeSpeed.h:33
OptionalMessage LoadFactoryDefaults(EffectSettings &settings) const override
void OnChoice_Vinyl(wxCommandEvent &evt)
void OnText_Multiplier(wxCommandEvent &evt)
bool TransferDataToWindow(const EffectSettings &settings) override
void Update_Slider_PercentChange()
OptionalMessage DoLoadFactoryDefaults(EffectSettings &settings)
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
wxTextCtrl * mpTextCtrl_Multiplier
Definition: ChangeSpeed.h:112
void Update_TimeCtrl_ToLength()
std::vector< Gap > Gaps
Definition: ChangeSpeed.h:66
wxChoice * mpChoice_ToVinyl
Definition: ChangeSpeed.h:115
wxTextCtrl * mpTextCtrl_PercentChange
Definition: ChangeSpeed.h:111
const EffectParameterMethods & Parameters() const override
Definition: ChangeSpeed.cpp:71
Gaps FindGaps(const WaveTrack &track, const double curT0, const double curT1)
bool ProcessOne(const WaveChannel &track, WaveChannel &outputTrack, sampleCount start, sampleCount end)
wxWeakRef< wxWindow > mUIParent
Definition: ChangeSpeed.h:91
void Update_Text_PercentChange()
bool Process(EffectInstance &instance, EffectSettings &settings) override
wxChoice * mpChoice_FromVinyl
Definition: ChangeSpeed.h:114
void OnTimeCtrl_ToLength(wxCommandEvent &evt)
void Update_Text_Multiplier()
void OnSlider_PercentChange(wxCommandEvent &evt)
ComponentInterfaceSymbol GetSymbol() const override
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
bool TransferDataFromWindow(EffectSettings &settings) override
void OnTimeCtrlUpdate(wxCommandEvent &evt)
static constexpr EffectParameter Percentage
Definition: ChangeSpeed.h:128
bool ProcessLabelTrack(LabelTrack *t)
wxSlider * mpSlider_PercentChange
Definition: ChangeSpeed.h:113
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
double m_PercentChange
Definition: ChangeSpeed.h:99
TranslatableString GetDescription() const override
bool Init() override
NumericTextCtrl * mpFromLengthCtrl
Definition: ChangeSpeed.h:116
static bool EnableApply(wxWindow *parent, bool enable=true)
Enable or disable the Apply button of the dialog that contains parent.
const EffectSettingsManager & GetDefinition() const override
Definition: Effect.cpp:182
OptionalMessage LoadFactoryDefaults(EffectSettings &settings) const override
Definition: Effect.cpp:165
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:343
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.
static FormatterContext SampleRateContext(double sampleRate)
const wxString & GET() const
Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct...
Definition: Identifier.h:66
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
void WarpLabels(const TimeWarper &warper)
Definition: LabelTrack.cpp:294
Linear scaling, initialised by giving two points on the line.
Definition: TimeWarper.h:87
bool SetFormatName(const NumericFormatID &formatName)
void SetValue(double newValue)
No change before the specified region; during the region, warp according to the given warper; after t...
Definition: TimeWarper.h:192
Interface to libsoxr.
Definition: Resample.h:27
std::pair< size_t, size_t > Process(double factor, const float *inBuffer, size_t inBufferLen, bool lastFlag, float *outBuffer, size_t outBufferLen)
Main processing function. Resamples from the input buffer to the output buffer.
Definition: Resample.cpp:88
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:630
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:112
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:82
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
Holds a msgid for the translation catalog; may also bind format arguments.
bool Append(constSamplePtr buffer, sampleFormat format, size_t len)
Definition: WaveTrack.cpp:2698
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
"narrow" overload fetches from the unique channel
Definition: WaveTrack.h:159
size_t GetBestBlockSize(sampleCount t) const
A hint for sizing of well aligned fetches.
Definition: WaveTrack.h:1244
size_t GetMaxBlockSize() const
Definition: WaveTrack.h:1252
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
NUMERIC_FORMATS_API NumericFormatSymbol DefaultSelectionFormat()
NUMERIC_FORMATS_API NumericFormatSymbol Lookup(const FormatterContext &context, const NumericConverterType &type, const NumericFormatID &formatIdentifier)
Looks up the format, returns Default for the type if the format is not registered.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
BuiltinEffectsModule::Registration< EffectChangeSpeed > reg
Definition: ChangeSpeed.cpp:90
const Type min
Minimum value.
const Type max
Maximum value.
Externalized state of a plug-in.
Options & ReadOnly(bool enable)