Audacity 3.2.0
TrackMenus.cpp
Go to the documentation of this file.
1#include "../CommonCommandFlags.h"
2#include "LabelTrack.h"
3#include "MixAndRender.h"
4
5#include "Prefs.h"
6#include "Project.h"
7#include "ProjectAudioIO.h"
8#include "ProjectHistory.h"
9#include "ProjectRate.h"
10#include "../ProjectSettings.h"
11#include "PluginManager.h"
12#include "ProjectStatus.h"
13#include "../ProjectWindows.h"
14#include "../SelectUtilities.h"
15#include "ShuttleGui.h"
16#include "SyncLock.h"
17#include "TrackFocus.h"
18#include "../TrackPanel.h"
19#include "../TrackUtilities.h"
20#include "UndoManager.h"
21#include "WaveClip.h"
22#include "ViewInfo.h"
23#include "Viewport.h"
24#include "WaveTrack.h"
25#include "CommandContext.h"
26#include "EffectManager.h"
27#include "../effects/EffectUI.h"
28#include "QualitySettings.h"
29#include "../tracks/playabletrack/wavetrack/ui/WaveTrackControls.h"
30#include "../toolbars/ToolManager.h"
31#include "../widgets/ASlider.h"
32#include "AudacityMessageBox.h"
33#include "ProgressDialog.h"
34#include "DoEffect.h"
35
36#include <wx/combobox.h>
37
38#ifdef EXPERIMENTAL_SCOREALIGN
39#include "../effects/ScoreAlignDialog.h"
40#include "audioreader.h"
41#include "scorealign.h"
42#include "scorealign-glue.h"
43#endif /* EXPERIMENTAL_SCOREALIGN */
44
45// private helper classes and functions
46namespace {
47
48void DoMixAndRender(AudacityProject &project, bool toNewTrack)
49{
51 auto &trackFactory = WaveTrackFactory::Get(project);
52 auto rate = ProjectRate::Get(project).GetRate();
53 auto defaultFormat = QualitySettings::SampleFormatChoice();
54 auto &trackPanel = TrackPanel::Get(project);
55
56 auto trackRange = tracks.Selected<WaveTrack>();
57 auto newTrack = ::MixAndRender(trackRange.Filter<const WaveTrack>(),
58 Mixer::WarpOptions{ tracks.GetOwner() },
59 tracks.MakeUniqueTrackName(_("Mix")),
60 &trackFactory, rate, defaultFormat, 0.0, 0.0);
61
62 if (newTrack) {
63 // Remove originals, get stats on what tracks were mixed
64
65 // But before removing, determine the first track after the removal
66 auto last = *trackRange.rbegin();
67 auto insertionPoint = * ++ tracks.Find(last);
68
69 auto selectedCount = trackRange.size();
70 if (!toNewTrack) {
71 // Beware iterator invalidation!
72 while (!trackRange.empty())
73 tracks.Remove(**trackRange.first++);
74 }
75
76 // Add new tracks
77 const bool stereo = newTrack->NChannels() > 1;
78 const auto firstName = newTrack->GetName();
79 tracks.Add(newTrack);
80 const auto pNewTrack = *tracks.Any<WaveTrack>().rbegin();
81
82 // Bug 2218, remember more things...
83 if (selectedCount >= 1)
84 pNewTrack->SetSelected(!toNewTrack);
85
86 // Permute the tracks as needed
87 // The new track appears after the old tracks (or where the old tracks
88 // had been) so that they are in the same sync-lock group
89 if (insertionPoint) {
90 std::vector<Track *> arr;
91 arr.reserve(tracks.Size());
92 size_t iBegin = 0, ii = 0;
93 for (const auto pTrack : tracks) {
94 arr.push_back(pTrack);
95 if (pTrack == insertionPoint)
96 iBegin = ii;
97 ++ii;
98 }
99 const auto end = arr.end(),
100 mid = end - 1;
101 std::rotate(arr.begin() + iBegin, mid, end);
102 tracks.Permute(arr);
103 }
104
105 // Smart history/undo message
106 if (selectedCount == 1) {
107 auto msg = XO("Rendered all audio in track '%s'").Format(firstName);
108 /* i18n-hint: Convert the audio into a more usable form, so apply
109 * panning and amplification and write to some external file.*/
110 ProjectHistory::Get( project ).PushState(msg, XO("Render"));
111 }
112 else {
113 auto msg = (stereo
114 ? XO("Mixed and rendered %d tracks into one new stereo track")
115 : XO("Mixed and rendered %d tracks into one new mono track")
116 )
117 .Format((int)selectedCount);
118 ProjectHistory::Get(project).PushState(msg, XO("Mix and Render"));
119 }
120
121 trackPanel.SetFocus();
122 TrackFocus::Get(project).Set(pNewTrack);
123 Viewport::Get(project).ShowTrack(*pNewTrack);
124 }
125}
126
127void DoPanTracks(AudacityProject &project, float PanValue)
128{
129 auto &tracks = TrackList::Get( project );
130
131 // count selected wave tracks
132 const auto range = tracks.Any< WaveTrack >();
133 const auto selectedRange = range + &Track::IsSelected;
134 auto count = selectedRange.size();
135
136 // iter through them, all if none selected.
137 for (auto left : count == 0 ? range : selectedRange )
138 left->SetPan( PanValue );
139
140 auto flags = UndoPush::NONE;
142 /*i18n-hint: One or more audio tracks have been panned*/
143 .PushState(XO("Panned audio track(s)"), XO("Pan Track"), flags);
144 flags = flags | UndoPush::CONSOLIDATE;
145}
146
147enum {
153 // The next two are only in one subMenu, so more easily handled at the end.
157
158static const std::vector< ComponentInterfaceSymbol >
159&alignLabels() { static std::vector< ComponentInterfaceSymbol > symbols{
160 { wxT("StartToZero"), XXO("Start to &Zero") },
161 { wxT("StartToSelStart"), XXO("Start to &Cursor/Selection Start") },
162 { wxT("StartToSelEnd"), XXO("Start to Selection &End") },
163 { wxT("EndToSelStart"), XXO("End to Cu&rsor/Selection Start") },
164 { wxT("EndToSelEnd"), XXO("End to Selection En&d") },
165}; return symbols; }
166
167const size_t kAlignLabelsCount(){ return alignLabels().size(); }
168
169void DoAlign(AudacityProject &project, int index, bool moveSel)
170{
171 auto &tracks = TrackList::Get( project );
172 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
173 auto &viewport = Viewport::Get(project);
174
175 TranslatableString action, shortAction;
176 double delta = 0.0;
177 double newPos = -1.0;
178
179 auto trackRange = tracks.Selected<AudioTrack>();
180
181 auto FindOffset =
182 [](const Track *pTrack) { return pTrack->GetStartTime(); };
183
184 auto firstTrackOffset = [&]{ return FindOffset( *trackRange.begin() ); };
185 auto minOffset = [&]{ return trackRange.min( FindOffset ); };
186 auto avgOffset = [&]{
187 return trackRange.sum( FindOffset ) /
188 std::max( size_t(1), trackRange.size() ); };
189
190 auto maxEndOffset = [&]{
191 return std::max(0.0, trackRange.max(&Track::GetEndTime)); };
192
193 switch(index) {
194 case kAlignStartZero:
195 delta = -minOffset();
196 action = moveSel
197 /* i18n-hint: In this and similar messages describing editing actions,
198 the starting or ending points of tracks are re-"aligned" to other
199 times, and the time selection may be "moved" too. The first
200 noun -- "start" in this example -- is the object of a verb (not of
201 an implied preposition "from"). */
202 ? XO("Aligned/Moved start to zero")
203 : XO("Aligned start to zero");
204 shortAction = moveSel
205 /* i18n-hint: This and similar messages give shorter descriptions of
206 the aligning and moving editing actions */
207 ? XO("Align/Move Start")
208 : XO("Align Start");
209 break;
211 delta = selectedRegion.t0() - minOffset();
212 action = moveSel
213 ? XO("Aligned/Moved start to cursor/selection start")
214 : XO("Aligned start to cursor/selection start");
215 shortAction = moveSel
216 ? XO("Align/Move Start")
217 : XO("Align Start");
218 break;
220 delta = selectedRegion.t1() - minOffset();
221 action = moveSel
222 ? XO("Aligned/Moved start to selection end")
223 : XO("Aligned start to selection end");
224 shortAction = moveSel
225 ? XO("Align/Move Start")
226 : XO("Align Start");
227 break;
229 delta = selectedRegion.t0() - maxEndOffset();
230 action = moveSel
231 ? XO("Aligned/Moved end to cursor/selection start")
232 : XO("Aligned end to cursor/selection start");
233 shortAction =
234 moveSel
235 ? XO("Align/Move End")
236 : XO("Align End");
237 break;
238 case kAlignEndSelEnd:
239 delta = selectedRegion.t1() - maxEndOffset();
240 action = moveSel
241 ? XO("Aligned/Moved end to selection end")
242 : XO("Aligned end to selection end");
243 shortAction =
244 moveSel
245 ? XO("Align/Move End")
246 : XO("Align End");
247 break;
248 // index set in alignLabelsNoSync
249 case kAlignEndToEnd:
250 newPos = firstTrackOffset();
251 action = moveSel
252 ? XO("Aligned/Moved end to end")
253 : XO("Aligned end to end");
254 shortAction =
255 moveSel
256 ? XO("Align/Move End to End")
257 : XO("Align End to End");
258 break;
259 case kAlignTogether:
260 newPos = avgOffset();
261 action = moveSel
262 ? XO("Aligned/Moved together")
263 : XO("Aligned together");
264 shortAction =
265 moveSel
266 ? XO("Align/Move Together")
267 : XO("Align Together");
268 }
269
270 if ((unsigned)index >= kAlignLabelsCount()) {
271 // This is an alignLabelsNoSync command.
272 for (auto t : tracks.Selected<AudioTrack>()) {
273 // This shifts different tracks in different ways, so no sync-lock
274 // move.
275 // Only align Wave and Note tracks end to end.
276 t->MoveTo(newPos);
277 if (index == kAlignEndToEnd)
278 newPos += (t->GetEndTime() - t->GetStartTime());
279 }
280 if (index == kAlignEndToEnd)
281 viewport.ZoomFitHorizontally();
282 }
283
284 if (delta != 0.0) {
285 // For a fixed-distance shift move sync-lock selected tracks also.
286 for (auto t : tracks.Any()
288 t->MoveTo(t->GetStartTime() + delta);
289 }
290
291 if (moveSel)
292 selectedRegion.move(delta);
293
294 ProjectHistory::Get( project ).PushState(action, shortAction);
295}
296
297#ifdef EXPERIMENTAL_SCOREALIGN
298
299#ifdef USE_MIDI
300static const ReservedCommandFlag&
301 NoteTracksSelectedFlag() { static ReservedCommandFlag flag{
302 [](const AudacityProject &project){
303 return !TrackList::Get( project ).Selected<const NoteTrack>().empty();
304 }
305 }; return flag; } //gsw
306#endif
307
308// rough relative amount of time to compute one
309// frame of audio or midi, or one cell of matrix, or one iteration
310// of smoothing, measured on a 1.9GHz Core 2 Duo in 32-bit mode
311// (see COLLECT_TIMING_DATA below)
312#define AUDIO_WORK_UNIT 0.004F
313#define MIDI_WORK_UNIT 0.0001F
314#define MATRIX_WORK_UNIT 0.000002F
315#define SMOOTHING_WORK_UNIT 0.000001F
316
317// Write timing data to a file; useful for calibrating AUDIO_WORK_UNIT,
318// MIDI_WORK_UNIT, MATRIX_WORK_UNIT, and SMOOTHING_WORK_UNIT coefficients
319// Data is written to timing-data.txt; look in
320// audacity-src/win/Release/modules/
321#define COLLECT_TIMING_DATA
322
323// Audacity Score Align Progress class -- progress reports come here
324class ASAProgress final : public SAProgress {
325 private:
326 float mTotalWork;
327 float mFrames[2];
328 long mTotalCells; // how many matrix cells?
329 long mCellCount; // how many cells so far?
330 long mPrevCellCount; // cell_count last reported with Update()
331 std::optional<ProgressDialog> mProgress;
332 #ifdef COLLECT_TIMING_DATA
333 FILE *mTimeFile;
334 wxDateTime mStartTime;
335 long iterations;
336 #endif
337
338 public:
339 ASAProgress() {
340 smoothing = false;
341 #ifdef COLLECT_TIMING_DATA
342 mTimeFile = fopen("timing-data.txt", "w");
343 #endif
344 }
345 ~ASAProgress() {
346 #ifdef COLLECT_TIMING_DATA
347 fclose(mTimeFile);
348 #endif
349 }
350 void set_phase(int i) override {
351 float work[2]; // chromagram computation work estimates
352 float work2, work3 = 0; // matrix and smoothing work estimates
353 SAProgress::set_phase(i);
354 #ifdef COLLECT_TIMING_DATA
355 long ms = 0;
356 wxDateTime now = wxDateTime::UNow();
357 wxFprintf(mTimeFile, "Phase %d begins at %s\n",
358 i, now.FormatTime());
359 if (i != 0)
360 ms = now.Subtract(mStartTime).GetMilliseconds().ToLong();
361 mStartTime = now;
362 #endif
363 if (i == 0) {
364 mCellCount = 0;
365 for (int j = 0; j < 2; j++) {
366 mFrames[j] = durations[j] / frame_period;
367 }
368 mTotalWork = 0;
369 for (int j = 0; j < 2; j++) {
370 work[j] =
371 (is_audio[j] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[j];
372 mTotalWork += work[j];
373 }
374 mTotalCells = mFrames[0] * mFrames[1];
375 work2 = mTotalCells * MATRIX_WORK_UNIT;
376 mTotalWork += work2;
377 // arbitrarily assume 60 iterations to fit smooth segments and
378 // per frame per iteration is SMOOTHING_WORK_UNIT
379 if (smoothing) {
380 work3 =
381 wxMax(mFrames[0], mFrames[1]) * SMOOTHING_WORK_UNIT * 40;
382 mTotalWork += work3;
383 }
384 #ifdef COLLECT_TIMING_DATA
385 wxFprintf(mTimeFile,
386 " mTotalWork (an estimate) = %g\n", mTotalWork);
387 wxFprintf(mTimeFile, " work0 = %g, frames %g, is_audio %d\n",
388 work[0], mFrames[0], is_audio[0]);
389 wxFprintf(mTimeFile, " work1 = %g, frames %g, is_audio %d\n",
390 work[1], mFrames[1], is_audio[1]);
391 wxFprintf(mTimeFile, "work2 = %g, work3 = %g\n", work2, work3);
392 #endif
393 mProgress.emplace(XO("Synchronize MIDI with Audio"),
394 XO("Synchronizing MIDI and Audio Tracks"));
395 } else if (i < 3) {
396 wxFprintf(mTimeFile,
397 "Phase %d took %d ms for %g frames, coefficient = %g s/frame\n",
398 i - 1, ms, mFrames[i - 1], (ms * 0.001) / mFrames[i - 1]);
399 } else if (i == 3) {
400 wxFprintf(mTimeFile,
401 "Phase 2 took %d ms for %d cells, coefficient = %g s/cell\n",
402 ms, mCellCount, (ms * 0.001) / mCellCount);
403 } else if (i == 4) {
404 wxFprintf(mTimeFile,
405 "Phase 3 took %d ms for %d iterations on %g frames, "
406 "coefficient = %g s per frame per iteration\n",
407 ms, iterations, wxMax(mFrames[0], mFrames[1]),
408 (ms * 0.001) / (wxMax(mFrames[0], mFrames[1]) * iterations));
409 }
410 }
411 bool set_feature_progress(float s) override {
412 float work;
413 if (phase == 0) {
414 float f = s / frame_period;
415 work = (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * f;
416 } else if (phase == 1) {
417 float f = s / frame_period;
418 work = (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
419 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * f;
420 }
421 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
422 return (updateResult == ProgressResult::Success);
423 }
424 bool set_matrix_progress(int cells) override {
425 mCellCount += cells;
426 float work =
427 (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
428 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[1];
429 work += mCellCount * MATRIX_WORK_UNIT;
430 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
431 return (updateResult == ProgressResult::Success);
432 }
433 bool set_smoothing_progress(int i) override {
434 iterations = i;
435 float work =
436 (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
437 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[1] +
438 MATRIX_WORK_UNIT * mFrames[0] * mFrames[1];
439 work += i * wxMax(mFrames[0], mFrames[1]) * SMOOTHING_WORK_UNIT;
440 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
441 return (updateResult == ProgressResult::Success);
442 }
443};
444
445
446long mixer_process(void *mixer, float **buffer, long n)
447{
448 Mixer *mix = (Mixer *) mixer;
449 long frame_count = mix->Process(std::max(0L, n));
450 *buffer = (float *) mix->GetBuffer();
451 return frame_count;
452}
453
454#endif // EXPERIMENTAL_SCOREALIGN
455
456enum{
459};
460
462{
463 auto GetTime = [](const Track &t) {
464 return t.TypeSwitch<double>(
465 [&](const WaveTrack &w) {
466 auto stime = w.GetEndTime();
467
468 int ndx;
469 for (ndx = 0; ndx < w.GetNumClips(); ndx++) {
470 const auto c = w.GetClip(ndx);
471 if (c->GetVisibleSampleCount() == 0)
472 continue;
473 stime = std::min(stime, c->GetPlayStartTime());
474 }
475 return stime;
476 },
477 [&](const LabelTrack& l) {
478 return l.GetStartTime();
479 }
480 );
481 };
482
483 std::vector<Track *> arr;
485 arr.reserve(tracks.Size());
486
487 // First find the permutation.
488 for (const auto pTrack : tracks) {
489 auto &track = *pTrack;
490 const auto size = arr.size();
491 size_t ndx = 0;
492 for (; ndx < size; ++ndx) {
493 Track &arrTrack = *arr[ndx];
494 if (flags & kAudacitySortByName) {
495 //do case insensitive sort - cmpNoCase returns less than zero if
496 // the string is 'less than' its argument
497 //also if we have case insensitive equality, then we need to sort
498 // by case as well
499 //We sort 'b' before 'B' accordingly. We uncharacteristically
500 // use greater than for the case sensitive
501 //compare because 'b' is greater than 'B' in ascii.
502 auto cmpValue = track.GetName().CmpNoCase(arrTrack.GetName());
503 if (cmpValue < 0 ||
504 (0 == cmpValue &&
505 track.GetName().CompareTo(arrTrack.GetName()) > 0))
506 break;
507 }
508 //sort by time otherwise
509 else if (flags & kAudacitySortByTime)
510 if (GetTime(track) < GetTime(arrTrack))
511 break;
512 }
513 arr.insert(arr.begin() + ndx, &track);
514 }
515
516 // Now apply the permutation
517 tracks.Permute(arr);
518}
519
521{
522 wxASSERT(wt);
523 float newValue = slider->Get();
524
525 wt->SetVolume(newValue);
526
528 .PushState(XO("Adjusted gain"), XO("Gain"), UndoPush::CONSOLIDATE);
529
531}
532
534{
535 wxASSERT(wt);
536 float newValue = slider->Get();
537
538 wt->SetPan(newValue);
539
541 .PushState(XO("Adjusted Pan"), XO("Pan"), UndoPush::CONSOLIDATE);
542
544}
545
546}
547
548namespace {
549
550// Menu handler functions
551
552void OnStereoToMono(const CommandContext &context)
553{
555 PluginManager::Get().GetByCommandIdentifier(wxT("StereoToMono")),
557}
558
559void OnMixAndRender(const CommandContext &context)
560{
561 auto &project = context.project;
562 DoMixAndRender(project, false);
563}
564
566{
567 auto &project = context.project;
568 DoMixAndRender(project, true);
569}
570
571void OnResample(const CommandContext &context)
572{
573 auto &project = context.project;
574 auto projectRate = ProjectRate::Get(project).GetRate();
576 auto &undoManager = UndoManager::Get(project);
577 auto &viewport = Viewport::Get(project);
578 auto &window = GetProjectFrame(project);
579
580 int newRate;
581
582 while (true) {
583 wxDialogWrapper dlg(&window, wxID_ANY, XO("Resample"));
584 ShuttleGui S(&dlg, eIsCreating);
585 wxString rate;
586 wxComboBox *cb;
587
588 rate.Printf(wxT("%ld"), lrint(projectRate));
589
590 wxArrayStringEx rates{
591 wxT("8000") ,
592 wxT("11025") ,
593 wxT("16000") ,
594 wxT("22050") ,
595 wxT("32000") ,
596 wxT("44100") ,
597 wxT("48000") ,
598 wxT("88200") ,
599 wxT("96000") ,
600 wxT("176400") ,
601 wxT("192000") ,
602 wxT("352800") ,
603 wxT("384000") ,
604 };
605
606 S.StartVerticalLay(true);
607 {
608 S.AddSpace(-1, 15);
609
610 S.StartHorizontalLay(wxCENTER, false);
611 {
612 cb = S.AddCombo(XXO("New sample rate (Hz):"),
613 rate,
614 rates);
615 }
616 S.EndHorizontalLay();
617
618 S.AddSpace(-1, 15);
619
620 S.AddStandardButtons();
621 }
622 S.EndVerticalLay();
623
624 dlg.Layout();
625 dlg.Fit();
626 dlg.Center();
627
628 if (dlg.ShowModal() != wxID_OK)
629 return; // user cancelled dialog
630
631 long lrate;
632 if (cb->GetValue().ToLong(&lrate) && lrate >= 1 && lrate <= 1000000) {
633 newRate = (int)lrate;
634 break;
635 }
636
638 XO("The entered value is invalid"),
639 XO("Error"),
640 wxICON_ERROR,
641 &window);
642 }
643
644 int ndx = 0;
645 auto flags = UndoPush::NONE;
646 for (auto wt : tracks.Selected<WaveTrack>()) {
647 auto msg = XO("Resampling track %d").Format(++ndx);
648
649 using namespace BasicUI;
650 auto progress = MakeProgress(XO("Resample"), msg);
651
652 // The resampling of a track may be stopped by the user. This might
653 // leave a track with multiple clips in a partially resampled state.
654 // But the thrown exception will cause rollback in the application
655 // level handler.
656
657 wt->Resample(newRate, progress.get());
658
659 // Each time a track is successfully, completely resampled,
660 // commit that to the undo stack. The second and later times,
661 // consolidate.
662
664 XO("Resampled audio track(s)"), XO("Resample Track"), flags);
665 flags = flags | UndoPush::CONSOLIDATE;
666 }
667
668 undoManager.StopConsolidating();
669
670 // Need to reset
671 viewport.DoScroll();
672}
673
674void OnRemoveTracks(const CommandContext &context)
675{
677}
678
679static void MuteTracks(const CommandContext &context, bool mute, bool selected)
680{
681 auto &project = context.project;
682 const auto &settings = ProjectSettings::Get( project );
683 auto &tracks = TrackList::Get( project );
684
685 const auto solo = TracksBehaviorsSolo.ReadEnum();
686 const auto soloSimple = (solo == SoloBehaviorSimple);
687
688 auto iter = selected ? tracks.Selected<PlayableTrack>() : tracks.Any<PlayableTrack>();
689 for (auto pt : iter) {
690 pt->SetMute(mute);
691 if (soloSimple)
692 pt->SetSolo(false);
693 }
694
696}
697
698void OnMuteAllTracks(const CommandContext &context)
699{
700 MuteTracks(context, true, false);
701}
702
704{
705 MuteTracks(context, false, false);
706}
707
709{
710 MuteTracks(context, true, true);
711}
712
714{
715 MuteTracks(context, false, true);
716}
717
718void OnPanLeft(const CommandContext &context)
719{
720 auto &project = context.project;
721 DoPanTracks( project, -1.0);
722}
723
724void OnPanRight(const CommandContext &context)
725{
726 auto &project = context.project;
727 DoPanTracks( project, 1.0);
728}
729
730void OnPanCenter(const CommandContext &context)
731{
732 auto &project = context.project;
733 DoPanTracks( project, 0.0);
734}
735
736void OnAlignNoSync(const CommandContext &context)
737{
738 auto &project = context.project;
739
741 context.index + kAlignLabelsCount(), false);
742}
743
744void OnAlign(const CommandContext &context)
745{
746 auto &project = context.project;
747
748 bool bMoveWith;
749 gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, false);
750 DoAlign(project, context.index, bMoveWith);
751}
752
753/*
754// Now handled in OnAlign.
755void OnAlignMoveSel(int index)
756{
757 DoAlign(index, true);
758}
759*/
760
761void OnMoveSelectionWithTracks(const CommandContext &WXUNUSED(context) )
762{
763 bool bMoveWith;
764 gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, false);
765 gPrefs->Write(wxT("/GUI/MoveSelectionWithTracks"), !bMoveWith);
766 gPrefs->Flush();
767
768}
769
770#ifdef EXPERIMENTAL_SCOREALIGN
771void OnScoreAlign(const CommandContext &context)
772{
773 auto &project = context.project;
774 auto &tracks = TrackList::Get( project );
775 const auto rate = ProjectSettings::Get( project ).GetRate();
776
777 int numWaveTracksSelected = 0;
778 int numNoteTracksSelected = 0;
779 int numOtherTracksSelected = 0;
780 double endTime = 0.0;
781
782 // Iterate through once to make sure that there is exactly
783 // one WaveTrack and one NoteTrack selected.
784 tracks.Selected().Visit(
785 [&](WaveTrack *wt) {
786 numWaveTracksSelected++;
787 endTime = endTime > wt->GetEndTime() ? endTime : wt->GetEndTime();
788 },
789 [&](NoteTrack *) {
790 numNoteTracksSelected++;
791 },
792 [&](Track*) {
793 numOtherTracksSelected++;
794 }
795 );
796
797 if(numWaveTracksSelected == 0 ||
798 numNoteTracksSelected != 1 ||
799 numOtherTracksSelected != 0){
801 XO("Please select at least one audio track and one MIDI track.") );
802 return;
803 }
804
805 // Creating the dialog also stores dialog into gScoreAlignDialog so
806 // that it can be deleted by CloseScoreAlignDialog() either here or
807 // if the program is quit by the user while the dialog is up.
808 ScoreAlignParams params;
809
810 // safe because the class maintains a global resource pointer
812
813 CloseScoreAlignDialog();
814
815 if (params.mStatus != wxID_OK) return;
816
817 // We're going to do it.
818 //pushing the state before the change is wrong (I think)
819 //PushState(XO("Sync MIDI with Audio"), XO("Sync MIDI with Audio"));
820 // Make a copy of the note track in case alignment is canceled or fails
821 auto holder = nt->Duplicate();
822 auto alignedNoteTrack = static_cast<NoteTrack*>(holder.get());
823 // Remove offset from NoteTrack because audio is
824 // mixed starting at zero and incorporating clip offsets.
825 if (alignedNoteTrack->GetOffset() < 0) {
826 // remove the negative offset data before alignment
827 nt->Clear(alignedNoteTrack->GetOffset(), 0);
828 } else if (alignedNoteTrack->GetOffset() > 0) {
829 alignedNoteTrack->Shift(alignedNoteTrack->GetOffset());
830 }
831 alignedNoteTrack->MoveTo(0);
832
833 WaveTrackConstArray waveTracks =
834 tracks->GetWaveTrackConstArray(true /* selectionOnly */);
835
836 int result;
837 {
838 Mixer mix(
839 waveTracks, // const WaveTrackConstArray &inputTracks
840 false, // mayThrow -- is this right?
842 0.0, // double startTime
843 endTime, // double stopTime
844 2, // int numOutChannels
845 44100u, // size_t outBufferSize
846 true, // bool outInterleaved
847 rate, // double outRate
848 floatSample, // sampleFormat outFormat
849 true, // bool highQuality = true
850 NULL); // MixerSpec *mixerSpec = NULL
851
852 ASAProgress progress;
853
854 // There's a lot of adjusting made to incorporate the note track offset into
855 // the note track while preserving the position of notes within beats and
856 // measures. For debugging, you can see just the pre-scorealign note track
857 // manipulation by setting SKIP_ACTUAL_SCORE_ALIGNMENT. You could then, for
858 // example, save the modified note track in ".gro" form to read the details.
859 //#define SKIP_ACTUAL_SCORE_ALIGNMENT 1
860#ifndef SKIP_ACTUAL_SCORE_ALIGNMENT
861 result = scorealign((void *) &mix, &mixer_process,
862 2 /* channels */, 44100.0 /* srate */, endTime,
863 &alignedNoteTrack->GetSeq(), &progress, params);
864#else
865 result = SA_SUCCESS;
866#endif
867 }
868
869 if (result == SA_SUCCESS) {
870 tracks->Replace(nt, holder);
872 XO("Alignment completed: MIDI from %.2f to %.2f secs, Audio from %.2f to %.2f secs.")
873 .Format(
874 params.mMidiStart, params.mMidiEnd,
875 params.mAudioStart, params.mAudioEnd) );
877 .PushState(XO("Sync MIDI with Audio"), XO("Sync MIDI with Audio"));
878 } else if (result == SA_TOOSHORT) {
880 XO(
881"Alignment error: input too short: MIDI from %.2f to %.2f secs, Audio from %.2f to %.2f secs.")
882 .Format(
883 params.mMidiStart, params.mMidiEnd,
884 params.mAudioStart, params.mAudioEnd) );
885 } else if (result == SA_CANCEL) {
886 // wrong way to recover...
887 //project.OnUndo(); // recover any changes to note track
888 return; // no message when user cancels alignment
889 } else {
890 //project.OnUndo(); // recover any changes to note track
891 AudacityMessageBox( XO("Internal error reported by alignment process.") );
892 }
893}
894#endif /* EXPERIMENTAL_SCOREALIGN */
895
896void OnSortTime(const CommandContext &context)
897{
898 auto &project = context.project;
900
902 .PushState(XO("Tracks sorted by time"), XO("Sort by Time"));
903}
904
905void OnSortName(const CommandContext &context)
906{
907 auto &project = context.project;
909
911 .PushState(XO("Tracks sorted by name"), XO("Sort by Name"));
912}
913
914void OnSyncLock(const CommandContext &context)
915{
916 auto &project = context.project;
917 auto &trackPanel = TrackPanel::Get( project );
918
920 gPrefs->Flush();
921
922 // Toolbar, project sync-lock handled within
924
925 trackPanel.Refresh(false);
926}
927
930void OnTrackPan(const CommandContext &context)
931{
932 auto &project = context.project;
933 auto &trackPanel = TrackPanel::Get( project );
934
935 const auto track = TrackFocus::Get( project ).Get();
936 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
937 LWSlider *slider = WaveTrackControls::PanSlider( trackPanel, wt );
938 if (slider->ShowDialog())
939 SetTrackPan(project, &wt, slider);
940 });
941}
942
943void OnTrackPanLeft(const CommandContext &context)
944{
945 auto &project = context.project;
946 auto &trackPanel = TrackPanel::Get( project );
947
948 const auto track = TrackFocus::Get( project ).Get();
949 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
950 LWSlider *slider = WaveTrackControls::PanSlider( trackPanel, wt );
951 slider->Decrease(1);
952 SetTrackPan(project, &wt, slider);
953 });
954}
955
956void OnTrackPanRight(const CommandContext &context)
957{
958 auto &project = context.project;
959 auto &trackPanel = TrackPanel::Get( project );
960
961 const auto track = TrackFocus::Get( project ).Get();
962 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
963 LWSlider *slider = WaveTrackControls::PanSlider( trackPanel, wt );
964 slider->Increase(1);
965 SetTrackPan(project, &wt, slider);
966 });
967}
968
969void OnTrackGain(const CommandContext &context)
970{
971 auto &project = context.project;
972 auto &trackPanel = TrackPanel::Get( project );
973
975 const auto track = TrackFocus::Get( project ).Get();
976 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
977 LWSlider *slider = WaveTrackControls::VolumeSlider( trackPanel, wt );
978 if (slider->ShowDialog())
979 SetTrackGain(project, &wt, slider);
980 });
981}
982
983void OnTrackGainInc(const CommandContext &context)
984{
985 auto &project = context.project;
986 auto &trackPanel = TrackPanel::Get( project );
987
988 const auto track = TrackFocus::Get( project ).Get();
989 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
990 LWSlider *slider = WaveTrackControls::VolumeSlider( trackPanel, wt );
991 slider->Increase(1);
992 SetTrackGain(project, &wt, slider);
993 });
994}
995
996void OnTrackGainDec(const CommandContext &context)
997{
998 auto &project = context.project;
999 auto &trackPanel = TrackPanel::Get( project );
1000
1001 const auto track = TrackFocus::Get( project ).Get();
1002 if (track) track->TypeSwitch( [&](WaveTrack &wt) {
1003 LWSlider *slider = WaveTrackControls::VolumeSlider( trackPanel, wt );
1004 slider->Decrease(1);
1005 SetTrackGain(project, &wt, slider);
1006 });
1007}
1008
1009void OnTrackMenu(const CommandContext &context)
1010{
1011 auto &project = context.project;
1012 auto &trackPanel = TrackPanel::Get( project );
1013
1014 trackPanel.OnTrackMenu();
1015}
1016
1017void OnTrackMute(const CommandContext &context)
1018{
1019 auto &project = context.project;
1020
1021 // Use the temporary selection if it is specified, else the track focus
1022 auto track = context.temporarySelection.pTrack;
1023 if (!track)
1024 track = TrackFocus::Get( project ).Get();
1025
1026 if (track) track->TypeSwitch( [&](PlayableTrack &t) {
1028 });
1029}
1030
1031void OnTrackSolo(const CommandContext &context)
1032{
1033 auto &project = context.project;
1034
1035 const auto track = TrackFocus::Get( project ).Get();
1036 if (track) track->TypeSwitch( [&](PlayableTrack &t) {
1038 });
1039}
1040
1041void OnTrackClose(const CommandContext &context)
1042{
1043 auto &project = context.project;
1044 auto &trackPanel = TrackPanel::Get( project );
1045
1046 const auto t = TrackFocus::Get( project ).Get();
1047 if (!t)
1048 return;
1049
1050 auto isAudioActive = ProjectAudioIO::Get( project ).IsAudioActive();
1051
1052 if (isAudioActive)
1053 {
1055 XO("Can't delete track with active audio"));
1056 wxBell();
1057 return;
1058 }
1059
1061
1062 trackPanel.UpdateViewIfNoTracks();
1063 trackPanel.Refresh(false);
1064}
1065
1066void OnTrackMoveUp(const CommandContext &context)
1067{
1068 auto &project = context.project;
1069 auto &trackPanel = TrackPanel::Get( project );
1070 auto &tracks = TrackList::Get( project );
1071
1072 const auto focusedTrack = TrackFocus::Get( project ).Get();
1073 if (focusedTrack && tracks.CanMoveUp(*focusedTrack)) {
1075 trackPanel.Refresh(false);
1076 }
1077}
1078
1080{
1081 auto &project = context.project;
1082 auto &trackPanel = TrackPanel::Get( project );
1083 auto &tracks = TrackList::Get( project );
1084
1085 const auto focusedTrack = TrackFocus::Get( project ).Get();
1086 if (focusedTrack && tracks.CanMoveDown(*focusedTrack)) {
1088 trackPanel.Refresh(false);
1089 }
1090}
1091
1092void OnTrackMoveTop(const CommandContext &context)
1093{
1094 auto &project = context.project;
1095 auto &trackPanel = TrackPanel::Get( project );
1096 auto &tracks = TrackList::Get( project );
1097
1098 const auto focusedTrack = TrackFocus::Get( project ).Get();
1099 if (focusedTrack && tracks.CanMoveUp(*focusedTrack)) {
1101 trackPanel.Refresh(false);
1102 }
1103}
1104
1106{
1107 auto &project = context.project;
1108 auto &trackPanel = TrackPanel::Get( project );
1109 auto &tracks = TrackList::Get( project );
1110
1111 const auto focusedTrack = TrackFocus::Get( project ).Get();
1112 if (focusedTrack && tracks.CanMoveDown(*focusedTrack)) {
1114 trackPanel.Refresh(false);
1115 }
1116}
1117
1118// Menu definitions
1119
1120// Under /MenuBar
1121using namespace MenuRegistry;
1123{
1124 // Tracks Menu (formerly Project Menu)
1125 static auto menu = std::shared_ptr{
1126 Menu( wxT("Tracks"), XXO("&Tracks"),
1127 Section( "Add",
1128 Menu( wxT("Add"), XXO("Add &New") )
1129 ),
1130
1132
1133 Section( "",
1134 Menu( wxT("Mix"), XXO("Mi&x"),
1135 // Delayed evaluation
1136 // Stereo to Mono is an oddball command that is also subject to control
1137 // by the plug-in manager, as if an effect. Decide whether to show or
1138 // hide it.
1139 [](AudacityProject&) -> std::unique_ptr<CommandItem> {
1140 const PluginID ID =
1142 const PluginDescriptor *plug = PluginManager::Get().GetPlugin(ID);
1143 if (plug && plug->IsEnabled())
1144 return Command( wxT("Stereo to Mono"),
1145 XXO("Mix Stereo Down to &Mono"), OnStereoToMono,
1148 else
1149 return {};
1150 },
1151 Command( wxT("MixAndRender"), XXO("Mi&x and Render"),
1154 Command( wxT("MixAndRenderToNewTrack"),
1155 XXO("Mix and Render to Ne&w Track"),
1157 AudioIONotBusyFlag() | WaveTracksSelectedFlag(), wxT("Ctrl+Shift+M") )
1158 ),
1159
1160 Command( wxT("Resample"), XXO("&Resample..."), OnResample,
1162 ),
1163
1164 Section( "",
1165 Command( wxT("RemoveTracks"), XXO("Remo&ve Tracks"), OnRemoveTracks,
1167 ),
1168
1169 Section( "",
1170 Menu( wxT("Mute"), XXO("M&ute/Unmute"),
1171 Command( wxT("MuteAllTracks"), XXO("&Mute All Tracks"),
1172 OnMuteAllTracks, TracksExistFlag(), wxT("Ctrl+U") ),
1173 Command( wxT("UnmuteAllTracks"), XXO("&Unmute All Tracks"),
1174 OnUnmuteAllTracks, TracksExistFlag(), wxT("Ctrl+Shift+U") ),
1175 Command( wxT("MuteTracks"), XXO("Mut&e Tracks"),
1177 Command( wxT("UnmuteTracks"), XXO("U&nmute Tracks"),
1178 OnUnmuteSelectedTracks, EditableTracksSelectedFlag(), wxT("Ctrl+Alt+Shift+U") )
1179 ),
1180
1181 Menu( wxT("Pan"), XXO("&Pan"),
1182 // As Pan changes are not saved on Undo stack,
1183 // pan settings for all tracks
1184 // in the project could very easily be lost unless we
1185 // require the tracks to be selected.
1186 Command( wxT("PanLeft"), XXO("&Left"), OnPanLeft,
1188 Options{}.LongName( XO("Pan Left") ) ),
1189 Command( wxT("PanRight"), XXO("&Right"), OnPanRight,
1191 Options{}.LongName( XO("Pan Right") ) ),
1192 Command( wxT("PanCenter"), XXO("&Center"), OnPanCenter,
1194 Options{}.LongName( XO("Pan Center") ) )
1195 )
1196 ),
1197
1198 Section( "",
1199 Menu( wxT("Align"), XXO("&Align Tracks"), // XO("Just Move Tracks"),
1200 Section( "",
1201 // Mutual alignment of tracks independent of selection or zero
1202 CommandGroup(wxT("Align"),
1203 {
1204 { wxT("EndToEnd"), XXO("&Align End to End") },
1205 { wxT("Together"), XXO("Align &Together") },
1206 },
1208 ),
1209
1210 Section( "",
1211 // Alignment commands using selection or zero
1212 CommandGroup(wxT("Align"),
1213 alignLabels(),
1215 ),
1216
1217 Section( "",
1218 Command( wxT("MoveSelectionWithTracks"),
1219 XXO("&Move Selection with Tracks"),
1222 Options{}.CheckTest( wxT("/GUI/MoveSelectionWithTracks"), false ) )
1223 )
1224 ),
1225
1226 #if 0
1227 // TODO: Can these labels be made clearer?
1228 // Do we need this sub-menu at all?
1229 Menu( wxT("MoveSelectionAndTracks"), XO("Move Sele&ction and Tracks"), {
1230 CommandGroup(wxT("AlignMove"), alignLabels(),
1231 OnAlignMoveSel, AudioIONotBusyFlag() | EditableTracksSelectedFlag()),
1232 } ),
1233 #endif
1234
1236
1237 #ifdef EXPERIMENTAL_SCOREALIGN
1238 Command( wxT("ScoreAlign"), XXO("Synchronize MIDI with Audio"),
1239 OnScoreAlign,
1240 AudioIONotBusyFlag() | NoteTracksSelectedFlag() | WaveTracksSelectedFlag() ),
1241 #endif // EXPERIMENTAL_SCOREALIGN
1242
1244
1245 Menu( wxT("Sort"), XXO("S&ort Tracks"),
1246 Command( wxT("SortByTime"), XXO("By &Start Time"), OnSortTime,
1248 Options{}.LongName( XO("Sort by Time") ) ),
1249 Command( wxT("SortByName"), XXO("By &Name"), OnSortName,
1251 Options{}.LongName( XO("Sort by Name") ) )
1252 )
1253
1255 ),
1256
1257 Section( "",
1258 Command( wxT("SyncLock"), XXO("Keep tracks synchronized (Sync-&Lock)"),
1261 )
1262
1263 ) };
1264 return menu;
1265}
1266
1268
1270{
1271 static auto menu = std::shared_ptr{
1272 Menu( wxT("Track"), XXO("&Track"),
1273 Command( wxT("TrackPan"), XXO("Change P&an on Focused Track..."),
1274 OnTrackPan,
1275 TrackPanelHasFocus() | TracksExistFlag(), wxT("Shift+P") ),
1276 Command( wxT("TrackPanLeft"), XXO("Pan &Left on Focused Track"),
1278 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Left") ),
1279 Command( wxT("TrackPanRight"), XXO("Pan &Right on Focused Track"),
1281 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Right") ),
1282 Command( wxT("TrackGain"), XXO("Change Gai&n on Focused Track..."),
1284 TrackPanelHasFocus() | TracksExistFlag(), wxT("Shift+G") ),
1285 Command( wxT("TrackGainInc"), XXO("&Increase Gain on Focused Track"),
1287 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Up") ),
1288 Command( wxT("TrackGainDec"), XXO("&Decrease Gain on Focused Track"),
1290 TrackPanelHasFocus() | TracksExistFlag(), wxT("Alt+Shift+Down") ),
1291 Command( wxT("TrackMenu"), XXO("Op&en Menu on Focused Track..."),
1294 Options{ wxT("Shift+M") }.SkipKeyDown() ),
1295 Command( wxT("TrackMute"), XXO("M&ute/Unmute Focused Track"),
1297 TracksExistFlag() | TrackPanelHasFocus(), wxT("Shift+U") ),
1298 Command( wxT("TrackSolo"), XXO("&Solo/Unsolo Focused Track"),
1300 TracksExistFlag() | TrackPanelHasFocus(), wxT("Shift+S") ),
1301 Command( wxT("TrackClose"), XXO("Delete Fo&cused Track"),
1304 wxT("Shift+C") ),
1305 Command( wxT("TrackMoveUp"), XXO("Move Focused Track U&p"),
1308 Command( wxT("TrackMoveDown"), XXO("Move Focused Track Do&wn"),
1311 Command( wxT("TrackMoveTop"), XXO("Move Focused Track to T&op"),
1314 Command( wxT("TrackMoveBottom"), XXO("Move Focused Track to &Bottom"),
1317 ) };
1318 return menu;
1319}
1320
1322 wxT("Optional/Extra/Part2")
1323};
1324
1325}
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
AttachedItem sAttachment1
AttachedItem sAttachment2
wxString PluginID
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & StereoRequiredFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & AnyTracksSelectedFlag()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
const ReservedCommandFlag & TrackPanelHasFocus()
int min(int a, int b)
EffectDistortionSettings params
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:10
Track::Holder MixAndRender(const TrackIterRange< const WaveTrack > &trackRange, const Mixer::WarpOptions &warpOptions, const wxString &newTrackName, WaveTrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime)
Mixes together all input tracks, applying any envelopes, per-track real-time effects,...
std::vector< std::shared_ptr< const WaveTrack > > WaveTrackConstArray
EnumSetting< SoloBehavior > TracksBehaviorsSolo
@ SoloBehaviorSimple
Definition: PlayableTrack.h:70
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
an object holding per-project preferred sample rate
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
constexpr sampleFormat floatSample
Definition: SampleFormat.h:45
@ eIsCreating
Definition: ShuttleGui.h:37
BoolSetting SyncLockTracks
Definition: SyncLock.cpp:163
const auto tracks
const auto project
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:51
static std::once_flag flag
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Track subclass holding data representing sound (as notes, or samples, or ...)
Definition: PlayableTrack.h:21
bool Toggle()
Write the negation of the previous value, and return true if successful.
Definition: Prefs.cpp:555
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
Definition: Channel.cpp:61
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
Definition: Channel.cpp:50
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:260
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:318
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
TemporarySelection temporarySelection
AudacityProject & project
Abstract base class used in importing a file.
Lightweight version of ASlider. In other words it does not have a window permanently associated with ...
Definition: ASlider.h:64
void Decrease(float steps)
Definition: ASlider.cpp:1617
void Increase(float steps)
Definition: ASlider.cpp:1594
float Get(bool convert=true)
Definition: ASlider.cpp:1569
bool ShowDialog()
Definition: ASlider.cpp:1120
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:98
Functions for doing the mixdown of the tracks.
Definition: Mix.h:31
size_t Process(size_t maxSamples)
Definition: Mix.cpp:295
constSamplePtr GetBuffer()
Retrieve the main buffer or the interleaved buffer.
Definition: Mix.cpp:344
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:78
void Clear(double t0, double t1) override
Definition: NoteTrack.cpp:403
AudioTrack subclass that can also be audibly replayed by the program.
Definition: PlayableTrack.h:40
void SetMute(bool m)
bool IsEnabled() const
const PluginDescriptor * GetPlugin(const PluginID &ID) const
const PluginID & GetByCommandIdentifier(const CommandID &strTarget)
static PluginManager & Get()
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
static ProjectSettings & Get(AudacityProject &project)
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=MainStatusBarField())
Generates classes whose instances register items at construction.
Definition: Registry.h:388
ScoreAlignDialog is \TODO.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
static bool IsSelectedOrSyncLockSelectedP(const Track *pTrack)
Definition: SyncLock.h:61
static void ModifyAllProjectToolbarMenus()
Track * Get()
Definition: TrackFocus.cpp:156
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
bool IsSelected() const
Definition: Track.cpp:258
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:64
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:967
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:234
void RefreshTrack(Track *trk, bool refreshbacking=true)
Definition: TrackPanel.cpp:768
Holds a msgid for the translation catalog; may also bind format arguments.
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void ShowTrack(const Track &track)
Definition: Viewport.cpp:460
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
static LWSlider * VolumeSlider(CellularPanel &panel, const WaveTrack &wt)
static LWSlider * PanSlider(CellularPanel &panel, const WaveTrack &wt)
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:3376
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
void SetPan(float newPan)
Definition: WaveTrack.cpp:870
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2613
size_t NChannels() const override
A constant property.
Definition: WaveTrack.cpp:530
void SetVolume(float newVolume)
Definition: WaveTrack.cpp:852
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
#define lrint(dbl)
Definition: float_cast.h:169
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:302
bool DoEffect(const PluginID &ID, AudacityProject &project, unsigned flags)
Definition: DoEffect.cpp:30
constexpr auto Section
Definition: MenuRegistry.h:436
constexpr auto CommandGroup
Definition: MenuRegistry.h:458
constexpr auto Command
Definition: MenuRegistry.h:456
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
Definition: MenuRegistry.h:445
PROJECT_RATE_API sampleFormat SampleFormatChoice()
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
AUDACITY_DLL_API void DoMoveTrack(AudacityProject &project, Track &target, MoveChoice choice)
Move a track up, down, to top or to bottom.
AUDACITY_DLL_API void DoRemoveTrack(AudacityProject &project, Track &toRemove)
AUDACITY_DLL_API void DoTrackSolo(AudacityProject &project, Track &track, bool exclusive)
AUDACITY_DLL_API void DoTrackMute(AudacityProject &project, Track &track, bool exclusive)
"exclusive" mute means mute the chosen track and unmute all others.
AUDACITY_DLL_API void DoRemoveTracks(AudacityProject &)
void OnPanCenter(const CommandContext &context)
Definition: TrackMenus.cpp:730
void OnUnmuteSelectedTracks(const CommandContext &context)
Definition: TrackMenus.cpp:713
void OnTrackMoveBottom(const CommandContext &context)
void OnResample(const CommandContext &context)
Definition: TrackMenus.cpp:571
void OnMixAndRenderToNewTrack(const CommandContext &context)
Definition: TrackMenus.cpp:565
void OnTrackPan(const CommandContext &context)
Definition: TrackMenus.cpp:930
static const std::vector< ComponentInterfaceSymbol > & alignLabels()
Definition: TrackMenus.cpp:159
void OnSortName(const CommandContext &context)
Definition: TrackMenus.cpp:905
void OnPanRight(const CommandContext &context)
Definition: TrackMenus.cpp:724
void OnMixAndRender(const CommandContext &context)
Definition: TrackMenus.cpp:559
void OnMuteAllTracks(const CommandContext &context)
Definition: TrackMenus.cpp:698
void OnTrackMoveTop(const CommandContext &context)
void DoAlign(AudacityProject &project, int index, bool moveSel)
Definition: TrackMenus.cpp:169
void SetTrackGain(AudacityProject &project, WaveTrack *wt, LWSlider *slider)
Definition: TrackMenus.cpp:520
void OnTrackPanRight(const CommandContext &context)
Definition: TrackMenus.cpp:956
void OnUnmuteAllTracks(const CommandContext &context)
Definition: TrackMenus.cpp:703
void DoSortTracks(AudacityProject &project, int flags)
Definition: TrackMenus.cpp:461
void OnTrackMoveDown(const CommandContext &context)
void OnTrackGain(const CommandContext &context)
Definition: TrackMenus.cpp:969
void OnRemoveTracks(const CommandContext &context)
Definition: TrackMenus.cpp:674
void OnTrackMute(const CommandContext &context)
void OnTrackMenu(const CommandContext &context)
void OnTrackSolo(const CommandContext &context)
void OnTrackGainDec(const CommandContext &context)
Definition: TrackMenus.cpp:996
void OnPanLeft(const CommandContext &context)
Definition: TrackMenus.cpp:718
void DoPanTracks(AudacityProject &project, float PanValue)
Definition: TrackMenus.cpp:127
void DoMixAndRender(AudacityProject &project, bool toNewTrack)
Definition: TrackMenus.cpp:48
void OnMuteSelectedTracks(const CommandContext &context)
Definition: TrackMenus.cpp:708
void OnTrackGainInc(const CommandContext &context)
Definition: TrackMenus.cpp:983
void OnMoveSelectionWithTracks(const CommandContext &WXUNUSED(context))
Definition: TrackMenus.cpp:761
void SetTrackPan(AudacityProject &project, WaveTrack *wt, LWSlider *slider)
Definition: TrackMenus.cpp:533
static void MuteTracks(const CommandContext &context, bool mute, bool selected)
Definition: TrackMenus.cpp:679
void OnSyncLock(const CommandContext &context)
Definition: TrackMenus.cpp:914
void OnAlignNoSync(const CommandContext &context)
Definition: TrackMenus.cpp:736
void OnTrackMoveUp(const CommandContext &context)
void OnTrackClose(const CommandContext &context)
void OnAlign(const CommandContext &context)
Definition: TrackMenus.cpp:744
void OnStereoToMono(const CommandContext &context)
Definition: TrackMenus.cpp:552
void OnSortTime(const CommandContext &context)
Definition: TrackMenus.cpp:896
void OnTrackPanLeft(const CommandContext &context)
Definition: TrackMenus.cpp:943
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
void rotate(const float *oldPhase, const float *newPhase, std::complex< float > *dst, int32_t n)
Definition: VectorOps.h:140
Options && CheckTest(const CheckFn &fn) &&
Definition: MenuRegistry.h:74
Options && LongName(const TranslatableString &value) &&
Definition: MenuRegistry.h:54
Immutable structure is an argument to Mixer's constructor.
Definition: MixerOptions.h:56