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