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.SortedIntervalArray();
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 pNewTrack = outWaveTrack.EmptyCopy();
253 auto iter = pNewTrack->Channels().begin();
254 for (const auto pChannel : outWaveTrack.Channels()) {
255 // ProcessOne() (implemented below) processes a single channel
256 if (ProcessOne(*pChannel, **iter++, start, end))
257 ++mCurTrackNum;
258 else {
259 pNewTrack.reset();
260 break;
261 }
262 }
263 if (!pNewTrack) {
264 bGoodResult = false;
265 return;
266 }
267 pNewTrack->Flush();
268
269 const double newLength = pNewTrack->GetEndTime();
270 const LinearTimeWarper warper{
271 mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
272
273 outWaveTrack.ClearAndPaste(mCurT0, mCurT1,
274 *pNewTrack, true, true, &warper);
275
276 // Finally, recreate the gaps
277 for (const auto [st, et] : gaps)
278 if (st >= mCurT0 && et <= mCurT1 && st != et)
279 outWaveTrack.SplitDelete(warper.Warp(st), warper.Warp(et));
280 }
281 else
282 mCurTrackNum += outWaveTrack.NChannels();
283 }; },
284 [&](Track &t) {
286 t.SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
287 }
288 );
289
290 if (bGoodResult)
291 outputs.Commit();
292
293 // Update selection.
294 mT1 = mT0 + (((mT1 - mT0) * 100.0) / (100.0 + m_PercentChange));
295
296 return bGoodResult;
297}
298
299std::unique_ptr<EffectEditor> EffectChangeSpeed::PopulateOrExchange(
301 const EffectOutputs *)
302{
303 mUIParent = S.GetParent();
304
305 {
306 wxString formatId;
309 wxT("TimeFormat"), formatId, mFormat.GET());
312 NumericConverterType_TIME(), formatId).Internal();
313 }
316 wxT("VinylChoice"), mFromVinyl, mFromVinyl);
317
318 S.SetBorder(5);
319
320 S.StartVerticalLay(0);
321 {
322 // Speed multiplier and percent change controls.
323 S.StartMultiColumn(4, wxCENTER);
324 {
326 .Validator<FloatingPointValidator<double>>(
327 3, &mMultiplier,
328 NumValidatorStyle::THREE_TRAILING_ZEROES,
329 Percentage.min / 100.0, ((Percentage.max / 100.0) + 1) )
330 .AddTextBox(XXO("&Speed Multiplier:"), L"", 12);
331
333 .Validator<FloatingPointValidator<double>>(
334 3, &m_PercentChange,
335 NumValidatorStyle::THREE_TRAILING_ZEROES,
337 .AddTextBox(XXO("Percent C&hange:"), L"", 12);
338 }
339 S.EndMultiColumn();
340
341 // Percent change slider.
342 S.StartHorizontalLay(wxEXPAND);
343 {
345 .Name(XO("Percent Change"))
346 .Style(wxSL_HORIZONTAL)
347 .AddSlider( {}, 0, (int)kSliderMax, (int)Percentage.min);
348 }
349 S.EndHorizontalLay();
350
351 // Vinyl rpm controls.
352 S.StartMultiColumn(5, wxCENTER);
353 {
354 /* i18n-hint: "rpm" is an English abbreviation meaning "revolutions per minute".
355 "vinyl" refers to old-fashioned phonograph records */
356 S.AddUnits(XO("Standard Vinyl rpm:"));
357
359 /* i18n-hint: changing speed of audio "from" one value "to" another
360 "rpm" means "revolutions per minute" as on a vinyl record turntable
361 */
362 .Name(XO("From rpm"))
363 .MinSize( { 100, -1 } )
364 /* i18n-hint: changing speed of audio "from" one value "to" another */
365 .AddChoice(XXC("&from", "change speed"), kVinylStrings);
366
368 /* i18n-hint: changing speed of audio "from" one value "to" another
369 "rpm" means "revolutions per minute" as on a vinyl record turntable
370 */
371 .Name(XO("To rpm"))
372 .MinSize( { 100, -1 } )
373 /* i18n-hint: changing speed of audio "from" one value "to" another */
374 .AddChoice(XXC("&to", "change speed"), kVinylStrings);
375 }
376 S.EndMultiColumn();
377
378 // From/To time controls.
379 S.StartStatic(XO("Selection Length"), 0);
380 {
381 S.StartMultiColumn(2, wxALIGN_LEFT);
382 {
383 S.AddPrompt(XXO("C&urrent Length:"));
384
387 S.GetParent(), wxID_ANY,
389 mFormat,
392 .ReadOnly(true)
393 .MenuEnabled(false));
394
395 S.ToolTip(XO("Current length of selection."))
396 /* i18n-hint: changing speed of audio "from" one value "to" another */
397 .Name(XC("from", "change speed"))
398 .Position(wxALIGN_LEFT)
399 .AddWindow(mpFromLengthCtrl);
400
401 S.AddPrompt(XXO("&New Length:"));
402
405 S.GetParent(), ID_ToLength,
407 mFormat,
408 mToLength);
409
410 /* i18n-hint: changing speed of audio "from" one value "to" another */
411 S.Name(XC("to", "change speed"))
412 .Position(wxALIGN_LEFT)
413 .AddWindow(mpToLengthCtrl);
414 }
415 S.EndMultiColumn();
416 }
417 S.EndStatic();
418 }
419 S.EndVerticalLay();
420 return nullptr;
421}
422
424{
425 mbLoopDetect = true;
426
427 if (!mUIParent->TransferDataToWindow())
428 {
429 return false;
430 }
431
432 if (mFromVinyl == kVinyl_NA)
433 {
435 }
436
441
442 // Set from/to Vinyl controls - mFromVinyl must be set first.
443 mpChoice_FromVinyl->SetSelection(mFromVinyl);
444 // Then update to get correct mToVinyl.
445 Update_Vinyl();
446 // Then update ToVinyl control.
447 mpChoice_ToVinyl->SetSelection(mToVinyl);
448
449 // Set From Length control.
450 // Set the format first so we can get sample accuracy.
453
454 mbLoopDetect = false;
455
456 return true;
457}
458
460{
461 // mUIParent->TransferDataFromWindow() loses some precision, so save and restore it.
462 double exactPercent = m_PercentChange;
463 if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
464 {
465 return false;
466 }
467 m_PercentChange = exactPercent;
468
469 // TODO: just visit these effect settings the default way
471 CurrentSettingsGroup(), wxT("TimeFormat"), mFormat.GET());
473 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
474
475 return true;
476}
477
478// EffectChangeSpeed implementation
479
480// Labels are time-scaled linearly inside the affected region, and labels after
481// the region are shifted along according to how the region size changed.
483{
484 RegionTimeWarper warper { mT0, mT1,
485 std::make_unique<LinearTimeWarper>(mT0, mT0,
486 mT1, mT0 + (mT1-mT0)*mFactor) };
487 lt->WarpLabels(warper);
488 return true;
489}
490
491// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
492// and calls libsamplerate code on these blocks.
494 const WaveChannel &track, WaveChannel &outputTrack,
496{
497 //Get the length of the selection (as double). len is
498 //used simple to calculate a progress meter, so it is easier
499 //to make it a double now than it is to do it later
500 auto len = (end - start).as_double();
501
502 // Initiate processing buffers, most likely shorter than
503 // the length of the selection being processed.
504 auto inBufferSize = track.GetMaxBlockSize();
505
506 Floats inBuffer{ inBufferSize };
507
508 // mFactor is at most 100-fold so this shouldn't overflow size_t
509 auto outBufferSize = size_t( mFactor * inBufferSize + 10 );
510 Floats outBuffer{ outBufferSize };
511
512 // Set up the resampling stuff for this track.
513 Resample resample(true, mFactor, mFactor); // constant rate resampling
514
515 //Go through the track one buffer at a time. samplePos counts which
516 //sample the current buffer starts at.
517 bool bResult = true;
518 auto samplePos = start;
519 while (samplePos < end) {
520 //Get a blockSize of samples (smaller than the size of the buffer)
521 auto blockSize = limitSampleBufferSize(
522 track.GetBestBlockSize(samplePos),
523 end - samplePos
524 );
525
526 //Get the samples from the track and put them in the buffer
527 track.GetFloats(inBuffer.get(), samplePos, blockSize);
528
529 const auto results = resample.Process(mFactor,
530 inBuffer.get(),
531 blockSize,
532 ((samplePos + blockSize) >= end),
533 outBuffer.get(),
534 outBufferSize);
535 const auto outgen = results.second;
536
537 if (outgen > 0)
538 outputTrack.Append((samplePtr)outBuffer.get(), floatSample,
539 outgen);
540
541 // Increment samplePos
542 samplePos += results.first;
543
544 // Update the Progress meter
545 if (TrackProgress(mCurTrackNum, (samplePos - start).as_double() / len)) {
546 bResult = false;
547 break;
548 }
549 }
550
551 return bResult;
552}
553
554// handler implementations for EffectChangeSpeed
555
556void EffectChangeSpeed::OnText_PercentChange(wxCommandEvent & WXUNUSED(evt))
557{
558 if (mbLoopDetect)
559 return;
560
561 mpTextCtrl_PercentChange->GetValidator()->TransferFromWindow();
562 UpdateUI();
563
564 mbLoopDetect = true;
567 Update_Vinyl();
569 mbLoopDetect = false;
570}
571
572void EffectChangeSpeed::OnText_Multiplier(wxCommandEvent & WXUNUSED(evt))
573{
574 if (mbLoopDetect)
575 return;
576
577 mpTextCtrl_Multiplier->GetValidator()->TransferFromWindow();
578 m_PercentChange = 100 * (mMultiplier - 1);
579 UpdateUI();
580
581 mbLoopDetect = true;
584 Update_Vinyl();
586 mbLoopDetect = false;
587}
588
589void EffectChangeSpeed::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(evt))
590{
591 if (mbLoopDetect)
592 return;
593
594 m_PercentChange = (double)(mpSlider_PercentChange->GetValue());
595 // Warp positive values to actually go up faster & further than negatives.
596 if (m_PercentChange > 0.0)
598 UpdateUI();
599
600 mbLoopDetect = true;
603 Update_Vinyl();
605 mbLoopDetect = false;
606}
607
608void EffectChangeSpeed::OnChoice_Vinyl(wxCommandEvent & WXUNUSED(evt))
609{
610 // Treat mpChoice_FromVinyl and mpChoice_ToVinyl as one control since we need
611 // both to calculate Percent Change.
612 mFromVinyl = mpChoice_FromVinyl->GetSelection();
613 mToVinyl = mpChoice_ToVinyl->GetSelection();
614 // Use this as the 'preferred' choice.
615 if (mFromVinyl != kVinyl_NA) {
617 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
618 }
619
620 // If mFromVinyl & mToVinyl are set, then there's a NEW percent change.
621 if ((mFromVinyl != kVinyl_NA) && (mToVinyl != kVinyl_NA))
622 {
623 double fromRPM;
624 double toRPM;
625 switch (mFromVinyl) {
626 default:
627 case kVinyl_33AndAThird: fromRPM = 33.0 + (1.0 / 3.0); break;
628 case kVinyl_45: fromRPM = 45.0; break;
629 case kVinyl_78: fromRPM = 78; break;
630 }
631 switch (mToVinyl) {
632 default:
633 case kVinyl_33AndAThird: toRPM = 33.0 + (1.0 / 3.0); break;
634 case kVinyl_45: toRPM = 45.0; break;
635 case kVinyl_78: toRPM = 78; break;
636 }
637 m_PercentChange = ((toRPM * 100.0) / fromRPM) - 100.0;
638 UpdateUI();
639
640 mbLoopDetect = true;
645 }
646 mbLoopDetect = false;
647}
648
649void EffectChangeSpeed::OnTimeCtrl_ToLength(wxCommandEvent & WXUNUSED(evt))
650{
651 if (mbLoopDetect)
652 return;
653
655 // Division by (double) 0.0 is not an error and we want to show "infinite" in
656 // text controls, so take care that we handle infinite values when they occur.
657 m_PercentChange = ((mFromLength * 100.0) / mToLength) - 100.0;
658 UpdateUI();
659
660 mbLoopDetect = true;
661
665 Update_Vinyl();
666
667 mbLoopDetect = false;
668}
669
670void EffectChangeSpeed::OnTimeCtrlUpdate(wxCommandEvent & evt)
671{
674 NumericConverterType_TIME(), evt.GetString()).Internal();
675
677 // Update From/To Length controls (precision has changed).
680}
681
682// helper functions
683
685// Update Text Percent control from percent change.
686{
687 mpTextCtrl_PercentChange->GetValidator()->TransferToWindow();
688}
689
691// Update Multiplier control from percent change.
692{
693 mMultiplier = 1 + (m_PercentChange) / 100.0;
694 mpTextCtrl_Multiplier->GetValidator()->TransferToWindow();
695}
696
698// Update Slider Percent control from percent change.
699{
700 auto unwarped = std::min<double>(m_PercentChange, Percentage.max);
701 if (unwarped > 0.0)
702 // Un-warp values above zero to actually go up to kSliderMax.
703 unwarped = pow(m_PercentChange, (1.0 / kSliderWarp));
704
705 // Caution: m_PercentChange could be infinite.
706 int unwarpedi = (int)(unwarped + 0.5);
707 unwarpedi = std::min<int>(unwarpedi, (int)kSliderMax);
708
709 mpSlider_PercentChange->SetValue(unwarpedi);
710}
711
713// Update Vinyl controls from percent change.
714{
715 // Match Vinyl rpm when within 0.01% of a standard ratio.
716 // Ratios calculated as: ((toRPM / fromRPM) - 1) * 100 * 100
717
718 // Caution: m_PercentChange could be infinite
719 int ratio = (int)((m_PercentChange * 100) + 0.5);
720
721 switch (ratio)
722 {
723 case 0: // toRPM is the same as fromRPM
724 if (mFromVinyl != kVinyl_NA) {
725 mpChoice_ToVinyl->SetSelection(mpChoice_FromVinyl->GetSelection());
726 } else {
727 // Use the last saved option.
729 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl, 0);
730 mpChoice_FromVinyl->SetSelection(mFromVinyl);
731 mpChoice_ToVinyl->SetSelection(mFromVinyl);
732 }
733 break;
734 case 3500:
736 mpChoice_ToVinyl->SetSelection(kVinyl_45);
737 break;
738 case 13400:
740 mpChoice_ToVinyl->SetSelection(kVinyl_78);
741 break;
742 case -2593:
743 mpChoice_FromVinyl->SetSelection(kVinyl_45);
745 break;
746 case 7333:
747 mpChoice_FromVinyl->SetSelection(kVinyl_45);
748 mpChoice_ToVinyl->SetSelection(kVinyl_78);
749 break;
750 case -5727:
751 mpChoice_FromVinyl->SetSelection(kVinyl_78);
753 break;
754 case -4231:
755 mpChoice_FromVinyl->SetSelection(kVinyl_78);
756 mpChoice_ToVinyl->SetSelection(kVinyl_45);
757 break;
758 default:
759 mpChoice_ToVinyl->SetSelection(kVinyl_NA);
760 }
761 // and update variables.
762 mFromVinyl = mpChoice_FromVinyl->GetSelection();
763 mToVinyl = mpChoice_ToVinyl->GetSelection();
764}
765
767// Update ToLength control from percent change.
768{
769 mToLength = (mFromLength * 100.0) / (100.0 + m_PercentChange);
770
771 // Set the format first so we can get sample accuracy.
773 // Negative times do not make sense.
774 // 359999 = 99h:59m:59s which is a little less disturbing than overflow characters
775 // though it may still look a bit strange with some formats.
776 mToLength = std::clamp<double>(mToLength, 0.0, 359999.0);
778}
779
781// Disable OK and Preview if not in sensible range.
782{
785}
wxT("CloseDown"))
END_EVENT_TABLE()
@ 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 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
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:10
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:47
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:114
double mProjectRate
Definition: EffectBase.h:110
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:107
double mT0
Definition: EffectBase.h:113
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:95
void WarpLabels(const TimeWarper &warper)
Definition: LabelTrack.cpp:297
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:640
static bool IsSelectedOrSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:104
static bool IsSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:80
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
Holds a msgid for the translation catalog; may also bind format arguments.
bool Append(constSamplePtr buffer, sampleFormat format, size_t len)
Definition: WaveTrack.cpp:2216
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:129
size_t GetBestBlockSize(sampleCount t) const
A hint for sizing of well aligned fetches.
Definition: WaveTrack.h:850
size_t GetMaxBlockSize() const
Definition: WaveTrack.h:858
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
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.
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 char * end(const char *str) noexcept
Definition: StringUtils.h:106
const Type min
Minimum value.
const Type max
Maximum value.
Externalized state of a plug-in.
Options & ReadOnly(bool enable)