Audacity 3.2.0
TranscriptionToolBar.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 TranscriptionToolBar.cpp
6
7 Shane T. Mueller
8 Leland Lucius
9
10*******************************************************************//*******************************************************************/
16
17
19#include "ToolManager.h"
20
21// For compilers that support precompilation, includes "wx/wx.h".
22#include <wx/wxprec.h>
23
24#ifndef WX_PRECOMP
25#include <wx/choice.h>
26#include <wx/defs.h>
27#include <wx/brush.h>
28#endif // WX_PRECOMP
29
30#include "Envelope.h"
31
32#include "AllThemeResources.h"
33#include "AudioIO.h"
34#include "ImageManipulation.h"
35#include "../KeyboardCapture.h"
36#include "NoteTrack.h"
37#include "Project.h"
38#include "ProjectAudioIO.h"
39#include "../ProjectAudioManager.h"
40#include "Envelope.h"
41#include "ViewInfo.h"
42#include "WaveTrack.h"
43#include "../widgets/AButton.h"
44#include "../widgets/ASlider.h"
45#include "../tracks/ui/Scrubbing.h"
46#include "Prefs.h"
47
48#ifdef EXPERIMENTAL_VOICE_DETECTION
49#include "../VoiceKey.h"
50#include "../ProjectWindow.h"
51#endif
52
54
58
59
60BEGIN_EVENT_TABLE(TranscriptionToolBar, ToolBar)
62 EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, TranscriptionToolBar::OnCaptureKey)
63
66 EVT_SLIDER(TTB_PlaySpeedSlider, TranscriptionToolBar::OnSpeedSlider)
67
68#ifdef EXPERIMENTAL_VOICE_DETECTION
69 EVT_COMMAND_RANGE(TTB_StartOn, TTB_StartOn,
70 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnStartOn)
71 EVT_COMMAND_RANGE(TTB_StartOff, TTB_StartOff,
72 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnStartOff)
73 EVT_COMMAND_RANGE(TTB_EndOn, TTB_EndOn,
74 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnEndOn)
75 EVT_COMMAND_RANGE(TTB_EndOff, TTB_EndOff,
76 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnEndOff)
77 EVT_COMMAND_RANGE(TTB_SelectSound, TTB_SelectSound,
78 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnSelectSound)
79 EVT_COMMAND_RANGE(TTB_SelectSilence, TTB_SelectSilence,
80 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnSelectSilence)
81 EVT_COMMAND_RANGE(TTB_AutomateSelection, TTB_AutomateSelection,
82 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnAutomateSelection)
83 EVT_COMMAND_RANGE(TTB_MakeLabel, TTB_MakeLabel,
84 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnMakeLabel)
85 EVT_COMMAND_RANGE(TTB_Calibrate, TTB_Calibrate,
86 wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnCalibrate)
87 EVT_SLIDER(TTB_SensitivitySlider, TranscriptionToolBar::OnSensitivitySlider)
88
89 EVT_CHOICE(TTB_KeyType, TranscriptionToolBar::SetKeyType)
90#endif
92 ; //semicolon enforces proper automatic indenting in emacs.
93
95{
96 return wxT("Transcription");
97}
98
101: ToolBar( project, XO("Play-at-Speed"), ID(), true )
102{
103 SetPlaySpeed( 1.0 * 100.0 );
104#ifdef EXPERIMENTAL_VOICE_DETECTION
105 mVk = std::make_unique<VoiceKey>();
106#endif
107}
108
110{
111}
112
114{
115 return
116#ifdef EXPERIMENTAL_DA
117 false
118#else
119 true
120#endif
121 ;
122}
123
125{
126 return BotDockID;
127}
128
130{
131 auto &toolManager = ToolManager::Get( project );
132 return *static_cast<TranscriptionToolBar*>(toolManager.GetToolBar(ID()));
133}
134
136{
137 return Get( const_cast<AudacityProject&>( project )) ;
138}
139
140void TranscriptionToolBar::Create(wxWindow * parent)
141{
142 ToolBar::Create(parent);
143
146
147#ifdef EXPERIMENTAL_VOICE_DETECTION
148 mButtons[TTB_StartOn]->Disable();
149 mButtons[TTB_StartOff]->Disable();
150 mButtons[TTB_EndOn]->Disable();
151 mButtons[TTB_EndOff]->Disable();
152 mButtons[TTB_SelectSound]->Disable();
153 mButtons[TTB_SelectSilence]->Disable();
154 mButtons[TTB_Calibrate]->Enable();
155 mButtons[TTB_AutomateSelection]->Disable();
156 mButtons[TTB_MakeLabel]->Enable();
157#endif
158
159 //Old code...
160 //Process a dummy event to set up mPlaySpeed
161 //wxCommandEvent dummy;
162 //OnSpeedSlider(dummy);
163
164 //JKC: Set speed this way is better, as we don't
165 //then stop Audio if it is playing, so we can be playing
166 //audio and open a second project.
167 SetPlaySpeed( (mPlaySpeedSlider->Get()) * 100 );
168
169 // Simulate a size event to set initial placement/size
170 wxSizeEvent event(GetSize(), GetId());
171 event.SetEventObject(this);
172 GetEventHandler()->ProcessEvent(event);
173}
174
176{
177 mPlaySpeed = value;
179}
180
186 teBmps eFore, teBmps eDisabled,
187 int id,
189{
190 AButton *&r = pBar->mButtons[id];
191
192 r = ToolBar::MakeButton(pBar,
193 bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall,bmpRecoloredHiliteSmall,
194 eFore, eFore, eDisabled,
195 wxWindowID(id),
196 wxDefaultPosition,
197 false,
198 theTheme.ImageSize( bmpRecoloredUpSmall ));
199
200 r->SetLabel(label);
201// JKC: Unlike ControlToolBar, does not have a focus rect. Shouldn't it?
202// r->SetFocusRect( r->GetRect().Deflate( 4, 4 ) );
203
204 pBar->Add( r, 0, wxALIGN_CENTER );
205
206 return r;
207}
208
210 teBmps eFore, teBmps eDisabled,
211 int id, unsigned altIdx)
212{
214 bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall,bmpRecoloredHiliteSmall,
215 eFore, eFore, eDisabled,
216 theTheme.ImageSize( bmpRecoloredUpSmall ));
217}
218
220{
221 SetBackgroundColour( theTheme.Colour( clrMedium ) );
222// Very similar to code in ControlToolBar...
223// Very similar to code in EditToolBar
225
226 AddButton(this, bmpPlay, bmpPlayDisabled, TTB_PlaySpeed,
227 XO("Play at selected speed"));
228 // 3.1.0 abandoned distinct images for Shift
229 MakeAlternateImages(bmpPlay, bmpPlayDisabled, TTB_PlaySpeed, 1);
230 MakeAlternateImages(bmpCutPreview, bmpCutPreviewDisabled, TTB_PlaySpeed, 2);
232
233 //Add a slider that controls the speed of playback.
234 const int SliderWidth=100;
237 XO("Playback Speed"),
238 wxDefaultPosition,
239 wxSize(SliderWidth,25),
242 // 6 steps using page up/down, and 60 using arrow keys
243 .Line( 0.16667f )
244 .Page( 1.6667f )
245 );
246 mPlaySpeedSlider->SetSizeHints(wxSize(100, 25), wxSize(2000, 25));
248 mPlaySpeedSlider->SetLabel(_("Playback Speed"));
249 Add( mPlaySpeedSlider, 1, wxALIGN_CENTER );
250 mPlaySpeedSlider->Bind(wxEVT_SET_FOCUS,
252 this);
253 mPlaySpeedSlider->Bind(wxEVT_KILL_FOCUS,
255 this);
256
257#ifdef EXPERIMENTAL_VOICE_DETECTION
258// If we need these strings translated, then search and replace
259// YO by XO and remove this #define.
260#define YO( x ) Verbatim( x )
261 AddButton(this, bmpTnStartOn, bmpTnStartOnDisabled, TTB_StartOn,
262 YO("Adjust left selection to next onset"));
263 AddButton(this, bmpTnEndOn, bmpTnEndOnDisabled, TTB_EndOn,
264 YO("Adjust right selection to previous offset"));
265 AddButton(this, bmpTnStartOff, bmpTnStartOffDisabled, TTB_StartOff,
266 YO("Adjust left selection to next offset"));
267 AddButton(this, bmpTnEndOff, bmpTnEndOffDisabled, TTB_EndOff,
268 YO("Adjust right selection to previous onset"));
269 AddButton(this, bmpTnSelectSound, bmpTnSelectSoundDisabled, TTB_SelectSound,
270 YO("Select region of sound around cursor"));
271 AddButton(this, bmpTnSelectSilence, bmpTnSelectSilenceDisabled, TTB_SelectSilence,
272 YO("Select region of silence around cursor"));
273 AddButton(this, bmpTnAutomateSelection, bmpTnAutomateSelectionDisabled, TTB_AutomateSelection,
274 YO("Automatically make labels from words"));
275 AddButton(this, bmpTnMakeTag, bmpTnMakeTagDisabled, TTB_MakeLabel,
276 YO("Add label at selection"));
277 AddButton(this, bmpTnCalibrate, bmpTnCalibrateDisabled, TTB_Calibrate,
278 YO("Calibrate voicekey"));
279
281 TTB_SensitivitySlider,
282 YO("Adjust Sensitivity"),
283 wxDefaultPosition,
284 wxSize(SliderWidth,25),
286 .Style( SPEED_SLIDER ));
288 mSensitivitySlider->SetLabel(YO("Sensitivity").Translation());
289 Add( mSensitivitySlider, 0, wxALIGN_CENTER );
290
291 TranslatableStrings choices {
292 YO("Energy"),
293 YO("Sign Changes (Low Threshold)"),
294 YO("Sign Changes (High Threshold)"),
295 YO("Direction Changes (Low Threshold)"),
296 YO("Direction Changes (High Threshold)")
297 };
298
299 mKeyTypeChoice = safenew wxChoice(this, TTB_KeyType,
300 wxDefaultPosition,
301 wxDefaultSize,
302 transform_container<wxArrayStringEx>( choices,
303 std::mem_fn( &TranslatableString::Translation ) ) );
304 mKeyTypeChoice->SetName(YO("Key type").Translation());
305 mKeyTypeChoice->SetSelection(0);
306 Add( mKeyTypeChoice, 0, wxALIGN_CENTER );
307#endif
308
309 // Add a little space
310 Add(2, -1);
311
312 UpdatePrefs();
313}
314
316{
318
319 auto gAudioIO = AudioIO::Get();
320 bool canStopAudioStream = (!gAudioIO->IsStreamActive() ||
321 gAudioIO->IsMonitoring() ||
322 gAudioIO->GetOwningProject().get() == p );
323 bool recording = gAudioIO->GetNumCaptureChannels() > 0;
324
325 // Only interested in audio type tracks
326 bool tracks = p && TrackList::Get(*p).Any<AudioTrack>(); // PRL: PlayableTrack ?
327 SetEnabled(canStopAudioStream && tracks && !recording);
328
329#ifdef EXPERIMENTAL_VOICE_DETECTION
330 if (!p)
331 return;
332 // Is anything selected?
333 const auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
334 auto selection = !selectedRegion.isPoint() &&
335 !TrackList::Get( *p ).Selected().empty();
336
337 mButtons[TTB_Calibrate]->SetEnabled(selection);
338#endif
339}
340
342{
344
345 // Set label to pull in language change
346 SetLabel(XO("Play-at-Speed"));
347
348 // Give base class a chance
350}
351
353{
354 // We could also mention the shift- and ctrl-modified versions in the
355 // tool tip... but it would get long
356
357 static const struct Entry {
358 int tool;
359 CommandID commandName;
360 TranslatableString untranslatedLabel;
361 CommandID commandName2;
362 TranslatableString untranslatedLabel2;
363 } table[] = {
365 wxT("PlayAtSpeedLooped"), XO("Play-at-Speed"),
366 wxT("PlayAtSpeed"), XO("Play-at-Speed Once"),
367 },
368 };
369
370 for (const auto &entry : table) {
371 ComponentInterfaceSymbol commands[] = {
372 { entry.commandName, entry.untranslatedLabel },
373 { entry.commandName2, entry.untranslatedLabel2 },
374 };
376 *mButtons[entry.tool], commands, 2u );
377 }
378
379#ifdef EXPERIMENTAL_VOICE_DETECTION
380 mButtons[TTB_StartOn]->SetToolTip(YO("Left-to-On"));
381 mButtons[TTB_EndOn]->SetToolTip( YO("Right-to-Off"));
382 mButtons[TTB_StartOff]->SetToolTip( YO("Left-to-Off"));
383 mButtons[TTB_EndOff]->SetToolTip( YO("Right-to-On"));
384 mButtons[TTB_SelectSound]->SetToolTip( YO("Select-Sound"));
385 mButtons[TTB_SelectSilence]->SetToolTip( YO("Select-Silence"));
386 mButtons[TTB_AutomateSelection]->SetToolTip( YO("Make Labels"));
387 mButtons[TTB_MakeLabel]->SetToolTip( YO("Add Label"));
388 mButtons[TTB_Calibrate]->SetToolTip( YO("Calibrate"));
389
390 mSensitivitySlider->SetToolTip(YO("Sensitivity").Translation());
391 mKeyTypeChoice->SetToolTip(YO("Key type").Translation());
392#endif
393}
394
395void TranscriptionToolBar::OnFocus(wxFocusEvent &event)
396{
397 KeyboardCapture::OnFocus( *this, event );
398}
399
400void TranscriptionToolBar::OnCaptureKey(wxCommandEvent &event)
401{
402 wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
403 int keyCode = kevent->GetKeyCode();
404
405 // Pass LEFT/RIGHT/UP/DOWN/PAGEUP/PAGEDOWN through for input/output sliders
406 if (FindFocus() == mPlaySpeedSlider && (keyCode == WXK_LEFT || keyCode == WXK_RIGHT
407 || keyCode == WXK_UP || keyCode == WXK_DOWN
408 || keyCode == WXK_PAGEUP || keyCode == WXK_PAGEDOWN)) {
409 return;
410 }
411
412 event.Skip();
413
414 return;
415}
416
417//This handles key-stroke events????
418void TranscriptionToolBar::OnKeyEvent(wxKeyEvent & event)
419{
420 if (event.ControlDown()) {
421 event.Skip();
422 return;
423 }
424
425 if (event.GetKeyCode() == WXK_SPACE) {
426 auto gAudioIO = AudioIOBase::Get();
427 if (gAudioIO->IsBusy()) {
428 /*Do Stuff Here*/
429 }
430 else {
431 /*Do other stuff Here*/
432 }
433 }
434}
435
436
437
438//This changes the state of the various buttons
440{
441 if (down) {
442 button->PushDown();
443 }
444 else {
445 button->PopUp();
446 }
447}
448
450 const WaveTrack *t, sampleCount *s0, sampleCount *slen)
451{
452 // GetSamples attempts to translate the start and end selection markers into sample indices
453 // These selection numbers are doubles.
454
456 if (!p) {
457 return;
458 }
459
460 //First, get the current selection. It is part of the mViewInfo, which is
461 //part of the project
462
463 const auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
464 double start = selectedRegion.t0();
465 double end = selectedRegion.t1();
466
467 auto ss0 = sampleCount( (start - t->GetStartTime()) * t->GetRate() );
468 auto ss1 = sampleCount( (end - t->GetStartTime()) * t->GetRate() );
469
470 if (start < t->GetStartTime()) {
471 ss0 = 0;
472 }
473
474#if 0
475 //This adjusts the right samplecount to the maximum sample.
476 if (ss1 >= t->GetNumSamples()) {
477 ss1 = t->GetNumSamples();
478 }
479#endif
480
481 if (ss1 < ss0) {
482 ss1 = ss0;
483 }
484
485 *s0 = ss0;
486 *slen = ss1 - ss0;
487}
488
489// PRL: duplicating constants from TimeTrack.cpp
490//TODO-MB: are these sensible values?
491#define TIMETRACK_MIN 0.01
492#define TIMETRACK_MAX 10.0
493
494// Come here from button clicks, or commands
495void TranscriptionToolBar::PlayAtSpeed(bool newDefault, bool cutPreview)
496{
497 // Can't do anything without an active project
499 if (!p) {
500 return;
501 }
502
503 auto &projectAudioManager = ProjectAudioManager::Get( mProject );
504
505 // Fixed speed play is the old method, that uses a time track.
506 // VariSpeed play reuses Scrubbing.
507 bool bFixedSpeedPlay = !gPrefs->ReadBool(wxT("/AudioIO/VariSpeedPlay"), true);
508 // Scrubbing doesn't support note tracks, but the fixed-speed method using time tracks does.
509 if (TrackList::Get(*p).Any<NoteTrack>())
510 bFixedSpeedPlay = true;
511
512 // If cutPreview, we have to fall back to fixed speed.
513 if (newDefault)
514 cutPreview = false;
515 bFixedSpeedPlay = bFixedSpeedPlay || cutPreview;
516 if (bFixedSpeedPlay)
517 {
518 // Create a BoundedEnvelope if we haven't done so already
519 if (!mEnvelope) {
520 mEnvelope =
521 std::make_unique<BoundedEnvelope>(
522 true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
523 // values as in the constructor for TimeTrack
524 mEnvelope->SetRangeLower( 0.9 );
525 mEnvelope->SetRangeUpper( 1.1 );
526 }
527 // Set the speed range
528 //mTimeTrack->SetRangeUpper((double)mPlaySpeed / 100.0);
529 //mTimeTrack->SetRangeLower((double)mPlaySpeed / 100.0);
530 mEnvelope->Flatten((double)mPlaySpeed / 100.0);
531 }
532
533 // Pop up the button
535
536 // If IO is busy, abort immediately
537 auto gAudioIO = AudioIOBase::Get();
538 if (gAudioIO->IsBusy())
539 projectAudioManager.Stop();
540
541 // Get the current play region
542 const auto &viewInfo = ViewInfo::Get( *p );
543 const auto &playRegion = viewInfo.playRegion;
544
545 // Start playing
546 if (playRegion.GetStart() < 0)
547 return;
548
549 {
550 auto options = ProjectAudioIO::GetDefaultOptions(*p, newDefault);
551 // No need to set cutPreview options.
552 options.envelope = bFixedSpeedPlay ? mEnvelope.get() : nullptr;
553 options.variableSpeed = !bFixedSpeedPlay;
554 auto mode =
555 cutPreview ? PlayMode::cutPreviewPlay
556 : newDefault ? PlayMode::loopedPlay
558 projectAudioManager.PlayPlayRegion(
559 SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()),
560 options,
561 mode);
562 }
563}
564
565// Come here from button clicks only
566void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & event)
567{
568 auto button = mButtons[TTB_PlaySpeed];
569
570 // Let control have precedence over shift
571 const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
572 const bool looped = !cutPreview &&
573 !button->WasShiftDown();
574 OnSpeedSlider(event);
575 PlayAtSpeed(looped, cutPreview);
576}
577
578void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
579{
580 SetPlaySpeed( (mPlaySpeedSlider->Get()) * 100 );
582
583 // If IO is busy, abort immediately
584 // AWD: This is disabled to work around a hang on Linux when PulseAudio is
585 // used. If we figure that one out we can re-enable this code.
586 // auto gAudioIO = AudioIOBase::Get();
587 //if (gAudioIO->IsBusy()) {
588 // OnPlaySpeed(event);
589 //}
590}
591
592#ifdef EXPERIMENTAL_VOICE_DETECTION
593void TranscriptionToolBar::OnStartOn(wxCommandEvent & WXUNUSED(event))
594{
595 //If IO is busy, abort immediately
596 auto gAudioIO = AudioIOBase::Get();
597 if (gAudioIO->IsBusy()){
598 SetButton(false,mButtons[TTB_StartOn]);
599 return;
600 }
601
602 mVk->AdjustThreshold(GetSensitivity());
603
604 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
605 if(t ) {
606 auto wt = static_cast<const WaveTrack*>(t);
607 sampleCount start, len;
608 GetSamples(wt, &start, &len);
609
610 //Adjust length to end if selection is null
611 //if(len == 0)
612 //len = wt->GetSequence()->GetNumSamples()-start;
613
614 auto newstart = mVk->OnForward(*wt, start, len);
615 double newpos = newstart.as_double() / wt->GetRate();
616
617 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
618 selectedRegion.setT0( newpos );
620
621 SetButton(false, mButtons[TTB_StartOn]);
622 }
623}
624
625void TranscriptionToolBar::OnStartOff(wxCommandEvent & WXUNUSED(event))
626{
627 //If IO is busy, abort immediately
628 auto gAudioIO = AudioIOBase::Get();
629 if (gAudioIO->IsBusy()){
630 SetButton(false,mButtons[TTB_StartOff]);
631 return;
632 }
633 mVk->AdjustThreshold(GetSensitivity());
635
636 SetButton(false, mButtons[TTB_StartOff]);
637 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
638 if(t) {
639 auto wt = static_cast<const WaveTrack*>(t);
640 sampleCount start, len;
641 GetSamples(wt, &start, &len);
642
643 //Adjust length to end if selection is null
644 //if(len == 0)
645 //len = wt->GetSequence()->GetNumSamples()-start;
646
647 auto newstart = mVk->OffForward(*wt, start, len);
648 double newpos = newstart.as_double() / wt->GetRate();
649
650 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
651 selectedRegion.setT0( newpos );
653
654 SetButton(false, mButtons[TTB_StartOn]);
655 }
656}
657
658void TranscriptionToolBar::OnEndOn(wxCommandEvent & WXUNUSED(event))
659{
660
661 //If IO is busy, abort immediately
662 auto gAudioIO = AudioIOBase::Get();
663 if (gAudioIO->IsBusy()){
664 SetButton(false,mButtons[TTB_EndOn]);
665 return;
666 }
667
668 mVk->AdjustThreshold(GetSensitivity());
670 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
671 if(t) {
672 auto wt = static_cast<const WaveTrack*>(t);
673 sampleCount start, len;
674 GetSamples(wt, &start, &len);
675
676 //Adjust length to end if selection is null
677 if(len == 0)
678 {
679 len = start;
680 start = 0;
681 }
682 auto newEnd = mVk->OnBackward(*wt, start + len, len);
683 double newpos = newEnd.as_double() / wt->GetRate();
684
685 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
686 selectedRegion.setT1( newpos );
688
689 SetButton(false, mButtons[TTB_EndOn]);
690 }
691}
692
693
694
695void TranscriptionToolBar::OnEndOff(wxCommandEvent & WXUNUSED(event))
696{
697
698 //If IO is busy, abort immediately
699 auto gAudioIO = AudioIOBase::Get();
700 if (gAudioIO->IsBusy()){
701 SetButton(false,mButtons[TTB_EndOff]);
702 return;
703 }
704 mVk->AdjustThreshold(GetSensitivity());
706
707 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
708 if(t) {
709 auto wt = static_cast<const WaveTrack*>(t);
710 sampleCount start, len;
711 GetSamples(wt, &start, &len);
712
713 //Adjust length to end if selection is null
714 if(len == 0) {
715 len = start;
716 start = 0;
717 }
718 auto newEnd = mVk->OffBackward(*wt, start + len, len);
719 double newpos = newEnd.as_double() / wt->GetRate();
720
721 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
722 selectedRegion.setT1( newpos );
724
725 SetButton(false, mButtons[TTB_EndOff]);
726 }
727}
728
729
730
731void TranscriptionToolBar::OnSelectSound(wxCommandEvent & WXUNUSED(event))
732{
733
734 //If IO is busy, abort immediately
735 auto gAudioIO = AudioIOBase::Get();
736 if (gAudioIO->IsBusy()){
737 SetButton(false,mButtons[TTB_SelectSound]);
738 return;
739 }
740
741
742 mVk->AdjustThreshold(GetSensitivity());
743
744
746 if(auto wt = *tl->Any<const WaveTrack>().begin()) {
747 sampleCount start, len;
748 GetSamples(wt, &start, &len);
749
750 //Adjust length to end if selection is null
751 //if(len == 0)
752 //len = wt->GetSequence()->GetNumSamples()-start;
753
754 double rate = wt->GetRate();
755 auto newstart = mVk->OffBackward(*wt, start, start);
756 auto newend =
757 mVk->OffForward(*wt, start + len, (int)(tl->GetEndTime() * rate));
758
759 //reset the selection bounds.
760 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
761 selectedRegion.setTimes(
762 newstart.as_double() / rate, newend.as_double() / rate );
764
765 }
766
767 SetButton(false,mButtons[TTB_SelectSound]);
768}
769
770void TranscriptionToolBar::OnSelectSilence(wxCommandEvent & WXUNUSED(event))
771{
772
773 //If IO is busy, abort immediately
774 auto gAudioIO = AudioIOBase::Get();
775 if (gAudioIO->IsBusy()) {
776 SetButton(false,mButtons[TTB_SelectSilence]);
777 return;
778 }
779
780 mVk->AdjustThreshold(GetSensitivity());
781
782
784 if (auto wt = *tl->Any<const WaveTrack>().begin()) {
785 sampleCount start, len;
786 GetSamples(wt, &start, &len);
787
788 //Adjust length to end if selection is null
789 //if(len == 0)
790 //len = wt->GetSequence()->GetNumSamples()-start;
791 double rate = wt->GetRate();
792 auto newstart = mVk->OnBackward(*wt, start, start);
793 auto newend =
794 mVk->OnForward(*wt, start + len, (int)(tl->GetEndTime() * rate));
795
796 //reset the selection bounds.
797 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
798 selectedRegion.setTimes(
799 newstart.as_double() / rate, newend.as_double() / rate);
801
802 }
803
804 SetButton(false,mButtons[TTB_SelectSilence]);
805
806}
807
808
809
810void TranscriptionToolBar::OnCalibrate(wxCommandEvent & WXUNUSED(event))
811{
812 //If IO is busy, abort immediately
813 auto gAudioIO = AudioIOBase::Get();
814 if (gAudioIO->IsBusy()){
815 SetButton(false,mButtons[TTB_Calibrate]);
816 return;
817 }
818
819
821 if(auto wt = *tl->Any<const WaveTrack>().begin()) {
822 sampleCount start, len;
823 GetSamples(wt, &start, &len);
824
825 mVk->CalibrateNoise(*wt, start, len);
826 mVk->AdjustThreshold(3);
827
828 mButtons[TTB_StartOn]->Enable();
829 mButtons[TTB_StartOff]->Enable();
830 mButtons[TTB_EndOn]->Enable();
831 mButtons[TTB_EndOff]->Enable();
832 //mThresholdSensitivity->Set(3);
833
834 SetButton(false,mButtons[TTB_Calibrate]);
835 }
836
837 mButtons[TTB_StartOn]->Enable();
838 mButtons[TTB_StartOff]->Enable();
839 mButtons[TTB_EndOn]->Enable();
840 mButtons[TTB_EndOff]->Enable();
841 mButtons[TTB_SelectSound]->Enable();
842 mButtons[TTB_SelectSilence]->Enable();
843 mButtons[TTB_AutomateSelection]->Enable();
844
845 //Make the sensitivity slider set the sensitivity by processing an event.
846 wxCommandEvent dummy;
847 OnSensitivitySlider(dummy);
848
849}
850
851#include "../LabelTrack.h"
852#include "ProjectHistory.h"
853#include "../TrackPanel.h"
854#include "../TrackPanelAx.h"
855#include "../tracks/labeltrack/ui/LabelTrackView.h"
856namespace {
857int DoAddLabel(
858 AudacityProject &project, const SelectedRegion &region )
859{
860 auto &tracks = TrackList::Get( project );
861 auto &trackFocus = TrackFocus::Get( project );
862 auto &trackPanel = TrackPanel::Get( project );
863 auto &window = ProjectWindow::Get( project );
864
865 wxString title; // of label
866
867 // If the focused track is a label track, use that
868 const auto pFocusedTrack = trackFocus.Get();
869
870 // Look for a label track at or after the focused track
871 auto iter = pFocusedTrack
872 ? tracks.Find(pFocusedTrack)
873 : tracks.Any().begin();
874 auto lt = * iter.Filter< LabelTrack >();
875
876 // If none found, start a NEW label track and use it
877 if (!lt)
878 lt = tracks.Add( std::make_shared<LabelTrack>() );
879
880// LLL: Commented as it seemed a little forceful to remove users
881// selection when adding the label. This does not happen if
882// you select several tracks and the last one of those is a
883// label track...typing a label will not clear the selections.
884//
885// SelectNone();
886 lt->SetSelected(true);
887
888 auto index = LabelTrackView::Get(*lt).AddLabel(region, title);
889
891 .PushState(XO("Added label"), XO("Label"));
892
893 TrackFocus::Get(project).Set(lt);
894 lt->EnsureVisible();
895
896 trackPanel.SetFocus();
897
898 return index;
899}
900}
901
902//This automates selection through a selected region,
903//selecting its best guess for words and creating labels at those points.
904
905void TranscriptionToolBar::OnAutomateSelection(wxCommandEvent & WXUNUSED(event))
906{
907
908
909 //If IO is busy, abort immediately
910 auto gAudioIO = AudioIOBase::Get();
911 if (gAudioIO->IsBusy())
912 {
913 SetButton(false,mButtons[TTB_EndOff]);
914 return;
915 }
916
917 wxBusyCursor busy;
918
919 mVk->AdjustThreshold(GetSensitivity());
921 if(auto wt = *tl->Any<const WaveTrack>().begin()) {
922 sampleCount start, len;
923 GetSamples(wt, &start, &len);
924
925 //Adjust length to end if selection is null
926 if(len == 0)
927 {
928 len = start;
929 start = 0;
930 }
931 sampleCount lastlen = 0;
932 double newStartPos, newEndPos;
933
934 //This is the minimum word size in samples (.05 is 50 ms)
935 int minWordSize = (int)(wt->GetRate() * .05);
936
937 //Continue until we have processed the entire
938 //region, or we are making no progress.
939 while(len > 0 && lastlen != len)
940 {
941
942 lastlen = len;
943
944 auto newStart = mVk->OnForward(*wt, start, len);
945
946 //JKC: If no start found then don't add any labels.
947 if( newStart==start)
948 break;
949
950 //Adjust len by the NEW start position
951 len -= (newStart - start);
952
953 //Adjust len by the minimum word size
954 len -= minWordSize;
955
956
957
958 //OK, now we have found a NEW starting point. A 'word' should be at least
959 //50 ms long, so jump ahead minWordSize
960
961 auto newEnd =
962 mVk->OffForward(*wt, newStart + minWordSize, len);
963
964 //If newEnd didn't move, we should give up, because
965 // there isn't another end before the end of the selection.
966 if(newEnd == (newStart + minWordSize))
967 break;
968
969
970 //Adjust len by the NEW word end
971 len -= (newEnd - newStart);
972
973 //Calculate the start and end of the words, in seconds
974 newStartPos = newStart.as_double() / wt->GetRate();
975 newEndPos = newEnd.as_double() / wt->GetRate();
976
977
978 //Increment
979 start = newEnd;
980
981 DoAddLabel(mProject, SelectedRegion(newStartPos, newEndPos));
983 }
984 SetButton(false, mButtons[TTB_AutomateSelection]);
985 }
986}
987
988void TranscriptionToolBar::OnMakeLabel(wxCommandEvent & WXUNUSED(event))
989{
990 SetButton(false, mButtons[TTB_MakeLabel]);
991 DoAddLabel( mProject, ViewInfo::Get( mProject ).selectedRegion );
992}
993
994//This returns a double z-score between 0 and 10.
995double TranscriptionToolBar::GetSensitivity()
996{
997 return (double)mSensitivity;
998}
999
1000void TranscriptionToolBar::OnSensitivitySlider(wxCommandEvent & WXUNUSED(event))
1001{
1002 mSensitivity = (mSensitivitySlider->Get());
1003}
1004
1005void TranscriptionToolBar::SetKeyType(wxCommandEvent & WXUNUSED(event))
1006{
1007 int value = mKeyTypeChoice->GetSelection();
1008
1009 //Only use one key type at a time.
1010 switch(value)
1011 {
1012 case 0:
1013 mVk->SetKeyType(true,0,0,0,0);
1014 break;
1015 case 1:
1016 mVk->SetKeyType(0,true,0,0,0);
1017 break;
1018 case 2:
1019 mVk->SetKeyType(0,0,true,0,0);
1020 break;
1021 case 3:
1022 mVk->SetKeyType(0,0,0,true,0);
1023 break;
1024 case 4:
1025 mVk->SetKeyType(0,0,0,0,true);
1026 break;
1027 }
1028
1029}
1030#endif
1031
1033{
1035 mPlaySpeedSlider->Refresh();
1036 wxCommandEvent e;
1037 OnSpeedSlider(e);
1038}
1039
1041{
1043}
1044
1045void TranscriptionToolBar::SetPlaying(bool down, bool looped, bool cutPreview)
1046{
1047 AButton *const button = mButtons[TTB_PlaySpeed];
1048 if (down) {
1049 button->SetAlternateIdx(cutPreview ? 2 : looped ? 1 : 0);
1050 button->PushDown();
1051 }
1052 else {
1053 button->SetAlternateIdx(0);
1054 button->PopUp();
1055 }
1056}
1057
1059{
1060 if (adj < 0) {
1062 }
1063 else {
1065 }
1066 wxCommandEvent e;
1067 OnSpeedSlider(e);
1068}
1069
1071 []( AudacityProject &project ){
1073};
1074
1075namespace {
1077 /* i18n-hint: Clicking this menu item shows the toolbar
1078 for transcription (currently just vary play speed) */
1080 wxT("ShowTranscriptionTB"), XXO("Pla&y-at-Speed Toolbar")
1081};
1082}
1083
1084// Menu handler functions
1085
1086#include "../CommonCommandFlags.h"
1087
1088namespace {
1089void OnPlayAtSpeed(const CommandContext &context)
1090{
1091 auto &project = context.project;
1092 auto tb = &TranscriptionToolBar::Get( project );
1093
1094 if (tb) {
1095 tb->PlayAtSpeed(false, false);
1096 }
1097}
1098
1100{
1101 auto &project = context.project;
1102 auto tb = &TranscriptionToolBar::Get( project );
1103
1104 if (tb) {
1105 tb->PlayAtSpeed(true, false);
1106 }
1107}
1108
1110{
1111 auto &project = context.project;
1112 auto tb = &TranscriptionToolBar::Get( project );
1113
1114 if (tb) {
1115 tb->PlayAtSpeed(false, true);
1116 }
1117}
1118
1119void OnSetPlaySpeed(const CommandContext &context)
1120{
1121 auto &project = context.project;
1122 auto tb = &TranscriptionToolBar::Get( project );
1123
1124 if (tb) {
1125 tb->ShowPlaySpeedDialog();
1126 }
1127}
1128
1129void OnPlaySpeedInc(const CommandContext &context)
1130{
1131 auto &project = context.project;
1132 auto tb = &TranscriptionToolBar::Get( project );
1133
1134 if (tb) {
1135 tb->AdjustPlaySpeed(0.1f);
1136 }
1137}
1138
1139void OnPlaySpeedDec(const CommandContext &context)
1140{
1141 auto &project = context.project;
1142 auto tb = &TranscriptionToolBar::Get( project );
1143
1144 if (tb) {
1145 tb->AdjustPlaySpeed(-0.1f);
1146 }
1147}
1148
1149using namespace MenuTable;
1150
1152{
1153 static BaseItemSharedPtr menu{
1154 Menu( wxT("PlayAtSpeed"), XXO("&Play-at-Speed") ) };
1155 return menu;
1156}
1157
1159 wxT("Optional/Extra/Part1"),
1161};
1162
1164{
1165 static BaseItemSharedPtr items{
1166 Items( "",
1167 /* i18n-hint: 'Normal Play-at-Speed' doesn't loop or cut preview. */
1168 Command( wxT("PlayAtSpeedLooped"), XXO("&Play-at-Speed"),
1170 Command( wxT("PlayAtSpeed"), XXO("Play-at-Speed &Once"),
1172 Command( wxT("PlayAtSpeedCutPreview"), XXO("Play C&ut Preview-at-Speed"),
1174 Command( wxT("SetPlaySpeed"), XXO("Ad&just Playback Speed..."),
1176 Command( wxT("PlaySpeedInc"), XXO("&Increase Playback Speed"),
1178 Command( wxT("PlaySpeedDec"), XXO("&Decrease Playback Speed"),
1180 ) };
1181 return items;
1182}
1183
1185 Placement{ wxT("Optional/Extra/Part1/PlayAtSpeed"),
1188};
1189
1190}
#define SPEED_SLIDER
Definition: ASlider.h:35
wxEVT_COMMAND_BUTTON_CLICKED
wxT("CloseDown"))
END_EVENT_TABLE()
AttachedItem sAttachment3
AttachedItem sAttachment2
const ReservedCommandFlag & CaptureNotBusyFlag()
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
int teBmps
#define _(s)
Definition: Internat.h:73
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:89
#define safenew
Definition: MemoryX.h:10
static const auto title
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
@ cutPreviewPlay
static ProjectFileIORegistry::AttributeWriterEntry entry
TranslatableString label
Definition: TagsEditor.cpp:165
const auto tracks
const auto project
THEME_API Theme theTheme
Definition: Theme.cpp:82
EVT_COMMAND_RANGE(TTB_PlaySpeed, TTB_PlaySpeed, wxEVT_COMMAND_BUTTON_CLICKED, TranscriptionToolBar::OnPlaySpeed)
Methods for TranscriptionToolBar.
#define TIMETRACK_MAX
IMPLEMENT_CLASS(TranscriptionToolBar, ToolBar)
static RegisteredToolbarFactory factory
#define TIMETRACK_MIN
@ TTB_PlaySpeedSlider
@ TTB_PlaySpeed
std::vector< TranslatableString > TranslatableStrings
int id
A wxButton with mouse-over behaviour.
Definition: AButton.h:104
void PushDown()
Definition: AButton.cpp:577
void SetToolTip(const TranslatableString &toolTip)
Definition: AButton.cpp:184
void SetAlternateIdx(unsigned idx)
Definition: AButton.cpp:232
bool WasControlDown()
Definition: AButton.cpp:546
void Disable()
Definition: AButton.cpp:560
void Enable()
Definition: AButton.cpp:551
void PopUp()
Definition: AButton.cpp:585
void SetEnabled(bool state)
Definition: AButton.h:182
void FollowModifierKeys()
Definition: AButton.cpp:243
void SetLabel(const TranslatableString &label)
Definition: AButton.cpp:189
ASlider is a custom slider, allowing for a slicker look and feel.
Definition: ASlider.h:260
void Set(float value)
Definition: ASlider.cpp:1850
bool ShowDialog(wxPoint pos=wxPoint(-1, -1))
Definition: ASlider.cpp:1865
void Increase(float steps)
Definition: ASlider.cpp:1855
void Decrease(float steps)
Definition: ASlider.cpp:1860
float Get(bool convert=true)
Definition: ASlider.cpp:1845
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:93
static AudioIO * Get()
Definition: AudioIO.cpp:123
Track subclass holding data representing sound (as notes, or samples, or ...)
Definition: PlayableTrack.h:21
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
static LabelTrackView & Get(LabelTrack &)
int AddLabel(const SelectedRegion &region, const wxString &title={}, int restoreFocus=-1)
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:65
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51
bool setT1(double t, bool maySwap=true)
Definition: ViewInfo.cpp:71
bool setT0(double t, bool maySwap=true)
Definition: ViewInfo.cpp:61
bool isPoint() const
Definition: ViewInfo.h:40
double t0() const
Definition: ViewInfo.h:35
void SetPlaySpeed(double value)
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
static ProjectAudioIO & Get(AudacityProject &project)
static ProjectAudioManager & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
Defines a selected portion of a project.
wxColour & Colour(int iIndex)
wxSize ImageSize(int iIndex)
Works with ToolManager and ToolDock to provide a dockable window in which buttons can be placed.
Definition: ToolBar.h:74
AudacityProject & mProject
Definition: ToolBar.h:248
static void MakeAlternateImages(AButton &button, int idx, teBmps eUp, teBmps eDown, teBmps eHilite, teBmps eDownHi, teBmps eStandardUp, teBmps eStandardDown, teBmps eDisabled, wxSize size)
Definition: ToolBar.cpp:945
DockID
Identifies one of the docking areas for toolbars.
Definition: ToolBar.h:92
@ BotDockID
Definition: ToolBar.h:94
void Add(wxWindow *window, int proportion=0, int flag=wxALIGN_TOP, int border=0, wxObject *userData=NULL)
Definition: ToolBar.cpp:709
static AButton * MakeButton(wxWindow *parent, teBmps eUp, teBmps eDown, teBmps eHilite, teBmps eDownHi, teBmps eStandardUp, teBmps eStandardDown, teBmps eDisabled, wxWindowID id, wxPoint placement, bool processdownevents, wxSize size)
Definition: ToolBar.cpp:875
void SetLabel(const wxString &label) override
Definition: ToolBar.cpp:408
static void MakeButtonBackgroundsSmall()
Definition: ToolBar.cpp:837
void UpdatePrefs() override
Definition: ToolBar.cpp:622
virtual void Create(wxWindow *parent)
Definition: ToolBar.cpp:492
wxWindowPtr< ToolBar > Holder
Definition: ToolBar.h:78
static void SetButtonToolTip(AudacityProject &project, AButton &button, const ComponentInterfaceSymbol commands[], size_t nCommands)
Definition: ToolBar.cpp:970
static ToolManager & Get(AudacityProject &project)
Track * Get()
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:86
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:987
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
Definition: Track.cpp:1008
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1091
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:354
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1108
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:232
A kind of ToolBar used to help with analysing voice recordings.
void Create(wxWindow *parent) override
static Identifier ID()
void SetEnabled(bool enabled)
static TranscriptionToolBar & Get(AudacityProject &project)
bool ShownByDefault() const override
Whether the toolbar should be shown by default. Default implementation returns true.
void OnCaptureKey(wxCommandEvent &event)
std::shared_ptr< BoundedEnvelope > mEnvelope
void GetSamples(const WaveTrack *t, sampleCount *s0, sampleCount *slen)
void SetButton(bool newstate, AButton *button)
static AButton * AddButton(TranscriptionToolBar *pBar, teBmps eFore, teBmps eDisabled, int id, const TranslatableString &label)
void OnPlaySpeed(wxCommandEvent &event)
void SetPlaySpeed(double value)
AButton * mButtons[TTBNumButtons]
void PlayAtSpeed(bool looped, bool cutPreview)
void SetPlaying(bool down, bool looped, bool cutPreview)
DockID DefaultDockID() const override
Which dock the toolbar defaults into. Default implementation chooses the top dock.
void OnFocus(wxFocusEvent &event)
void MakeAlternateImages(teBmps eFore, teBmps eDisabled, int id, unsigned altIdx)
void OnKeyEvent(wxKeyEvent &event)
TranscriptionToolBar(AudacityProject &project)
void EnableDisableButtons() override
void RegenerateTooltips() override
void OnSpeedSlider(wxCommandEvent &event)
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:219
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
A Track that contains audio waveform data.
Definition: WaveTrack.h:220
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2712
double GetRate() const override
Definition: WaveTrack.cpp:868
bool ReadBool(const wxString &key, bool defaultValue) const
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
double as_double() const
Definition: SampleCount.h:46
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:343
bool Begin(const FilePath &dataDir)
Definition: Journal.cpp:226
void OnFocus(wxWindow &window, wxFocusEvent &event)
a function useful to implement a focus event handler The window releases the keyboard if the event is...
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
constexpr auto Items
constexpr auto Command
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
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:113
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:78
int DoAddLabel(AudacityProject &project, const SelectedRegion &region, bool preserveFocus=false)
Definition: LabelMenus.cpp:54
void OnPlayAtSpeedCutPreview(const CommandContext &context)
void OnPlaySpeedDec(const CommandContext &context)
void OnPlaySpeedInc(const CommandContext &context)
void OnPlayAtSpeed(const CommandContext &context)
void OnSetPlaySpeed(const CommandContext &context)
void OnPlayAtSpeedLooped(const CommandContext &context)
Options & Style(int s)
Definition: ASlider.h:280