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/slider.h>
24
25#include "ConfigInterface.h"
26#include "../LabelTrack.h"
27#include "Prefs.h"
28#include "Resample.h"
29#include "../ShuttleGui.h"
30#include "../SyncLock.h"
31#include "../widgets/NumericTextCtrl.h"
32#include "../widgets/valnum.h"
33
34#include "TimeWarper.h"
35#include "../WaveClip.h"
36#include "../WaveTrack.h"
37
38enum
39{
45};
46
47// the standard vinyl rpm choices
48// If the percent change is not one of these ratios, the choice control gets "n/a".
50{
55};
56
58 XO("33\u2153"),
59 XO("45"),
60 XO("78"),
61 /* i18n-hint: n/a is an English abbreviation meaning "not applicable". */
62 XO("n/a"),
63};
64
65// Soundtouch is not reasonable below -99% or above 3000%.
66
68{
71 > parameters;
72 return parameters;
73}
74
75// We warp the slider to go up to 400%, but user can enter higher values
76static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
77static const double kSliderWarp = 1.30105; // warp power takes max from 100 to 400.
78
79//
80// EffectChangeSpeed
81//
82
84{ XO("Change Speed") };
85
87
88BEGIN_EVENT_TABLE(EffectChangeSpeed, wxEvtHandler)
97
99{
100 Parameters().Reset(*this);
101
102 mFromVinyl = kVinyl_33AndAThird;
103 mToVinyl = kVinyl_33AndAThird;
104 mFromLength = 0.0;
105 mToLength = 0.0;
107 mbLoopDetect = false;
108
109 SetLinearEffectFlag(true);
110}
111
113{
114}
115
116// ComponentInterface implementation
117
119{
120 return Symbol;
121}
122
124{
125 return XO("Changes the speed of a track, also changing its pitch");
126}
127
129{
130 return L"Change_Speed";
131}
132
133
134// EffectDefinitionInterface implementation
135
137{
138 return EffectTypeProcess;
139}
140
142{
143 // To do: externalize state so const_cast isn't needed
144 return const_cast<EffectChangeSpeed&>(*this).DoLoadFactoryDefaults(settings);
145}
146
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 const EffectOutputs *)
243{
244 mUIParent = S.GetParent();
245
246 {
247 wxString formatId;
250 wxT("TimeFormat"), formatId, mFormat.Internal());
252 NumericConverter::TIME, formatId );
253 }
256 wxT("VinylChoice"), mFromVinyl, mFromVinyl);
257
258 S.SetBorder(5);
259
260 S.StartVerticalLay(0);
261 {
262 S.AddSpace(0, 5);
263 S.AddTitle(XO("Change Speed, affecting both Tempo and Pitch"));
264 S.AddSpace(0, 10);
265
266 // Speed multiplier and percent change controls.
267 S.StartMultiColumn(4, wxCENTER);
268 {
270 .Validator<FloatingPointValidator<double>>(
271 3, &mMultiplier,
272 NumValidatorStyle::THREE_TRAILING_ZEROES,
273 Percentage.min / 100.0, ((Percentage.max / 100.0) + 1) )
274 .AddTextBox(XXO("&Speed Multiplier:"), L"", 12);
275
277 .Validator<FloatingPointValidator<double>>(
278 3, &m_PercentChange,
279 NumValidatorStyle::THREE_TRAILING_ZEROES,
281 .AddTextBox(XXO("Percent C&hange:"), L"", 12);
282 }
283 S.EndMultiColumn();
284
285 // Percent change slider.
286 S.StartHorizontalLay(wxEXPAND);
287 {
289 .Name(XO("Percent Change"))
290 .Style(wxSL_HORIZONTAL)
291 .AddSlider( {}, 0, (int)kSliderMax, (int)Percentage.min);
292 }
293 S.EndHorizontalLay();
294
295 // Vinyl rpm controls.
296 S.StartMultiColumn(5, wxCENTER);
297 {
298 /* i18n-hint: "rpm" is an English abbreviation meaning "revolutions per minute".
299 "vinyl" refers to old-fashioned phonograph records */
300 S.AddUnits(XO("Standard Vinyl rpm:"));
301
303 /* i18n-hint: changing speed of audio "from" one value "to" another
304 "rpm" means "revolutions per minute" as on a vinyl record turntable
305 */
306 .Name(XO("From rpm"))
307 .MinSize( { 100, -1 } )
308 /* i18n-hint: changing speed of audio "from" one value "to" another */
309 .AddChoice(XXC("&from", "change speed"), kVinylStrings);
310
312 /* i18n-hint: changing speed of audio "from" one value "to" another
313 "rpm" means "revolutions per minute" as on a vinyl record turntable
314 */
315 .Name(XO("To rpm"))
316 .MinSize( { 100, -1 } )
317 /* i18n-hint: changing speed of audio "from" one value "to" another */
318 .AddChoice(XXC("&to", "change speed"), kVinylStrings);
319 }
320 S.EndMultiColumn();
321
322 // From/To time controls.
323 S.StartStatic(XO("Selection Length"), 0);
324 {
325 S.StartMultiColumn(2, wxALIGN_LEFT);
326 {
327 S.AddPrompt(XXO("C&urrent Length:"));
328
330 NumericTextCtrl(S.GetParent(), wxID_ANY,
332 mFormat,
336 .ReadOnly(true)
337 .MenuEnabled(false));
338
339 S.ToolTip(XO("Current length of selection."))
340 /* i18n-hint: changing speed of audio "from" one value "to" another */
341 .Name(XC("from", "change speed"))
342 .Position(wxALIGN_LEFT)
343 .AddWindow(mpFromLengthCtrl);
344
345 S.AddPrompt(XXO("&New Length:"));
346
348 NumericTextCtrl(S.GetParent(), ID_ToLength,
350 mFormat,
351 mToLength,
353
354 /* i18n-hint: changing speed of audio "from" one value "to" another */
355 S.Name(XC("to", "change speed"))
356 .Position(wxALIGN_LEFT)
357 .AddWindow(mpToLengthCtrl);
358 }
359 S.EndMultiColumn();
360 }
361 S.EndStatic();
362 }
363 S.EndVerticalLay();
364 return nullptr;
365}
366
368{
369 mbLoopDetect = true;
370
371 if (!mUIParent->TransferDataToWindow())
372 {
373 return false;
374 }
375
376 if (mFromVinyl == kVinyl_NA)
377 {
379 }
380
385
386 // Set from/to Vinyl controls - mFromVinyl must be set first.
387 mpChoice_FromVinyl->SetSelection(mFromVinyl);
388 // Then update to get correct mToVinyl.
389 Update_Vinyl();
390 // Then update ToVinyl control.
391 mpChoice_ToVinyl->SetSelection(mToVinyl);
392
393 // Set From Length control.
394 // Set the format first so we can get sample accuracy.
397
398 mbLoopDetect = false;
399
400 return true;
401}
402
404{
405 // mUIParent->TransferDataFromWindow() loses some precision, so save and restore it.
406 double exactPercent = m_PercentChange;
407 if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
408 {
409 return false;
410 }
411 m_PercentChange = exactPercent;
412
413 // TODO: just visit these effect settings the default way
415 CurrentSettingsGroup(), wxT("TimeFormat"), mFormat.Internal());
417 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
418
419 return true;
420}
421
422// EffectChangeSpeed implementation
423
424// Labels are time-scaled linearly inside the affected region, and labels after
425// the region are shifted along according to how the region size changed.
427{
428 RegionTimeWarper warper { mT0, mT1,
429 std::make_unique<LinearTimeWarper>(mT0, mT0,
430 mT1, mT0 + (mT1-mT0)*mFactor) };
431 lt->WarpLabels(warper);
432 return true;
433}
434
435// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
436// and calls libsamplerate code on these blocks.
439{
440 if (track == NULL)
441 return false;
442
443 // initialization, per examples of Mixer::Mixer and
444 // EffectSoundTouch::ProcessOne
445
446
447 auto outputTrack = track->EmptyCopy();
448
449 //Get the length of the selection (as double). len is
450 //used simple to calculate a progress meter, so it is easier
451 //to make it a double now than it is to do it later
452 auto len = (end - start).as_double();
453
454 // Initiate processing buffers, most likely shorter than
455 // the length of the selection being processed.
456 auto inBufferSize = track->GetMaxBlockSize();
457
458 Floats inBuffer{ inBufferSize };
459
460 // mFactor is at most 100-fold so this shouldn't overflow size_t
461 auto outBufferSize = size_t( mFactor * inBufferSize + 10 );
462 Floats outBuffer{ outBufferSize };
463
464 // Set up the resampling stuff for this track.
465 Resample resample(true, mFactor, mFactor); // constant rate resampling
466
467 //Go through the track one buffer at a time. samplePos counts which
468 //sample the current buffer starts at.
469 bool bResult = true;
470 auto samplePos = start;
471 while (samplePos < end) {
472 //Get a blockSize of samples (smaller than the size of the buffer)
473 auto blockSize = limitSampleBufferSize(
474 track->GetBestBlockSize(samplePos),
475 end - samplePos
476 );
477
478 //Get the samples from the track and put them in the buffer
479 track->GetFloats(inBuffer.get(), samplePos, blockSize);
480
481 const auto results = resample.Process(mFactor,
482 inBuffer.get(),
483 blockSize,
484 ((samplePos + blockSize) >= end),
485 outBuffer.get(),
486 outBufferSize);
487 const auto outgen = results.second;
488
489 if (outgen > 0)
490 outputTrack->Append((samplePtr)outBuffer.get(), floatSample,
491 outgen);
492
493 // Increment samplePos
494 samplePos += results.first;
495
496 // Update the Progress meter
497 if (TrackProgress(mCurTrackNum, (samplePos - start).as_double() / len)) {
498 bResult = false;
499 break;
500 }
501 }
502
503 // Flush the output WaveTrack (since it's buffered, too)
504 outputTrack->Flush();
505
506 // Take the output track and insert it in place of the original
507 // sample data
508 double newLength = outputTrack->GetEndTime();
509 if (bResult)
510 {
511 // Silenced samples will be inserted in gaps between clips, so capture where these
512 // gaps are for later deletion
513 std::vector<std::pair<double, double>> gaps;
514 double last = mCurT0;
515 auto clips = track->SortedClipArray();
516 auto front = clips.front();
517 auto back = clips.back();
518 for (auto &clip : clips) {
519 auto st = clip->GetPlayStartTime();
520 auto et = clip->GetPlayEndTime();
521
522 if (st >= mCurT0 || et < mCurT1) {
523 if (mCurT0 < st && clip == front) {
524 gaps.push_back(std::make_pair(mCurT0, st));
525 }
526 else if (last < st && mCurT0 <= last ) {
527 gaps.push_back(std::make_pair(last, st));
528 }
529
530 if (et < mCurT1 && clip == back) {
531 gaps.push_back(std::make_pair(et, mCurT1));
532 }
533 }
534 last = et;
535 }
536
537 LinearTimeWarper warper { mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
538
539 // Take the output track and insert it in place of the original sample data
540 track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), true, true, &warper);
541
542 // Finally, recreate the gaps
543 for (auto gap : gaps) {
544 auto st = track->LongSamplesToTime(track->TimeToLongSamples(gap.first));
545 auto et = track->LongSamplesToTime(track->TimeToLongSamples(gap.second));
546 if (st >= mCurT0 && et <= mCurT1 && st != et)
547 {
548 track->SplitDelete(warper.Warp(st), warper.Warp(et));
549 }
550 }
551 }
552
553 if (newLength > mMaxNewLength)
554 mMaxNewLength = newLength;
555
556 return bResult;
557}
558
559// handler implementations for EffectChangeSpeed
560
561void EffectChangeSpeed::OnText_PercentChange(wxCommandEvent & WXUNUSED(evt))
562{
563 if (mbLoopDetect)
564 return;
565
566 mpTextCtrl_PercentChange->GetValidator()->TransferFromWindow();
567 UpdateUI();
568
569 mbLoopDetect = true;
572 Update_Vinyl();
574 mbLoopDetect = false;
575}
576
577void EffectChangeSpeed::OnText_Multiplier(wxCommandEvent & WXUNUSED(evt))
578{
579 if (mbLoopDetect)
580 return;
581
582 mpTextCtrl_Multiplier->GetValidator()->TransferFromWindow();
583 m_PercentChange = 100 * (mMultiplier - 1);
584 UpdateUI();
585
586 mbLoopDetect = true;
589 Update_Vinyl();
591 mbLoopDetect = false;
592}
593
594void EffectChangeSpeed::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(evt))
595{
596 if (mbLoopDetect)
597 return;
598
599 m_PercentChange = (double)(mpSlider_PercentChange->GetValue());
600 // Warp positive values to actually go up faster & further than negatives.
601 if (m_PercentChange > 0.0)
603 UpdateUI();
604
605 mbLoopDetect = true;
608 Update_Vinyl();
610 mbLoopDetect = false;
611}
612
613void EffectChangeSpeed::OnChoice_Vinyl(wxCommandEvent & WXUNUSED(evt))
614{
615 // Treat mpChoice_FromVinyl and mpChoice_ToVinyl as one control since we need
616 // both to calculate Percent Change.
617 mFromVinyl = mpChoice_FromVinyl->GetSelection();
618 mToVinyl = mpChoice_ToVinyl->GetSelection();
619 // Use this as the 'preferred' choice.
620 if (mFromVinyl != kVinyl_NA) {
622 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
623 }
624
625 // If mFromVinyl & mToVinyl are set, then there's a NEW percent change.
626 if ((mFromVinyl != kVinyl_NA) && (mToVinyl != kVinyl_NA))
627 {
628 double fromRPM;
629 double toRPM;
630 switch (mFromVinyl) {
631 default:
632 case kVinyl_33AndAThird: fromRPM = 33.0 + (1.0 / 3.0); break;
633 case kVinyl_45: fromRPM = 45.0; break;
634 case kVinyl_78: fromRPM = 78; break;
635 }
636 switch (mToVinyl) {
637 default:
638 case kVinyl_33AndAThird: toRPM = 33.0 + (1.0 / 3.0); break;
639 case kVinyl_45: toRPM = 45.0; break;
640 case kVinyl_78: toRPM = 78; break;
641 }
642 m_PercentChange = ((toRPM * 100.0) / fromRPM) - 100.0;
643 UpdateUI();
644
645 mbLoopDetect = true;
650 }
651 mbLoopDetect = false;
652}
653
654void EffectChangeSpeed::OnTimeCtrl_ToLength(wxCommandEvent & WXUNUSED(evt))
655{
656 if (mbLoopDetect)
657 return;
658
660 // Division by (double) 0.0 is not an error and we want to show "infinite" in
661 // text controls, so take care that we handle infinite values when they occur.
662 m_PercentChange = ((mFromLength * 100.0) / mToLength) - 100.0;
663 UpdateUI();
664
665 mbLoopDetect = true;
666
670 Update_Vinyl();
671
672 mbLoopDetect = false;
673}
674
675void EffectChangeSpeed::OnTimeCtrlUpdate(wxCommandEvent & evt)
676{
678 NumericConverter::TIME, evt.GetString() );
679
681 // Update From/To Length controls (precision has changed).
684}
685
686// helper functions
687
689// Update Text Percent control from percent change.
690{
691 mpTextCtrl_PercentChange->GetValidator()->TransferToWindow();
692}
693
695// Update Multiplier control from percent change.
696{
697 mMultiplier = 1 + (m_PercentChange) / 100.0;
698 mpTextCtrl_Multiplier->GetValidator()->TransferToWindow();
699}
700
702// Update Slider Percent control from percent change.
703{
704 auto unwarped = std::min<double>(m_PercentChange, Percentage.max);
705 if (unwarped > 0.0)
706 // Un-warp values above zero to actually go up to kSliderMax.
707 unwarped = pow(m_PercentChange, (1.0 / kSliderWarp));
708
709 // Caution: m_PercentChange could be infinite.
710 int unwarpedi = (int)(unwarped + 0.5);
711 unwarpedi = std::min<int>(unwarpedi, (int)kSliderMax);
712
713 mpSlider_PercentChange->SetValue(unwarpedi);
714}
715
717// Update Vinyl controls from percent change.
718{
719 // Match Vinyl rpm when within 0.01% of a standard ratio.
720 // Ratios calculated as: ((toRPM / fromRPM) - 1) * 100 * 100
721
722 // Caution: m_PercentChange could be infinite
723 int ratio = (int)((m_PercentChange * 100) + 0.5);
724
725 switch (ratio)
726 {
727 case 0: // toRPM is the same as fromRPM
728 if (mFromVinyl != kVinyl_NA) {
729 mpChoice_ToVinyl->SetSelection(mpChoice_FromVinyl->GetSelection());
730 } else {
731 // Use the last saved option.
733 CurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl, 0);
734 mpChoice_FromVinyl->SetSelection(mFromVinyl);
735 mpChoice_ToVinyl->SetSelection(mFromVinyl);
736 }
737 break;
738 case 3500:
740 mpChoice_ToVinyl->SetSelection(kVinyl_45);
741 break;
742 case 13400:
744 mpChoice_ToVinyl->SetSelection(kVinyl_78);
745 break;
746 case -2593:
747 mpChoice_FromVinyl->SetSelection(kVinyl_45);
749 break;
750 case 7333:
751 mpChoice_FromVinyl->SetSelection(kVinyl_45);
752 mpChoice_ToVinyl->SetSelection(kVinyl_78);
753 break;
754 case -5727:
755 mpChoice_FromVinyl->SetSelection(kVinyl_78);
757 break;
758 case -4231:
759 mpChoice_FromVinyl->SetSelection(kVinyl_78);
760 mpChoice_ToVinyl->SetSelection(kVinyl_45);
761 break;
762 default:
763 mpChoice_ToVinyl->SetSelection(kVinyl_NA);
764 }
765 // and update variables.
766 mFromVinyl = mpChoice_FromVinyl->GetSelection();
767 mToVinyl = mpChoice_ToVinyl->GetSelection();
768}
769
771// Update ToLength control from percent change.
772{
773 mToLength = (mFromLength * 100.0) / (100.0 + m_PercentChange);
774
775 // Set the format first so we can get sample accuracy.
777 // Negative times do not make sense.
778 // 359999 = 99h:59m:59s which is a little less disturbing than overflow characters
779 // though it may still look a bit strange with some formats.
780 mToLength = std::clamp<double>(mToLength, 0.0, 359999.0);
782}
783
785// Disable OK and Preview if not in sensible range.
786{
789}
wxT("CloseDown"))
END_EVENT_TABLE()
static const double kSliderMax
Definition: ChangeSpeed.cpp:76
kVinyl
Definition: ChangeSpeed.cpp:50
@ kVinyl_78
Definition: ChangeSpeed.cpp:53
@ kVinyl_45
Definition: ChangeSpeed.cpp:52
@ kVinyl_33AndAThird
Definition: ChangeSpeed.cpp:51
@ kVinyl_NA
Definition: ChangeSpeed.cpp:54
static const TranslatableStrings kVinylStrings
Definition: ChangeSpeed.cpp:57
@ ID_ToLength
Definition: ChangeSpeed.cpp:44
@ ID_FromVinyl
Definition: ChangeSpeed.cpp:42
@ ID_ToVinyl
Definition: ChangeSpeed.cpp:43
@ ID_Multiplier
Definition: ChangeSpeed.cpp:41
@ ID_PercentChange
Definition: ChangeSpeed.cpp:40
static const double kSliderWarp
Definition: ChangeSpeed.cpp:77
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
EffectType
@ EffectTypeProcess
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:88
#define safenew
Definition: MemoryX.h:10
static const int gap
Definition: MeterPanel.cpp:253
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
char * samplePtr
Definition: SampleFormat.h:55
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:109
std::shared_ptr< TrackList > mOutputTracks
Definition: EffectBase.h:107
double mProjectRate
Definition: EffectBase.h:101
double mT0
Definition: EffectBase.h:108
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: EffectBase.cpp:241
An Effect that affects both pitch & speed.
Definition: ChangeSpeed.h:26
void OnText_PercentChange(wxCommandEvent &evt)
NumericTextCtrl * mpToLengthCtrl
Definition: ChangeSpeed.h:109
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
OptionalMessage LoadFactoryDefaults(EffectSettings &settings) const override
void OnChoice_Vinyl(wxCommandEvent &evt)
void OnText_Multiplier(wxCommandEvent &evt)
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
void Update_Slider_PercentChange()
OptionalMessage DoLoadFactoryDefaults(EffectSettings &settings)
wxTextCtrl * mpTextCtrl_Multiplier
Definition: ChangeSpeed.h:104
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
bool ProcessOne(WaveTrack *t, sampleCount start, sampleCount end)
void Update_TimeCtrl_ToLength()
wxChoice * mpChoice_ToVinyl
Definition: ChangeSpeed.h:107
wxTextCtrl * mpTextCtrl_PercentChange
Definition: ChangeSpeed.h:103
const EffectParameterMethods & Parameters() const override
Definition: ChangeSpeed.cpp:67
wxWeakRef< wxWindow > mUIParent
Definition: ChangeSpeed.h:82
void Update_Text_PercentChange()
bool Process(EffectInstance &instance, EffectSettings &settings) override
wxChoice * mpChoice_FromVinyl
Definition: ChangeSpeed.h:106
void OnTimeCtrl_ToLength(wxCommandEvent &evt)
void Update_Text_Multiplier()
double mMaxNewLength
Definition: ChangeSpeed.h:86
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:115
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
void OnTimeCtrlUpdate(wxCommandEvent &evt)
static constexpr EffectParameter Percentage
Definition: ChangeSpeed.h:120
bool ProcessLabelTrack(LabelTrack *t)
wxSlider * mpSlider_PercentChange
Definition: ChangeSpeed.h:105
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
double m_PercentChange
Definition: ChangeSpeed.h:91
TranslatableString GetDescription() const override
bool Init() override
NumericTextCtrl * mpFromLengthCtrl
Definition: ChangeSpeed.h:108
const EffectSettingsManager & GetDefinition() const override
Definition: Effect.cpp:455
OptionalMessage LoadFactoryDefaults(EffectSettings &settings) const override
Definition: Effect.cpp:280
void CopyInputTracks(bool allSyncLockSelected=false)
Definition: Effect.cpp:677
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:627
Performs effect computation.
Hold values to send to effect output meters.
Interface for manipulations of an Effect's settings.
static bool EnableApply(wxWindow *parent, bool enable=true)
Enable or disable the Apply button of the dialog that contains parent.
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
void WarpLabels(const TimeWarper &warper)
Definition: LabelTrack.cpp:282
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:71
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: SampleTrack.cpp:47
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: SampleTrack.cpp:42
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:469
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:541
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:1159
double GetStartTime() const override
Get the time at which the first clip in the track starts.
Definition: WaveTrack.cpp:1991
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1800
size_t GetBestBlockSize(sampleCount t) const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1782
WaveClipPointers SortedClipArray()
Definition: WaveTrack.cpp:2720
double GetEndTime() const override
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:2011
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:899
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
Definition: WaveTrack.cpp:689
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
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:86
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)