Audacity  2.2.2
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 #include "../Audacity.h"
17 #include "ChangeSpeed.h"
18 
19 #include <math.h>
20 
21 #include <wx/intl.h>
22 
23 #include "../LabelTrack.h"
24 #include "../Prefs.h"
25 #include "../Project.h"
26 #include "../Resample.h"
27 #include "../ShuttleGui.h"
28 #include "../widgets/valnum.h"
29 
30 #include "TimeWarper.h"
31 #include "../WaveTrack.h"
32 
33 enum
34 {
40 };
41 
42 // the standard vinyl rpm choices
43 // If the percent change is not one of these ratios, the choice control gets "n/a".
44 enum kVinyl
45 {
51 };
52 
53 static const wxChar *kVinylStrings[kNumVinyl] =
54 {
55  wxT("33\u2153"),
56  wxT("45"),
57  wxT("78"),
58  /* i18n-hint: n/a is an English abbreviation meaning "not applicable". */
59  XO("n/a"),
60 };
61 
62 // Soundtouch is not reasonable below -99% or above 3000%.
63 
64 // Define keys, defaults, minimums, and maximums for the effect parameters
65 //
66 // Name Type Key Def Min Max Scale
67 Param( Percentage, double, wxT("Percentage"), 0.0, -99.0, 4900.0, 1 );
68 
69 // We warp the slider to go up to 400%, but user can enter higher values
70 static const double kSliderMax = 100.0; // warped above zero to actually go up to 400%
71 static const double kSliderWarp = 1.30105; // warp power takes max from 100 to 400.
72 
73 //
74 // EffectChangeSpeed
75 //
76 
77 BEGIN_EVENT_TABLE(EffectChangeSpeed, wxEvtHandler)
78  EVT_TEXT(ID_PercentChange, EffectChangeSpeed::OnText_PercentChange)
79  EVT_TEXT(ID_Multiplier, EffectChangeSpeed::OnText_Multiplier)
80  EVT_SLIDER(ID_PercentChange, EffectChangeSpeed::OnSlider_PercentChange)
81  EVT_CHOICE(ID_FromVinyl, EffectChangeSpeed::OnChoice_Vinyl)
82  EVT_CHOICE(ID_ToVinyl, EffectChangeSpeed::OnChoice_Vinyl)
83  EVT_TEXT(ID_ToLength, EffectChangeSpeed::OnTimeCtrl_ToLength)
84  EVT_COMMAND(ID_ToLength, EVT_TIMETEXTCTRL_UPDATED, EffectChangeSpeed::OnTimeCtrlUpdate)
86 
88 {
89  // effect parameters
90  m_PercentChange = DEF_Percentage;
91 
92  mFromVinyl = kVinyl_33AndAThird;
93  mToVinyl = kVinyl_33AndAThird;
94  mFromLength = 0.0;
95  mToLength = 0.0;
96  mFormat = _("hh:mm:ss + milliseconds");
97  mbLoopDetect = false;
98 
99  SetLinearEffectFlag(true);
100 }
101 
103 {
104 }
105 
106 // IdentInterface implementation
107 
109 {
111 }
112 
114 {
115  return _("Change the speed of a track, also changing its pitch");
116 }
117 
119 {
120  return wxT("Change_Speed");
121 }
122 
123 
124 // EffectIdentInterface implementation
125 
127 {
128  return EffectTypeProcess;
129 }
130 
131 // EffectClientInterface implementation
132 
133 bool EffectChangeSpeed::GetAutomationParameters(EffectAutomationParameters & parms)
134 {
135  parms.Write(KEY_Percentage, m_PercentChange);
136 
137  return true;
138 }
139 
140 bool EffectChangeSpeed::SetAutomationParameters(EffectAutomationParameters & parms)
141 {
142  ReadAndVerifyDouble(Percentage);
143 
144  m_PercentChange = Percentage;
145 
146  return true;
147 }
148 
150 {
152  mFormat = _("hh:mm:ss + milliseconds");
153 
155 }
156 
157 // Effect implementation
158 
160 {
161  return (m_PercentChange == 0.0);
162 }
163 
164 double EffectChangeSpeed::CalcPreviewInputLength(double previewLength)
165 {
166  return previewLength * (100.0 + m_PercentChange) / 100.0;
167 }
168 
170 {
171  wxString base = wxT("/Effects/ChangeSpeed/");
172 
173  // Migrate settings from 2.1.0 or before
174 
175  // Already migrated, so bail
176  if (gPrefs->Exists(base + wxT("Migrated")))
177  {
178  return true;
179  }
180 
181  // Load the old "current" settings
182  if (gPrefs->Exists(base))
183  {
184  // Retrieve last used control values
185  gPrefs->Read(base + wxT("PercentChange"), &m_PercentChange, 0);
186 
187  // default format "4" is the same as the Selection toolbar: "hh:mm:ss + milliseconds";
188  gPrefs->Read(base + wxT("TimeFormat"), &mFormat, _("hh:mm:ss + milliseconds"));
189 
190  gPrefs->Read(base + wxT("VinylChoice"), &mFromVinyl, 0);
191  if (mFromVinyl == kVinyl_NA)
192  {
194  }
195 
196  SetPrivateConfig(GetCurrentSettingsGroup(), wxT("TimeFormat"), mFormat);
197  SetPrivateConfig(GetCurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
198 
200 
201  // Do not migrate again
202  gPrefs->Write(base + wxT("Migrated"), true);
203  gPrefs->Flush();
204  }
205 
206  return true;
207 }
208 
210 {
211  // The selection might have changed since the last time EffectChangeSpeed
212  // was invoked, so recalculate the Length parameters.
213  mFromLength = mT1 - mT0;
214  return true;
215 }
216 
218 {
219  // Similar to EffectSoundTouch::Process()
220 
221  // Iterate over each track.
222  // Track::All is needed because this effect needs to introduce
223  // silence in the sync-lock group tracks to keep sync
224  CopyInputTracks(Track::All); // Set up mOutputTracks.
225  bool bGoodResult = true;
226 
227  TrackListIterator iter(mOutputTracks.get());
228  Track* t;
229  mCurTrackNum = 0;
230  mMaxNewLength = 0.0;
231 
232  mFactor = 100.0 / (100.0 + m_PercentChange);
233 
234  t = iter.First();
235  while (t != NULL)
236  {
237  if (t->GetKind() == Track::Label) {
238  if (t->GetSelected() || t->IsSyncLockSelected())
239  {
240  if (!ProcessLabelTrack(static_cast<LabelTrack*>(t))) {
241  bGoodResult = false;
242  break;
243  }
244  }
245  }
246  else if (t->GetKind() == Track::Wave && t->GetSelected())
247  {
248  WaveTrack *pOutWaveTrack = (WaveTrack*)t;
249  //Get start and end times from track
250  mCurT0 = pOutWaveTrack->GetStartTime();
251  mCurT1 = pOutWaveTrack->GetEndTime();
252 
253  //Set the current bounds to whichever left marker is
254  //greater and whichever right marker is less:
255  mCurT0 = wxMax(mT0, mCurT0);
256  mCurT1 = wxMin(mT1, mCurT1);
257 
258  // Process only if the right marker is to the right of the left marker
259  if (mCurT1 > mCurT0) {
260  //Transform the marker timepoints to samples
261  auto start = pOutWaveTrack->TimeToLongSamples(mCurT0);
262  auto end = pOutWaveTrack->TimeToLongSamples(mCurT1);
263 
264  //ProcessOne() (implemented below) processes a single track
265  if (!ProcessOne(pOutWaveTrack, start, end))
266  {
267  bGoodResult = false;
268  break;
269  }
270  }
271  mCurTrackNum++;
272  }
273  else if (t->IsSyncLockSelected())
274  {
275  t->SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
276  }
277 
278  //Iterate to the next track
279  t=iter.Next();
280  }
281 
282  if (bGoodResult)
283  ReplaceProcessedTracks(bGoodResult);
284 
285  // Update selection.
286  mT1 = mT0 + (((mT1 - mT0) * 100.0) / (100.0 + m_PercentChange));
287 
288  return bGoodResult;
289 }
290 
292 {
295 
296  S.SetBorder(5);
297 
298  S.StartVerticalLay(0);
299  {
300  S.AddSpace(0, 5);
301  S.AddTitle(_("Change Speed, affecting both Tempo and Pitch"));
302  S.AddSpace(0, 10);
303 
304  // Speed multiplier and percent change controls.
305  S.StartMultiColumn(4, wxCENTER);
306  {
307  FloatingPointValidator<double> vldMultiplier(3, &mMultiplier, NUM_VAL_THREE_TRAILING_ZEROES);
308  vldMultiplier.SetRange(MIN_Percentage / 100.0, ((MAX_Percentage / 100.0) + 1));
310  S.Id(ID_Multiplier).AddTextBox(_("Speed Multiplier:"), wxT(""), 12);
311  mpTextCtrl_Multiplier->SetValidator(vldMultiplier);
312 
313  FloatingPointValidator<double> vldPercentage(3, &m_PercentChange, NUM_VAL_THREE_TRAILING_ZEROES);
314  vldPercentage.SetRange(MIN_Percentage, MAX_Percentage);
316  S.Id(ID_PercentChange).AddTextBox(_("Percent Change:"), wxT(""), 12);
317  mpTextCtrl_PercentChange->SetValidator(vldPercentage);
318  }
319  S.EndMultiColumn();
320 
321  // Percent change slider.
322  S.StartHorizontalLay(wxEXPAND);
323  {
324  S.SetStyle(wxSL_HORIZONTAL);
326  S.Id(ID_PercentChange).AddSlider( {}, 0, (int)kSliderMax, (int)MIN_Percentage);
327  mpSlider_PercentChange->SetName(_("Percent Change"));
328  }
329  S.EndHorizontalLay();
330 
331  // Vinyl rpm controls.
332  S.StartMultiColumn(5, wxCENTER);
333  {
334  /* i18n-hint: "rpm" is an English abbreviation meaning "revolutions per minute". */
335  S.AddUnits(_("Standard Vinyl rpm:"));
336 
337  wxASSERT(kNumVinyl == WXSIZEOF(kVinylStrings));
338 
339  wxArrayString vinylChoices;
340  for (int i = 0; i < kNumVinyl; i++)
341  {
342  if (i == kVinyl_NA)
343  {
344  vinylChoices.Add(wxGetTranslation(kVinylStrings[i]));
345  }
346  else
347  {
348  vinylChoices.Add(kVinylStrings[i]);
349  }
350  }
351 
353  S.Id(ID_FromVinyl).AddChoice(_("from"), wxT(""), &vinylChoices);
354  mpChoice_FromVinyl->SetName(_("From rpm"));
355  mpChoice_FromVinyl->SetSizeHints(100, -1);
356 
358  S.Id(ID_ToVinyl).AddChoice(_("to"), wxT(""), &vinylChoices);
359  mpChoice_ToVinyl->SetName(_("To rpm"));
360  mpChoice_ToVinyl->SetSizeHints(100, -1);
361  }
362  S.EndMultiColumn();
363 
364  // From/To time controls.
365  S.StartStatic(_("Selection Length"), 0);
366  {
367  S.StartMultiColumn(2, wxALIGN_LEFT);
368  {
369  S.AddPrompt(_("Current Length:"));
370 
373  S.GetParent(),
374  wxID_ANY,
375  mFormat,
376  mFromLength,
377  mProjectRate);
378 
379  mpFromLengthCtrl->SetName(_("from"));
380  mpFromLengthCtrl->SetToolTip(_("Current length of selection."));
383  S.AddWindow(mpFromLengthCtrl, wxALIGN_LEFT);
384 
385  S.AddPrompt(_("New Length:"));
386 
389  S.GetParent(),
390  ID_ToLength,
391  mFormat,
392  mToLength,
393  mProjectRate);
394 
395  mpToLengthCtrl->SetName(_("to"));
397  S.AddWindow(mpToLengthCtrl, wxALIGN_LEFT);
398  }
399  S.EndMultiColumn();
400  }
401  S.EndStatic();
402  }
403  S.EndVerticalLay();
404 }
405 
407 {
408  mbLoopDetect = true;
409 
410  if (!mUIParent->TransferDataToWindow())
411  {
412  return false;
413  }
414 
415  if (mFromVinyl == kVinyl_NA)
416  {
418  }
419 
424 
425  // Set from/to Vinyl controls - mFromVinyl must be set first.
426  mpChoice_FromVinyl->SetSelection(mFromVinyl);
427  // Then update to get correct mToVinyl.
428  Update_Vinyl();
429  // Then update ToVinyl control.
430  mpChoice_ToVinyl->SetSelection(mToVinyl);
431 
432  // Set From Length control.
433  // Set the format first so we can get sample accuracy.
436 
437  mbLoopDetect = false;
438 
439  return true;
440 }
441 
443 {
444  // mUIParent->TransferDataFromWindow() loses some precision, so save and restore it.
445  double exactPercent = m_PercentChange;
446  if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
447  {
448  return false;
449  }
450  m_PercentChange = exactPercent;
451 
452  SetPrivateConfig(GetCurrentSettingsGroup(), wxT("TimeFormat"), mFormat);
453  SetPrivateConfig(GetCurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
454 
455  return true;
456 }
457 
458 // EffectChangeSpeed implementation
459 
460 // Labels are time-scaled linearly inside the affected region, and labels after
461 // the region are shifted along according to how the region size changed.
463 {
464  RegionTimeWarper warper { mT0, mT1,
465  std::make_unique<LinearTimeWarper>(mT0, mT0,
466  mT1, mT0 + (mT1-mT0)*mFactor) };
467  lt->WarpLabels(warper);
468  return true;
469 }
470 
471 // ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
472 // and calls libsamplerate code on these blocks.
474  sampleCount start, sampleCount end)
475 {
476  if (track == NULL)
477  return false;
478 
479  // initialization, per examples of Mixer::Mixer and
480  // EffectSoundTouch::ProcessOne
481 
482  auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),
483  track->GetRate());
484 
485  //Get the length of the selection (as double). len is
486  //used simple to calculate a progress meter, so it is easier
487  //to make it a double now than it is to do it later
488  auto len = (end - start).as_double();
489 
490  // Initiate processing buffers, most likely shorter than
491  // the length of the selection being processed.
492  auto inBufferSize = track->GetMaxBlockSize();
493 
494  Floats inBuffer{ inBufferSize };
495 
496  // mFactor is at most 100-fold so this shouldn't overflow size_t
497  auto outBufferSize = size_t( mFactor * inBufferSize + 10 );
498  Floats outBuffer{ outBufferSize };
499 
500  // Set up the resampling stuff for this track.
501  Resample resample(true, mFactor, mFactor); // constant rate resampling
502 
503  //Go through the track one buffer at a time. samplePos counts which
504  //sample the current buffer starts at.
505  bool bResult = true;
506  auto samplePos = start;
507  while (samplePos < end) {
508  //Get a blockSize of samples (smaller than the size of the buffer)
509  auto blockSize = limitSampleBufferSize(
510  track->GetBestBlockSize(samplePos),
511  end - samplePos
512  );
513 
514  //Get the samples from the track and put them in the buffer
515  track->Get((samplePtr) inBuffer.get(), floatSample, samplePos, blockSize);
516 
517  const auto results = resample.Process(mFactor,
518  inBuffer.get(),
519  blockSize,
520  ((samplePos + blockSize) >= end),
521  outBuffer.get(),
522  outBufferSize);
523  const auto outgen = results.second;
524 
525  if (outgen > 0)
526  outputTrack->Append((samplePtr)outBuffer.get(), floatSample,
527  outgen);
528 
529  // Increment samplePos
530  samplePos += results.first;
531 
532  // Update the Progress meter
533  if (TrackProgress(mCurTrackNum, (samplePos - start).as_double() / len)) {
534  bResult = false;
535  break;
536  }
537  }
538 
539  // Flush the output WaveTrack (since it's buffered, too)
540  outputTrack->Flush();
541 
542  // Take the output track and insert it in place of the original
543  // sample data
544  double newLength = outputTrack->GetEndTime();
545  if (bResult)
546  {
547  LinearTimeWarper warper { mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
548  track->ClearAndPaste(
549  mCurT0, mCurT1, outputTrack.get(), true, false, &warper);
550  }
551 
552  if (newLength > mMaxNewLength)
553  mMaxNewLength = newLength;
554 
555  return bResult;
556 }
557 
558 // handler implementations for EffectChangeSpeed
559 
560 void EffectChangeSpeed::OnText_PercentChange(wxCommandEvent & WXUNUSED(evt))
561 {
562  if (mbLoopDetect)
563  return;
564 
565  mpTextCtrl_PercentChange->GetValidator()->TransferFromWindow();
566  UpdateUI();
567 
568  mbLoopDetect = true;
571  Update_Vinyl();
573  mbLoopDetect = false;
574 }
575 
576 void EffectChangeSpeed::OnText_Multiplier(wxCommandEvent & WXUNUSED(evt))
577 {
578  if (mbLoopDetect)
579  return;
580 
581  mpTextCtrl_Multiplier->GetValidator()->TransferFromWindow();
582  m_PercentChange = 100 * (mMultiplier - 1);
583  UpdateUI();
584 
585  mbLoopDetect = true;
588  Update_Vinyl();
590  mbLoopDetect = false;
591 }
592 
593 void EffectChangeSpeed::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(evt))
594 {
595  if (mbLoopDetect)
596  return;
597 
598  m_PercentChange = (double)(mpSlider_PercentChange->GetValue());
599  // Warp positive values to actually go up faster & further than negatives.
600  if (m_PercentChange > 0.0)
601  m_PercentChange = pow(m_PercentChange, kSliderWarp);
602  UpdateUI();
603 
604  mbLoopDetect = true;
607  Update_Vinyl();
609  mbLoopDetect = false;
610 }
611 
612 void EffectChangeSpeed::OnChoice_Vinyl(wxCommandEvent & WXUNUSED(evt))
613 {
614  // Treat mpChoice_FromVinyl and mpChoice_ToVinyl as one control since we need
615  // both to calculate Percent Change.
616  mFromVinyl = mpChoice_FromVinyl->GetSelection();
617  mToVinyl = mpChoice_ToVinyl->GetSelection();
618  // Use this as the 'preferred' choice.
619  if (mFromVinyl != kVinyl_NA) {
620  SetPrivateConfig(GetCurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl);
621  }
622 
623  // If mFromVinyl & mToVinyl are set, then there's a NEW percent change.
624  if ((mFromVinyl != kVinyl_NA) && (mToVinyl != kVinyl_NA))
625  {
626  double fromRPM;
627  double toRPM;
628  switch (mFromVinyl) {
629  default:
630  case kVinyl_33AndAThird: fromRPM = 33.0 + (1.0 / 3.0); break;
631  case kVinyl_45: fromRPM = 45.0; break;
632  case kVinyl_78: fromRPM = 78; break;
633  }
634  switch (mToVinyl) {
635  default:
636  case kVinyl_33AndAThird: toRPM = 33.0 + (1.0 / 3.0); break;
637  case kVinyl_45: toRPM = 45.0; break;
638  case kVinyl_78: toRPM = 78; break;
639  }
640  m_PercentChange = ((toRPM * 100.0) / fromRPM) - 100.0;
641  UpdateUI();
642 
643  mbLoopDetect = true;
648  }
649  mbLoopDetect = false;
650 }
651 
652 void EffectChangeSpeed::OnTimeCtrl_ToLength(wxCommandEvent & WXUNUSED(evt))
653 {
654  if (mbLoopDetect)
655  return;
656 
658  // Division by (double) 0.0 is not an error and we want to show "infinite" in
659  // text controls, so take care that we handle infinite values when they occur.
660  m_PercentChange = ((mFromLength * 100.0) / mToLength) - 100.0;
661  UpdateUI();
662 
663  mbLoopDetect = true;
664 
668  Update_Vinyl();
669 
670  mbLoopDetect = false;
671 }
672 
673 void EffectChangeSpeed::OnTimeCtrlUpdate(wxCommandEvent & evt)
674 {
675  mFormat = evt.GetString();
676 
678  // Update From/To Length controls (precision has changed).
681 }
682 
683 // helper functions
684 
686 // Update Text Percent control from percent change.
687 {
688  mpTextCtrl_PercentChange->GetValidator()->TransferToWindow();
689 }
690 
692 // Update Multiplier control from percent change.
693 {
694  mMultiplier = 1 + (m_PercentChange) / 100.0;
695  mpTextCtrl_Multiplier->GetValidator()->TransferToWindow();
696 }
697 
699 // Update Slider Percent control from percent change.
700 {
701  auto unwarped = std::min<double>(m_PercentChange, MAX_Percentage);
702  if (unwarped > 0.0)
703  // Un-warp values above zero to actually go up to kSliderMax.
704  unwarped = pow(m_PercentChange, (1.0 / kSliderWarp));
705 
706  // Caution: m_PercentChange could be infinite.
707  int unwarpedi = (int)(unwarped + 0.5);
708  unwarpedi = std::min<int>(unwarpedi, (int)kSliderMax);
709 
710  mpSlider_PercentChange->SetValue(unwarpedi);
711 }
712 
714 // Update Vinyl controls from percent change.
715 {
716  // Match Vinyl rpm when within 0.01% of a standard ratio.
717  // Ratios calculated as: ((toRPM / fromRPM) - 1) * 100 * 100
718 
719  // Caution: m_PercentChange could be infinite
720  int ratio = (int)((m_PercentChange * 100) + 0.5);
721 
722  switch (ratio)
723  {
724  case 0: // toRPM is the same as fromRPM
725  if (mFromVinyl != kVinyl_NA) {
726  mpChoice_ToVinyl->SetSelection(mpChoice_FromVinyl->GetSelection());
727  } else {
728  // Use the last saved option.
729  GetPrivateConfig(GetCurrentSettingsGroup(), wxT("VinylChoice"), mFromVinyl, 0);
730  mpChoice_FromVinyl->SetSelection(mFromVinyl);
731  mpChoice_ToVinyl->SetSelection(mFromVinyl);
732  }
733  break;
734  case 3500:
735  mpChoice_FromVinyl->SetSelection(kVinyl_33AndAThird);
736  mpChoice_ToVinyl->SetSelection(kVinyl_45);
737  break;
738  case 13400:
739  mpChoice_FromVinyl->SetSelection(kVinyl_33AndAThird);
740  mpChoice_ToVinyl->SetSelection(kVinyl_78);
741  break;
742  case -2593:
743  mpChoice_FromVinyl->SetSelection(kVinyl_45);
744  mpChoice_ToVinyl->SetSelection(kVinyl_33AndAThird);
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);
752  mpChoice_ToVinyl->SetSelection(kVinyl_33AndAThird);
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 = TrapDouble(mToLength, 0.0, 359999.0);
778 }
779 
781 // Disable OK and Preview if not in sensible range.
782 {
783  EnableApply(m_PercentChange >= MIN_Percentage && m_PercentChange <= MAX_Percentage);
784 }
wxString ManualPage() override
double mT1
Definition: Effect.h:460
bool SaveUserPreset(const wxString &name) override
Definition: Effect.cpp:615
void Update_Slider_PercentChange()
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:88
bool TrackProgress(int whichTrack, double frac, const wxString &=wxEmptyString)
Definition: Effect.cpp:1978
static const double kSliderMax
Definition: ChangeSpeed.cpp:70
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:366
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true) const
Definition: WaveTrack.cpp:1950
bool GetPrivateConfig(const wxString &group, const wxString &key, wxString &value, const wxString &defval=wxEmptyString) override
Definition: Effect.cpp:910
wxString GetCurrentSettingsGroup() override
Definition: Effect.cpp:814
void CopyInputTracks()
Definition: Effect.cpp:2029
wxWindow * AddWindow(wxWindow *pWindow, int Flags=wxALIGN_CENTRE|wxALL)
Definition: ShuttleGui.cpp:257
bool TransferDataToWindow() override
void SetFormatName(const wxString &formatName)
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: Effect.cpp:2160
void SetReadOnly(bool readOnly=true)
void OnTimeCtrlUpdate(wxCommandEvent &evt)
void EndMultiColumn()
wxTextCtrl * mpTextCtrl_Multiplier
Definition: ChangeSpeed.h:106
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:759
wxSlider * mpSlider_PercentChange
Definition: ChangeSpeed.h:107
void Update_TimeCtrl_ToLength()
void EnableMenu(bool enable=true)
double m_PercentChange
Definition: ChangeSpeed.h:93
#define XO(s)
Definition: Internat.h:30
bool ProcessOne(WaveTrack *t, sampleCount start, sampleCount end)
An Effect that affects both pitch & speed.
Definition: ChangeSpeed.h:30
wxChoice * mpChoice_FromVinyl
Definition: ChangeSpeed.h:108
wxString GetSymbol() override
size_t GetBestBlockSize(sampleCount t) const
Definition: WaveTrack.cpp:1586
bool SetPrivateConfig(const wxString &group, const wxString &key, const wxString &value) override
Definition: Effect.cpp:935
No change before the specified region; during the region, warp according to the given warper; after t...
Definition: TimeWarper.h:192
#define safenew
Definition: Audacity.h:223
static const wxChar * kVinylStrings[kNumVinyl]
Definition: ChangeSpeed.cpp:53
wxTextCtrl * mpTextCtrl_PercentChange
Definition: ChangeSpeed.h:105
void EndHorizontalLay()
Definition: ShuttleGui.cpp:975
bool TransferDataFromWindow() override
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:114
void PopulateOrExchange(ShuttleGui &S) override
void AddUnits(const wxString &Prompt)
Left aligned text string.
Definition: ShuttleGui.cpp:229
void AddPrompt(const wxString &Prompt)
Right aligned text string.
Definition: ShuttleGui.cpp:215
void Update_Text_PercentChange()
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper, LinearInputRateSlideTimeWarper, LinearOutputRateSlideTimeWarper, LinearInputInverseRateTimeWarper, GeometricInputRateTimeWarper, GeometricOutputRateTimeWarper classes.
NumericTextCtrl * mpFromLengthCtrl
Definition: ChangeSpeed.h:110
void EndVerticalLay()
Definition: ShuttleGui.cpp:991
static const double kSliderWarp
Definition: ChangeSpeed.cpp:71
Linear scaling, initialised by giving two points on the line.
Definition: TimeWarper.h:86
Param(Percentage, double, wxT("Percentage"), 0.0,-99.0, 4900.0, 1)
bool Init() override
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:493
virtual ~EffectChangeSpeed()
wxWindow * GetParent()
Definition: ShuttleGui.h:259
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:966
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:998
void WarpLabels(const TimeWarper &warper)
Definition: LabelTrack.cpp:256
wxChoice * AddChoice(const wxString &Prompt, const wxString &Selected, const wxArrayString *pChoices)
Definition: ShuttleGui.cpp:331
void OnChoice_Vinyl(wxCommandEvent &evt)
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
ShuttleGui & Id(int id)
void OnTimeCtrl_ToLength(wxCommandEvent &evt)
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:67
void SetStyle(int Style)
Definition: ShuttleGui.h:252
#define ReadAndVerifyDouble(name)
Definition: Effect.h:787
void AddTitle(const wxString &Prompt)
Centred text string.
Definition: ShuttleGui.cpp:243
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1604
void SetValue(double newValue)
wxChoice * mpChoice_ToVinyl
Definition: ChangeSpeed.h:109
std::unique_ptr< WaveTrack > NewWaveTrack(sampleFormat format=(sampleFormat) 0, double rate=0)
Definition: WaveTrack.cpp:78
wxWindow * mUIParent
Definition: Effect.h:471
An iterator for a TrackList.
Definition: Track.h:339
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
double TrapDouble(double x, double min, double max)
Definition: Effect.h:724
double mProjectRate
Definition: Effect.h:453
TrackFactory * mFactory
Definition: Effect.h:456
void OnText_Multiplier(wxCommandEvent &evt)
double CalcPreviewInputLength(double previewLength) override
#define CHANGESPEED_PLUGIN_SYMBOL
Definition: ChangeSpeed.h:28
EffectType GetType() override
Interface to libsoxr.
Definition: Resample.h:30
double mMaxNewLength
Definition: ChangeSpeed.h:88
bool CheckWhetherSkipEffect() override
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1822
sampleFormat GetSampleFormat() const
Definition: WaveTrack.h:140
bool LoadFactoryDefaults() override
Definition: Effect.cpp:651
bool GetAutomationParameters(EffectAutomationParameters &parms) override
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:701
bool Startup() override
void OnSlider_PercentChange(wxCommandEvent &evt)
bool ProcessLabelTrack(LabelTrack *t)
double GetEndTime() const
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:1852
void OnText_PercentChange(wxCommandEvent &evt)
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:95
bool LoadFactoryDefaults() override
wxString GetDescription() override
kVinyl
Definition: ChangeSpeed.cpp:44
END_EVENT_TABLE()
wxSizerItem * AddSpace(int width, int height)
double GetRate() const
Definition: WaveTrack.cpp:397
void SetBorder(int Border)
Definition: ShuttleGui.h:251
std::shared_ptr< TrackList > mOutputTracks
Definition: Effect.h:458
void Update_Text_Multiplier()
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1879
double mT0
Definition: Effect.h:459
double GetStartTime() const
Get the time at which the first clip in the track starts.
Definition: WaveTrack.cpp:1832
bool Process() override
NumericTextCtrl * mpToLengthCtrl
Definition: ChangeSpeed.h:111
wxSlider * AddSlider(const wxString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:456
bool SetAutomationParameters(EffectAutomationParameters &parms) override
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:982