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 "../effects/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
35#include <wx/combobox.h>
36
37#ifdef EXPERIMENTAL_SCOREALIGN
38#include "../effects/ScoreAlignDialog.h"
39#include "audioreader.h"
40#include "scorealign.h"
41#include "scorealign-glue.h"
42#endif /* EXPERIMENTAL_SCOREALIGN */
43
44// private helper classes and functions
45namespace {
46
47void DoMixAndRender(AudacityProject &project, bool toNewTrack)
48{
50 auto &trackFactory = WaveTrackFactory::Get(project);
51 auto rate = ProjectRate::Get(project).GetRate();
52 auto defaultFormat = QualitySettings::SampleFormatChoice();
53 auto &trackPanel = TrackPanel::Get(project);
54
55 auto trackRange = tracks.Selected<WaveTrack>();
56 auto newTrack = ::MixAndRender(trackRange.Filter<const WaveTrack>(),
57 Mixer::WarpOptions{ tracks.GetOwner() },
58 tracks.MakeUniqueTrackName(_("Mix")),
59 &trackFactory, rate, defaultFormat, 0.0, 0.0);
60
61 if (newTrack) {
62 // Remove originals, get stats on what tracks were mixed
63
64 // But before removing, determine the first track after the removal
65 auto last = *trackRange.rbegin();
66 auto insertionPoint = * ++ tracks.Find(last);
67
68 auto selectedCount = trackRange.size();
69 if (!toNewTrack) {
70 // Beware iterator invalidation!
71 while (!trackRange.empty())
72 tracks.Remove(**trackRange.first++);
73 }
74
75 // Add new tracks
76 const bool stereo = newTrack->NChannels() > 1;
77 const auto firstName = newTrack->GetName();
78 tracks.Add(newTrack);
79 const auto pNewTrack = *tracks.Any<WaveTrack>().rbegin();
80
81 // Bug 2218, remember more things...
82 if (selectedCount >= 1)
83 pNewTrack->SetSelected(!toNewTrack);
84
85 // Permute the tracks as needed
86 // The new track appears after the old tracks (or where the old tracks
87 // had been) so that they are in the same sync-lock group
88 if (insertionPoint) {
89 std::vector<Track *> arr;
90 arr.reserve(tracks.Size());
91 size_t iBegin = 0, ii = 0;
92 for (const auto pTrack : tracks) {
93 arr.push_back(pTrack);
94 if (pTrack == insertionPoint)
95 iBegin = ii;
96 ++ii;
97 }
98 const auto end = arr.end(),
99 mid = end - 1;
100 std::rotate(arr.begin() + iBegin, mid, end);
101 tracks.Permute(arr);
102 }
103
104 // Smart history/undo message
105 if (selectedCount == 1) {
106 auto msg = XO("Rendered all audio in track '%s'").Format(firstName);
107 /* i18n-hint: Convert the audio into a more usable form, so apply
108 * panning and amplification and write to some external file.*/
109 ProjectHistory::Get( project ).PushState(msg, XO("Render"));
110 }
111 else {
112 auto msg = (stereo
113 ? XO("Mixed and rendered %d tracks into one new stereo track")
114 : XO("Mixed and rendered %d tracks into one new mono track")
115 )
116 .Format((int)selectedCount);
117 ProjectHistory::Get(project).PushState(msg, XO("Mix and Render"));
118 }
119
120 trackPanel.SetFocus();
121 TrackFocus::Get(project).Set(pNewTrack);
122 Viewport::Get(project).ShowTrack(*pNewTrack);
123 }
124}
125
126void DoPanTracks(AudacityProject &project, float PanValue)
127{
128 auto &tracks = TrackList::Get( project );
129
130 // count selected wave tracks
131 const auto range = tracks.Any< WaveTrack >();
132 const auto selectedRange = range + &Track::IsSelected;
133 auto count = selectedRange.size();
134
135 // iter through them, all if none selected.
136 for (auto left : count == 0 ? range : selectedRange )
137 left->SetPan( PanValue );
138
139 auto flags = UndoPush::NONE;
141 /*i18n-hint: One or more audio tracks have been panned*/
142 .PushState(XO("Panned audio track(s)"), XO("Pan Track"), flags);
143 flags = flags | UndoPush::CONSOLIDATE;
144}
145
146enum {
152 // The next two are only in one subMenu, so more easily handled at the end.
156
157static const std::vector< ComponentInterfaceSymbol >
158&alignLabels() { static std::vector< ComponentInterfaceSymbol > symbols{
159 { wxT("StartToZero"), XXO("Start to &Zero") },
160 { wxT("StartToSelStart"), XXO("Start to &Cursor/Selection Start") },
161 { wxT("StartToSelEnd"), XXO("Start to Selection &End") },
162 { wxT("EndToSelStart"), XXO("End to Cu&rsor/Selection Start") },
163 { wxT("EndToSelEnd"), XXO("End to Selection En&d") },
164}; return symbols; }
165
166const size_t kAlignLabelsCount(){ return alignLabels().size(); }
167
168void DoAlign(AudacityProject &project, int index, bool moveSel)
169{
170 auto &tracks = TrackList::Get( project );
171 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
172 auto &viewport = Viewport::Get(project);
173
174 TranslatableString action, shortAction;
175 double delta = 0.0;
176 double newPos = -1.0;
177
178 auto trackRange = tracks.Selected<AudioTrack>();
179
180 auto FindOffset =
181 [](const Track *pTrack) { return pTrack->GetStartTime(); };
182
183 auto firstTrackOffset = [&]{ return FindOffset( *trackRange.begin() ); };
184 auto minOffset = [&]{ return trackRange.min( FindOffset ); };
185 auto avgOffset = [&]{
186 return trackRange.sum( FindOffset ) /
187 std::max( size_t(1), trackRange.size() ); };
188
189 auto maxEndOffset = [&]{
190 return std::max(0.0, trackRange.max(&Track::GetEndTime)); };
191
192 switch(index) {
193 case kAlignStartZero:
194 delta = -minOffset();
195 action = moveSel
196 /* i18n-hint: In this and similar messages describing editing actions,
197 the starting or ending points of tracks are re-"aligned" to other
198 times, and the time selection may be "moved" too. The first
199 noun -- "start" in this example -- is the object of a verb (not of
200 an implied preposition "from"). */
201 ? XO("Aligned/Moved start to zero")
202 : XO("Aligned start to zero");
203 shortAction = moveSel
204 /* i18n-hint: This and similar messages give shorter descriptions of
205 the aligning and moving editing actions */
206 ? XO("Align/Move Start")
207 : XO("Align Start");
208 break;
210 delta = selectedRegion.t0() - minOffset();
211 action = moveSel
212 ? XO("Aligned/Moved start to cursor/selection start")
213 : XO("Aligned start to cursor/selection start");
214 shortAction = moveSel
215 ? XO("Align/Move Start")
216 : XO("Align Start");
217 break;
219 delta = selectedRegion.t1() - minOffset();
220 action = moveSel
221 ? XO("Aligned/Moved start to selection end")
222 : XO("Aligned start to selection end");
223 shortAction = moveSel
224 ? XO("Align/Move Start")
225 : XO("Align Start");
226 break;
228 delta = selectedRegion.t0() - maxEndOffset();
229 action = moveSel
230 ? XO("Aligned/Moved end to cursor/selection start")
231 : XO("Aligned end to cursor/selection start");
232 shortAction =
233 moveSel
234 ? XO("Align/Move End")
235 : XO("Align End");
236 break;
237 case kAlignEndSelEnd:
238 delta = selectedRegion.t1() - maxEndOffset();
239 action = moveSel
240 ? XO("Aligned/Moved end to selection end")
241 : XO("Aligned end to selection end");
242 shortAction =
243 moveSel
244 ? XO("Align/Move End")
245 : XO("Align End");
246 break;
247 // index set in alignLabelsNoSync
248 case kAlignEndToEnd:
249 newPos = firstTrackOffset();
250 action = moveSel
251 ? XO("Aligned/Moved end to end")
252 : XO("Aligned end to end");
253 shortAction =
254 moveSel
255 ? XO("Align/Move End to End")
256 : XO("Align End to End");
257 break;
258 case kAlignTogether:
259 newPos = avgOffset();
260 action = moveSel
261 ? XO("Aligned/Moved together")
262 : XO("Aligned together");
263 shortAction =
264 moveSel
265 ? XO("Align/Move Together")
266 : XO("Align Together");
267 }
268
269 if ((unsigned)index >= kAlignLabelsCount()) {
270 // This is an alignLabelsNoSync command.
271 for (auto t : tracks.Selected<AudioTrack>()) {
272 // This shifts different tracks in different ways, so no sync-lock
273 // move.
274 // Only align Wave and Note tracks end to end.
275 t->MoveTo(newPos);
276 if (index == kAlignEndToEnd)
277 newPos += (t->GetEndTime() - t->GetStartTime());
278 }
279 if (index == kAlignEndToEnd)
280 viewport.ZoomFitHorizontally();
281 }
282
283 if (delta != 0.0) {
284 // For a fixed-distance shift move sync-lock selected tracks also.
285 for (auto t : tracks.Any()
287 t->MoveTo(t->GetStartTime() + delta);
288 }
289
290 if (moveSel)
291 selectedRegion.move(delta);
292
293 ProjectHistory::Get( project ).PushState(action, shortAction);
294}
295
296#ifdef EXPERIMENTAL_SCOREALIGN
297
298#ifdef USE_MIDI
299static const ReservedCommandFlag&
300 NoteTracksSelectedFlag() { static ReservedCommandFlag flag{
301 [](const AudacityProject &project){
302 return !TrackList::Get( project ).Selected<const NoteTrack>().empty();
303 }
304 }; return flag; } //gsw
305#endif
306
307// rough relative amount of time to compute one
308// frame of audio or midi, or one cell of matrix, or one iteration
309// of smoothing, measured on a 1.9GHz Core 2 Duo in 32-bit mode
310// (see COLLECT_TIMING_DATA below)
311#define AUDIO_WORK_UNIT 0.004F
312#define MIDI_WORK_UNIT 0.0001F
313#define MATRIX_WORK_UNIT 0.000002F
314#define SMOOTHING_WORK_UNIT 0.000001F
315
316// Write timing data to a file; useful for calibrating AUDIO_WORK_UNIT,
317// MIDI_WORK_UNIT, MATRIX_WORK_UNIT, and SMOOTHING_WORK_UNIT coefficients
318// Data is written to timing-data.txt; look in
319// audacity-src/win/Release/modules/
320#define COLLECT_TIMING_DATA
321
322// Audacity Score Align Progress class -- progress reports come here
323class ASAProgress final : public SAProgress {
324 private:
325 float mTotalWork;
326 float mFrames[2];
327 long mTotalCells; // how many matrix cells?
328 long mCellCount; // how many cells so far?
329 long mPrevCellCount; // cell_count last reported with Update()
330 std::optional<ProgressDialog> mProgress;
331 #ifdef COLLECT_TIMING_DATA
332 FILE *mTimeFile;
333 wxDateTime mStartTime;
334 long iterations;
335 #endif
336
337 public:
338 ASAProgress() {
339 smoothing = false;
340 #ifdef COLLECT_TIMING_DATA
341 mTimeFile = fopen("timing-data.txt", "w");
342 #endif
343 }
344 ~ASAProgress() {
345 #ifdef COLLECT_TIMING_DATA
346 fclose(mTimeFile);
347 #endif
348 }
349 void set_phase(int i) override {
350 float work[2]; // chromagram computation work estimates
351 float work2, work3 = 0; // matrix and smoothing work estimates
352 SAProgress::set_phase(i);
353 #ifdef COLLECT_TIMING_DATA
354 long ms = 0;
355 wxDateTime now = wxDateTime::UNow();
356 wxFprintf(mTimeFile, "Phase %d begins at %s\n",
357 i, now.FormatTime());
358 if (i != 0)
359 ms = now.Subtract(mStartTime).GetMilliseconds().ToLong();
360 mStartTime = now;
361 #endif
362 if (i == 0) {
363 mCellCount = 0;
364 for (int j = 0; j < 2; j++) {
365 mFrames[j] = durations[j] / frame_period;
366 }
367 mTotalWork = 0;
368 for (int j = 0; j < 2; j++) {
369 work[j] =
370 (is_audio[j] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[j];
371 mTotalWork += work[j];
372 }
373 mTotalCells = mFrames[0] * mFrames[1];
374 work2 = mTotalCells * MATRIX_WORK_UNIT;
375 mTotalWork += work2;
376 // arbitrarily assume 60 iterations to fit smooth segments and
377 // per frame per iteration is SMOOTHING_WORK_UNIT
378 if (smoothing) {
379 work3 =
380 wxMax(mFrames[0], mFrames[1]) * SMOOTHING_WORK_UNIT * 40;
381 mTotalWork += work3;
382 }
383 #ifdef COLLECT_TIMING_DATA
384 wxFprintf(mTimeFile,
385 " mTotalWork (an estimate) = %g\n", mTotalWork);
386 wxFprintf(mTimeFile, " work0 = %g, frames %g, is_audio %d\n",
387 work[0], mFrames[0], is_audio[0]);
388 wxFprintf(mTimeFile, " work1 = %g, frames %g, is_audio %d\n",
389 work[1], mFrames[1], is_audio[1]);
390 wxFprintf(mTimeFile, "work2 = %g, work3 = %g\n", work2, work3);
391 #endif
392 mProgress.emplace(XO("Synchronize MIDI with Audio"),
393 XO("Synchronizing MIDI and Audio Tracks"));
394 } else if (i < 3) {
395 wxFprintf(mTimeFile,
396 "Phase %d took %d ms for %g frames, coefficient = %g s/frame\n",
397 i - 1, ms, mFrames[i - 1], (ms * 0.001) / mFrames[i - 1]);
398 } else if (i == 3) {
399 wxFprintf(mTimeFile,
400 "Phase 2 took %d ms for %d cells, coefficient = %g s/cell\n",
401 ms, mCellCount, (ms * 0.001) / mCellCount);
402 } else if (i == 4) {
403 wxFprintf(mTimeFile,
404 "Phase 3 took %d ms for %d iterations on %g frames, "
405 "coefficient = %g s per frame per iteration\n",
406 ms, iterations, wxMax(mFrames[0], mFrames[1]),
407 (ms * 0.001) / (wxMax(mFrames[0], mFrames[1]) * iterations));
408 }
409 }
410 bool set_feature_progress(float s) override {
411 float work;
412 if (phase == 0) {
413 float f = s / frame_period;
414 work = (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * f;
415 } else if (phase == 1) {
416 float f = s / frame_period;
417 work = (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
418 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * f;
419 }
420 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
421 return (updateResult == ProgressResult::Success);
422 }
423 bool set_matrix_progress(int cells) override {
424 mCellCount += cells;
425 float work =
426 (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
427 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[1];
428 work += mCellCount * MATRIX_WORK_UNIT;
429 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
430 return (updateResult == ProgressResult::Success);
431 }
432 bool set_smoothing_progress(int i) override {
433 iterations = i;
434 float work =
435 (is_audio[0] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[0] +
436 (is_audio[1] ? AUDIO_WORK_UNIT : MIDI_WORK_UNIT) * mFrames[1] +
437 MATRIX_WORK_UNIT * mFrames[0] * mFrames[1];
438 work += i * wxMax(mFrames[0], mFrames[1]) * SMOOTHING_WORK_UNIT;
439 auto updateResult = mProgress->Update((int)(work), (int)(mTotalWork));
440 return (updateResult == ProgressResult::Success);
441 }
442};
443
444
445long mixer_process(void *mixer, float **buffer, long n)
446{
447 Mixer *mix = (Mixer *) mixer;
448 long frame_count = mix->Process(std::max(0L, n));
449 *buffer = (float *) mix->GetBuffer();
450 return frame_count;
451}
452
453#endif // EXPERIMENTAL_SCOREALIGN
454
455enum{
458};
459
461{
462 auto GetTime = [](const Track &t) {
463 return t.TypeSwitch<double>(
464 [&](const WaveTrack &w) {
465 auto stime = w.GetEndTime();
466
467 int ndx;
468 for (ndx = 0; ndx < w.GetNumClips(); ndx++) {
469 const auto c = w.GetClip(ndx);
470 if (c->GetVisibleSampleCount() == 0)
471 continue;
472 stime = std::min(stime, c->GetPlayStartTime());
473 }
474 return stime;
475 },
476 [&](const LabelTrack& l) {
477 return l.GetStartTime();
478 }
479 );
480 };
481
482 std::vector<Track *> arr;
484 arr.reserve(tracks.Size());
485
486 // First find the permutation.
487 for (const auto pTrack : tracks) {
488 auto &track = *pTrack;
489 const auto size = arr.size();
490 size_t ndx = 0;
491 for (; ndx < size; ++ndx) {
492 Track &arrTrack = *arr[ndx];
493 if (flags & kAudacitySortByName) {
494 //do case insensitive sort - cmpNoCase returns less than zero if
495 // the string is 'less than' its argument
496 //also if we have case insensitive equality, then we need to sort
497 // by case as well
498 //We sort 'b' before 'B' accordingly. We uncharacteristically
499 // use greater than for the case sensitive
500 //compare because 'b' is greater than 'B' in ascii.
501 auto cmpValue = track.GetName().CmpNoCase(arrTrack.GetName());
502 if (cmpValue < 0 ||
503 (0 == cmpValue &&
504 track.GetName().CompareTo(arrTrack.GetName()) > 0))
505 break;
506 }
507 //sort by time otherwise
508 else if (flags & kAudacitySortByTime)
509 if (GetTime(track) < GetTime(arrTrack))
510 break;
511 }
512 arr.insert(arr.begin() + ndx, &track);
513 }
514
515 // Now apply the permutation
516 tracks.Permute(arr);
517}
518
520{
521 wxASSERT(wt);
522 float newValue = slider->Get();
523
524 wt->SetGain(newValue);
525
527 .PushState(XO("Adjusted gain"), XO("Gain"), UndoPush::CONSOLIDATE);
528
530}
531
533{
534 wxASSERT(wt);
535 float newValue = slider->Get();
536
537 wt->SetPan(newValue);
538
540 .PushState(XO("Adjusted Pan"), XO("Pan"), UndoPush::CONSOLIDATE);
541
543}
544
545}
546
547namespace {
548
549// Menu handler functions
550
551void OnStereoToMono(const CommandContext &context)
552{
554 EffectManager::Get().GetEffectByIdentifier(wxT("StereoToMono")),
555 context,
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::GainSlider( 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::GainSlider( 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::GainSlider( 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 =
1141 EffectManager::Get().GetEffectByIdentifier(wxT("StereoToMono"));
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("&Close Focused 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
Definition: Distortion.cpp:77
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:9
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, amplitude gain, panning, and real-time effec...
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:69
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 then return the current value.
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
static EffectManager & Get()
const PluginID & GetEffectByIdentifier(const CommandID &strTarget)
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:1593
void Increase(float steps)
Definition: ASlider.cpp:1570
float Get(bool convert=true)
Definition: ASlider.cpp:1545
bool ShowDialog()
Definition: ASlider.cpp:1114
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:95
Functions for doing the mixdown of the tracks.
Definition: Mix.h:27
size_t Process(size_t maxSamples)
Definition: Mix.cpp:271
constSamplePtr GetBuffer()
Retrieve the main buffer or the interleaved buffer.
Definition: Mix.cpp:378
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:397
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
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:215
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void ShowTrack(const Track &track)
Definition: Viewport.cpp:456
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
static LWSlider * PanSlider(CellularPanel &panel, const WaveTrack &wt)
static LWSlider * GainSlider(CellularPanel &panel, const WaveTrack &wt)
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:3349
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
void SetPan(float newPan)
Definition: WaveTrack.cpp:847
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2586
void SetGain(float newGain)
Definition: WaveTrack.cpp:829
size_t NChannels() const override
A constant property.
Definition: WaveTrack.cpp:532
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:294
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1148
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:158
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:168
void SetTrackGain(AudacityProject &project, WaveTrack *wt, LWSlider *slider)
Definition: TrackMenus.cpp:519
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:460
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:126
void DoMixAndRender(AudacityProject &project, bool toNewTrack)
Definition: TrackMenus.cpp:47
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:532
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:551
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