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