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 "LoadEffects.h"
19
20#include <math.h>
21
22#include <wx/choice.h>
23#include <wx/intl.h>
24#include <wx/slider.h>
25
26#include "ConfigInterface.h"
27#include "../LabelTrack.h"
28#include "Prefs.h"
29#include "Resample.h"
30#include "../ShuttleGui.h"
31#include "../SyncLock.h"
32#include "../widgets/NumericTextCtrl.h"
33#include "../widgets/valnum.h"
34
35#include "TimeWarper.h"
36#include "../WaveClip.h"
37#include "../WaveTrack.h"
38
39enum
40{
46};
47
48// the standard vinyl rpm choices
49// If the percent change is not one of these ratios, the choice control gets "n/a".
51{
56};
57
59 XO("33\u2153"),
60 XO("45"),
61 XO("78"),
62 /* i18n-hint: n/a is an English abbreviation meaning "not applicable". */
63 XO("n/a"),
64};
65
66// Soundtouch is not reasonable below -99% or above 3000%.
67
69{
72 > parameters;
73 return parameters;
74}
75
76// We warp the slider to go up to 400%, but user can enter higher values
77static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
78static const double kSliderWarp = 1.30105; // warp power takes max from 100 to 400.
79
80//
81// EffectChangeSpeed
82//
83
85{ XO("Change Speed") };
86
88
89BEGIN_EVENT_TABLE(EffectChangeSpeed, wxEvtHandler)
98
100{
101 Parameters().Reset(*this);
102
103 mFromVinyl = kVinyl_33AndAThird;
104 mToVinyl = kVinyl_33AndAThird;
105 mFromLength = 0.0;
106 mToLength = 0.0;
108 mbLoopDetect = false;
109
110 SetLinearEffectFlag(true);
111}
112
114{
115}
116
117// ComponentInterface implementation
118
120{
121 return Symbol;
122}
123
125{
126 return XO("Changes the speed of a track, also changing its pitch");
127}
128
130{
131 return L"Change_Speed";
132}
133
134
135// EffectDefinitionInterface implementation
136
138{
139 return EffectTypeProcess;
140}
141
143{
144 // To do: externalize state so const_cast isn't needed
145 return const_cast<EffectChangeSpeed&>(*this).DoLoadFactoryDefaults(settings);
146}
147
149{
152
154}
155
156// Effect implementation
157
159{
160 return (m_PercentChange == 0.0);
161}
162
164 const EffectSettings &, double previewLength) const
165{
166 return previewLength * (100.0 + m_PercentChange) / 100.0;
167}
168
170{
171 // The selection might have changed since the last time EffectChangeSpeed
172 // was invoked, so recalculate the Length parameters.
173 mFromLength = mT1 - mT0;
174 return true;
175}
176
178{
179 // Similar to EffectSoundTouch::Process()
180
181 // Iterate over each track.
182 // All needed because this effect needs to introduce
183 // silence in the sync-lock group tracks to keep sync
184 CopyInputTracks(true); // Set up mOutputTracks.
185 bool bGoodResult = true;
186
187 mCurTrackNum = 0;
188 mMaxNewLength = 0.0;
189
190 mFactor = 100.0 / (100.0 + m_PercentChange);
191
192 mOutputTracks->Any().VisitWhile( bGoodResult,
193 [&](LabelTrack *lt) {
195 {
196 if (!ProcessLabelTrack(lt))
197 bGoodResult = false;
198 }
199 },
200 [&](WaveTrack *pOutWaveTrack, const Track::Fallthrough &fallthrough) {
201 if (!pOutWaveTrack->GetSelected())
202 return fallthrough();
203
204 //Get start and end times from track
205 mCurT0 = pOutWaveTrack->GetStartTime();
206 mCurT1 = pOutWaveTrack->GetEndTime();
207
208 //Set the current bounds to whichever left marker is
209 //greater and whichever right marker is less:
210 mCurT0 = wxMax(mT0, mCurT0);
211 mCurT1 = wxMin(mT1, mCurT1);
212
213 // Process only if the right marker is to the right of the left marker
214 if (mCurT1 > mCurT0) {
215 //Transform the marker timepoints to samples
216 auto start = pOutWaveTrack->TimeToLongSamples(mCurT0);
217 auto end = pOutWaveTrack->TimeToLongSamples(mCurT1);
218
219 //ProcessOne() (implemented below) processes a single track
220 if (!ProcessOne(pOutWaveTrack, start, end))
221 bGoodResult = false;
222 }
223 mCurTrackNum++;
224 },
225 [&](Track *t) {
227 t->SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
228 }
229 );
230
231 if (bGoodResult)
232 ReplaceProcessedTracks(bGoodResult);
233
234 // Update selection.
235 mT1 = mT0 + (((mT1 - mT0) * 100.0) / (100.0 + m_PercentChange));
236
237 return bGoodResult;
238}
239
240std::unique_ptr<EffectUIValidator> EffectChangeSpeed::PopulateOrExchange(
242{
243 {
244 wxString formatId;
247 wxT("TimeFormat"), formatId, mFormat.Internal());
249 NumericConverter::TIME, formatId );
250 }
253 wxT("VinylChoice"), mFromVinyl, mFromVinyl);
254
255 S.SetBorder(5);
256
257 S.StartVerticalLay(0);
258 {
259 S.AddSpace(0, 5);
260 S.AddTitle(XO("Change Speed, affecting both Tempo and Pitch"));
261 S.AddSpace(0, 10);
262
263 // Speed multiplier and percent change controls.
264 S.StartMultiColumn(4, wxCENTER);
265 {
267 .Validator<FloatingPointValidator<double>>(
268 3, &mMultiplier,
269 NumValidatorStyle::THREE_TRAILING_ZEROES,
270 Percentage.min / 100.0, ((Percentage.max / 100.0) + 1) )
271 .AddTextBox(XXO("&Speed Multiplier:"), L"", 12);
272
274 .Validator<FloatingPointValidator<double>>(
275 3, &m_PercentChange,
276 NumValidatorStyle::THREE_TRAILING_ZEROES,
278 .AddTextBox(XXO("Percent C&hange:"), L"", 12);
279 }
280 S.EndMultiColumn();
281
282 // Percent change slider.
283 S.StartHorizontalLay(wxEXPAND);
284 {
286 .Name(XO("Percent Change"))
287 .Style(wxSL_HORIZONTAL)
288 .AddSlider( {}, 0, (int)kSliderMax, (int)Percentage.min);
289 }
290 S.EndHorizontalLay();
291
292 // Vinyl rpm controls.
293 S.StartMultiColumn(5, wxCENTER);
294 {
295 /* i18n-hint: "rpm" is an English abbreviation meaning "revolutions per minute".
296 "vinyl" refers to old-fashioned phonograph records */
297 S.AddUnits(XO("Standard Vinyl rpm:"));
298
300 /* i18n-hint: changing speed of audio "from" one value "to" another
301 "rpm" means "revolutions per minute" as on a vinyl record turntable
302 */
303 .Name(XO("From rpm"))
304 .MinSize( { 100, -1 } )
305 /* i18n-hint: changing speed of audio "from" one value "to" another */
306 .AddChoice(XXC("&from", "change speed"), kVinylStrings);
307
309 /* i18n-hint: changing speed of audio "from" one value "to" another
310 "rpm" means "revolutions per minute" as on a vinyl record turntable
311 */
312 .Name(XO("To rpm"))
313 .MinSize( { 100, -1 } )
314 /* i18n-hint: changing speed of audio "from" one value "to" another */
315 .AddChoice(XXC("&to", "change speed"), kVinylStrings);
316 }
317 S.EndMultiColumn();
318
319 // From/To time controls.
320 S.StartStatic(XO("Selection Length"), 0);
321 {
322 S.StartMultiColumn(2, wxALIGN_LEFT);
323 {
324 S.AddPrompt(XXO("C&urrent Length:"));
325
327 NumericTextCtrl(S.GetParent(), wxID_ANY,
329 mFormat,
333 .ReadOnly(true)
334 .MenuEnabled(false));
335
336 S.ToolTip(XO("Current length of selection."))
337 /* i18n-hint: changing speed of audio "from" one value "to" another */
338 .Name(XC("from", "change speed"))
339 .Position(wxALIGN_LEFT)
340 .AddWindow(mpFromLengthCtrl);
341
342 S.AddPrompt(XXO("&New Length:"));
343
345 NumericTextCtrl(S.GetParent(), ID_ToLength,
347 mFormat,
348 mToLength,
350
351 /* i18n-hint: changing speed of audio "from" one value "to" another */
352 S.Name(XC("to", "change speed"))
353 .Position(wxALIGN_LEFT)
354 .AddWindow(mpToLengthCtrl);
355 }
356 S.EndMultiColumn();
357 }
358 S.EndStatic();
359 }
360 S.EndVerticalLay();
361 return nullptr;
362}
363
365{
366 mbLoopDetect = true;
367
368 if (mFromVinyl == kVinyl_NA)
369 {
371 }
372
377
378 // Set from/to Vinyl controls - mFromVinyl must be set first.
379 mpChoice_FromVinyl->SetSelection(mFromVinyl);
380 // Then update to get correct mToVinyl.
381 Update_Vinyl();
382 // Then update ToVinyl control.
383 mpChoice_ToVinyl->SetSelection(mToVinyl);
384
385 // Set From Length control.
386 // Set the format first so we can get sample accuracy.
389
390 mbLoopDetect = false;
391
392 return true;
393}
394
396{
397 // mUIParent->TransferDataFromWindow() loses some precision, so save and restore it.
398 double exactPercent = m_PercentChange;
399 m_PercentChange = exactPercent;
400
401 // TODO: just visit these effect settings the default way
403 CurrentSettingsGroup(), wxT("TimeFormat"), mFormat.Internal());
405 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
406
407 return true;
408}
409
410// EffectChangeSpeed implementation
411
412// Labels are time-scaled linearly inside the affected region, and labels after
413// the region are shifted along according to how the region size changed.
415{
416 RegionTimeWarper warper { mT0, mT1,
417 std::make_unique<LinearTimeWarper>(mT0, mT0,
418 mT1, mT0 + (mT1-mT0)*mFactor) };
419 lt->WarpLabels(warper);
420 return true;
421}
422
423// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
424// and calls libsamplerate code on these blocks.
427{
428 if (track == NULL)
429 return false;
430
431 // initialization, per examples of Mixer::Mixer and
432 // EffectSoundTouch::ProcessOne
433
434
435 auto outputTrack = track->EmptyCopy();
436
437 //Get the length of the selection (as double). len is
438 //used simple to calculate a progress meter, so it is easier
439 //to make it a double now than it is to do it later
440 auto len = (end - start).as_double();
441
442 // Initiate processing buffers, most likely shorter than
443 // the length of the selection being processed.
444 auto inBufferSize = track->GetMaxBlockSize();
445
446 Floats inBuffer{ inBufferSize };
447
448 // mFactor is at most 100-fold so this shouldn't overflow size_t
449 auto outBufferSize = size_t( mFactor * inBufferSize + 10 );
450 Floats outBuffer{ outBufferSize };
451
452 // Set up the resampling stuff for this track.
453 Resample resample(true, mFactor, mFactor); // constant rate resampling
454
455 //Go through the track one buffer at a time. samplePos counts which
456 //sample the current buffer starts at.
457 bool bResult = true;
458 auto samplePos = start;
459 while (samplePos < end) {
460 //Get a blockSize of samples (smaller than the size of the buffer)
461 auto blockSize = limitSampleBufferSize(
462 track->GetBestBlockSize(samplePos),
463 end - samplePos
464 );
465
466 //Get the samples from the track and put them in the buffer
467 track->GetFloats(inBuffer.get(), samplePos, blockSize);
468
469 const auto results = resample.Process(mFactor,
470 inBuffer.get(),
471 blockSize,
472 ((samplePos + blockSize) >= end),
473 outBuffer.get(),
474 outBufferSize);
475 const auto outgen = results.second;
476
477 if (outgen > 0)
478 outputTrack->Append((samplePtr)outBuffer.get(), floatSample,
479 outgen);
480
481 // Increment samplePos
482 samplePos += results.first;
483
484 // Update the Progress meter
485 if (TrackProgress(mCurTrackNum, (samplePos - start).as_double() / len)) {
486 bResult = false;
487 break;
488 }
489 }
490
491 // Flush the output WaveTrack (since it's buffered, too)
492 outputTrack->Flush();
493
494 // Take the output track and insert it in place of the original
495 // sample data
496 double newLength = outputTrack->GetEndTime();
497 if (bResult)
498 {
499 // Silenced samples will be inserted in gaps between clips, so capture where these
500 // gaps are for later deletion
501 std::vector<std::pair<double, double>> gaps;
502 double last = mCurT0;
503 auto clips = track->SortedClipArray();
504 auto front = clips.front();
505 auto back = clips.back();
506 for (auto &clip : clips) {
507 auto st = clip->GetPlayStartTime();
508 auto et = clip->GetPlayEndTime();
509
510 if (st >= mCurT0 || et < mCurT1) {
511 if (mCurT0 < st && clip == front) {
512 gaps.push_back(std::make_pair(mCurT0, st));
513 }
514 else if (last < st && mCurT0 <= last ) {
515 gaps.push_back(std::make_pair(last, st));
516 }
517
518 if (et < mCurT1 && clip == back) {
519 gaps.push_back(std::make_pair(et, mCurT1));
520 }
521 }
522 last = et;
523 }
524
525 LinearTimeWarper warper { mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
526
527 // Take the output track and insert it in place of the original sample data
528 track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), true, true, &warper);
529
530 // Finally, recreate the gaps
531 for (auto gap : gaps) {
532 auto st = track->LongSamplesToTime(track->TimeToLongSamples(gap.first));
533 auto et = track->LongSamplesToTime(track->TimeToLongSamples(gap.second));
534 if (st >= mCurT0 && et <= mCurT1 && st != et)
535 {
536 track->SplitDelete(warper.Warp(st), warper.Warp(et));
537 }
538 }
539 }
540
541 if (newLength > mMaxNewLength)
542 mMaxNewLength = newLength;
543
544 return bResult;
545}
546
547// handler implementations for EffectChangeSpeed
548
549void EffectChangeSpeed::OnText_PercentChange(wxCommandEvent & WXUNUSED(evt))
550{
551 if (mbLoopDetect)
552 return;
553
554 mpTextCtrl_PercentChange->GetValidator()->TransferFromWindow();
555 UpdateUI();
556
557 mbLoopDetect = true;
560 Update_Vinyl();
562 mbLoopDetect = false;
563}
564
565void EffectChangeSpeed::OnText_Multiplier(wxCommandEvent & WXUNUSED(evt))
566{
567 if (mbLoopDetect)
568 return;
569
570 mpTextCtrl_Multiplier->GetValidator()->TransferFromWindow();
571 m_PercentChange = 100 * (mMultiplier - 1);
572 UpdateUI();
573
574 mbLoopDetect = true;
577 Update_Vinyl();
579 mbLoopDetect = false;
580}
581
582void EffectChangeSpeed::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(evt))
583{
584 if (mbLoopDetect)
585 return;
586
587 m_PercentChange = (double)(mpSlider_PercentChange->GetValue());
588 // Warp positive values to actually go up faster & further than negatives.
589 if (m_PercentChange > 0.0)
591 UpdateUI();
592
593 mbLoopDetect = true;
596 Update_Vinyl();
598 mbLoopDetect = false;
599}
600
601void EffectChangeSpeed::OnChoice_Vinyl(wxCommandEvent & WXUNUSED(evt))
602{
603 // Treat mpChoice_FromVinyl and mpChoice_ToVinyl as one control since we need
604 // both to calculate Percent Change.
605 mFromVinyl = mpChoice_FromVinyl->GetSelection();
606 mToVinyl = mpChoice_ToVinyl->GetSelection();
607 // Use this as the 'preferred' choice.
608 if (mFromVinyl != kVinyl_NA) {
610 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
611 }
612
613 // If mFromVinyl & mToVinyl are set, then there's a NEW percent change.
614 if ((mFromVinyl != kVinyl_NA) && (mToVinyl != kVinyl_NA))
615 {
616 double fromRPM;
617 double toRPM;
618 switch (mFromVinyl) {
619 default:
620 case kVinyl_33AndAThird: fromRPM = 33.0 + (1.0 / 3.0); break;
621 case kVinyl_45: fromRPM = 45.0; break;
622 case kVinyl_78: fromRPM = 78; break;
623 }
624 switch (mToVinyl) {
625 default:
626 case kVinyl_33AndAThird: toRPM = 33.0 + (1.0 / 3.0); break;
627 case kVinyl_45: toRPM = 45.0; break;
628 case kVinyl_78: toRPM = 78; break;
629 }
630 m_PercentChange = ((toRPM * 100.0) / fromRPM) - 100.0;
631 UpdateUI();
632
633 mbLoopDetect = true;
638 }
639 mbLoopDetect = false;
640}
641
642void EffectChangeSpeed::OnTimeCtrl_ToLength(wxCommandEvent & WXUNUSED(evt))
643{
644 if (mbLoopDetect)
645 return;
646
648 // Division by (double) 0.0 is not an error and we want to show "infinite" in
649 // text controls, so take care that we handle infinite values when they occur.
650 m_PercentChange = ((mFromLength * 100.0) / mToLength) - 100.0;
651 UpdateUI();
652
653 mbLoopDetect = true;
654
658 Update_Vinyl();
659
660 mbLoopDetect = false;
661}
662
663void EffectChangeSpeed::OnTimeCtrlUpdate(wxCommandEvent & evt)
664{
666 NumericConverter::TIME, evt.GetString() );
667
669 // Update From/To Length controls (precision has changed).
672}
673
674// helper functions
675
677// Update Text Percent control from percent change.
678{
679 mpTextCtrl_PercentChange->GetValidator()->TransferToWindow();
680}
681
683// Update Multiplier control from percent change.
684{
685 mMultiplier = 1 + (m_PercentChange) / 100.0;
686 mpTextCtrl_Multiplier->GetValidator()->TransferToWindow();
687}
688
690// Update Slider Percent control from percent change.
691{
692 auto unwarped = std::min<double>(m_PercentChange, Percentage.max);
693 if (unwarped > 0.0)
694 // Un-warp values above zero to actually go up to kSliderMax.
695 unwarped = pow(m_PercentChange, (1.0 / kSliderWarp));
696
697 // Caution: m_PercentChange could be infinite.
698 int unwarpedi = (int)(unwarped + 0.5);
699 unwarpedi = std::min<int>(unwarpedi, (int)kSliderMax);
700
701 mpSlider_PercentChange->SetValue(unwarpedi);
702}
703
705// Update Vinyl controls from percent change.
706{
707 // Match Vinyl rpm when within 0.01% of a standard ratio.
708 // Ratios calculated as: ((toRPM / fromRPM) - 1) * 100 * 100
709
710 // Caution: m_PercentChange could be infinite
711 int ratio = (int)((m_PercentChange * 100) + 0.5);
712
713 switch (ratio)
714 {
715 case 0: // toRPM is the same as fromRPM
716 if (mFromVinyl != kVinyl_NA) {
717 mpChoice_ToVinyl->SetSelection(mpChoice_FromVinyl->GetSelection());
718 } else {
719 // Use the last saved option.
721 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl, 0);
722 mpChoice_FromVinyl->SetSelection(mFromVinyl);
723 mpChoice_ToVinyl->SetSelection(mFromVinyl);
724 }
725 break;
726 case 3500:
728 mpChoice_ToVinyl->SetSelection(kVinyl_45);
729 break;
730 case 13400:
732 mpChoice_ToVinyl->SetSelection(kVinyl_78);
733 break;
734 case -2593:
735 mpChoice_FromVinyl->SetSelection(kVinyl_45);
737 break;
738 case 7333:
739 mpChoice_FromVinyl->SetSelection(kVinyl_45);
740 mpChoice_ToVinyl->SetSelection(kVinyl_78);
741 break;
742 case -5727:
743 mpChoice_FromVinyl->SetSelection(kVinyl_78);
745 break;
746 case -4231:
747 mpChoice_FromVinyl->SetSelection(kVinyl_78);
748 mpChoice_ToVinyl->SetSelection(kVinyl_45);
749 break;
750 default:
751 mpChoice_ToVinyl->SetSelection(kVinyl_NA);
752 }
753 // and update variables.
754 mFromVinyl = mpChoice_FromVinyl->GetSelection();
755 mToVinyl = mpChoice_ToVinyl->GetSelection();
756}
757
759// Update ToLength control from percent change.
760{
761 mToLength = (mFromLength * 100.0) / (100.0 + m_PercentChange);
762
763 // Set the format first so we can get sample accuracy.
765 // Negative times do not make sense.
766 // 359999 = 99h:59m:59s which is a little less disturbing than overflow characters
767 // though it may still look a bit strange with some formats.
768 mToLength = std::clamp<double>(mToLength, 0.0, 359999.0);
770}
771
773// Disable OK and Preview if not in sensible range.
774{
776}
END_EVENT_TABLE()
static const double kSliderMax
Definition: ChangeSpeed.cpp:77
kVinyl
Definition: ChangeSpeed.cpp:51
@ kVinyl_78
Definition: ChangeSpeed.cpp:54
@ kVinyl_45
Definition: ChangeSpeed.cpp:53
@ kVinyl_33AndAThird
Definition: ChangeSpeed.cpp:52
@ kVinyl_NA
Definition: ChangeSpeed.cpp:55
static const TranslatableStrings kVinylStrings
Definition: ChangeSpeed.cpp:58
@ ID_ToLength
Definition: ChangeSpeed.cpp:45
@ ID_FromVinyl
Definition: ChangeSpeed.cpp:43
@ ID_ToVinyl
Definition: ChangeSpeed.cpp:44
@ ID_Multiplier
Definition: ChangeSpeed.cpp:42
@ ID_PercentChange
Definition: ChangeSpeed.cpp:41
static const double kSliderWarp
Definition: ChangeSpeed.cpp:78
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
EffectType
@ EffectTypeProcess
#define XXC(s, c)
Definition: Internat.h:47
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define XC(s, c)
Definition: Internat.h:37
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:92
#define safenew
Definition: MemoryX.h:10
static const int gap
Definition: MeterPanel.cpp:259
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:23
@ floatSample
Definition: SampleFormat.h:34
char * samplePtr
Definition: SampleFormat.h:49
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:87
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:107
std::shared_ptr< TrackList > mOutputTracks
Definition: EffectBase.h:105
double mProjectRate
Definition: EffectBase.h:99
double mT0
Definition: EffectBase.h:106
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: EffectBase.cpp:236
An Effect that affects both pitch & speed.
Definition: ChangeSpeed.h:26
void OnText_PercentChange(wxCommandEvent &evt)
NumericTextCtrl * mpToLengthCtrl
Definition: ChangeSpeed.h:106
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:30
void OnChoice_Vinyl(wxCommandEvent &evt)
void OnText_Multiplier(wxCommandEvent &evt)
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Add controls to effect panel; always succeeds.
void Update_Slider_PercentChange()
bool DoLoadFactoryDefaults(EffectSettings &settings)
wxTextCtrl * mpTextCtrl_Multiplier
Definition: ChangeSpeed.h:101
bool LoadFactoryDefaults(EffectSettings &settings) const override
Change settings back to "factory default".
bool ProcessOne(WaveTrack *t, sampleCount start, sampleCount end)
void Update_TimeCtrl_ToLength()
wxChoice * mpChoice_ToVinyl
Definition: ChangeSpeed.h:104
wxTextCtrl * mpTextCtrl_PercentChange
Definition: ChangeSpeed.h:100
const EffectParameterMethods & Parameters() const override
Definition: ChangeSpeed.cpp:68
void Update_Text_PercentChange()
bool Process(EffectInstance &instance, EffectSettings &settings) override
Actually do the effect here.
wxChoice * mpChoice_FromVinyl
Definition: ChangeSpeed.h:103
void OnTimeCtrl_ToLength(wxCommandEvent &evt)
void Update_Text_Multiplier()
double mMaxNewLength
Definition: ChangeSpeed.h:83
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.
NumericFormatSymbol mFormat
Definition: ChangeSpeed.h:112
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
void OnTimeCtrlUpdate(wxCommandEvent &evt)
static constexpr EffectParameter Percentage
Definition: ChangeSpeed.h:117
bool ProcessLabelTrack(LabelTrack *t)
wxSlider * mpSlider_PercentChange
Definition: ChangeSpeed.h:102
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
double m_PercentChange
Definition: ChangeSpeed.h:88
TranslatableString GetDescription() const override
bool Init() override
Call once to set up state for whole list of tracks to be processed.
NumericTextCtrl * mpFromLengthCtrl
Definition: ChangeSpeed.h:105
const EffectSettingsManager & GetDefinition() const override
Definition: Effect.cpp:453
void CopyInputTracks(bool allSyncLockSelected=false)
Definition: Effect.cpp:739
bool LoadFactoryDefaults(EffectSettings &settings) const override
Change settings back to "factory default".
Definition: Effect.cpp:280
bool EnableApply(bool enable=true)
Definition: Effect.cpp:613
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:691
Performs effect computation.
Interface for manipulations of an Effect's settings.
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:89
void WarpLabels(const TimeWarper &warper)
Definition: LabelTrack.cpp:287
Linear scaling, initialised by giving two points on the line.
Definition: TimeWarper.h:87
static NumericFormatSymbol DefaultSelectionFormat()
static NumericFormatSymbol LookupFormat(Type type, const wxString &id)
bool SetFormatName(const NumericFormatSymbol &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, 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
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Retrieve samples from a track in floating-point format, regardless of the storage format.
Definition: SampleTrack.h:65
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: SampleTrack.cpp:40
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: SampleTrack.cpp:35
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:73
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:43
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
bool GetSelected() const
Definition: Track.h:461
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:533
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1167
double GetStartTime() const override
Get the time at which the first clip in the track starts.
Definition: WaveTrack.cpp:1997
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1808
size_t GetBestBlockSize(sampleCount t) const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1790
WaveClipPointers SortedClipArray()
Definition: WaveTrack.cpp:2725
double GetEndTime() const override
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:2017
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:917
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
Definition: WaveTrack.cpp:707
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
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:87
const Type min
Minimum value.
Definition: Shuttle.h:30
const Type max
Maximum value.
Definition: Shuttle.h:31
Externalized state of a plug-in.
Options & MenuEnabled(bool enable)
Options & ReadOnly(bool enable)