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
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 true;
116}
117
119{
120 return BotDockID;
121}
122
124{
125 auto &toolManager = ToolManager::Get( project );
126 return *static_cast<TranscriptionToolBar*>(toolManager.GetToolBar(ID()));
127}
128
130{
131 return Get( const_cast<AudacityProject&>( project )) ;
132}
133
134void TranscriptionToolBar::Create(wxWindow * parent)
135{
136 ToolBar::Create(parent);
137
140
141#ifdef EXPERIMENTAL_VOICE_DETECTION
142 mButtons[TTB_StartOn]->Disable();
143 mButtons[TTB_StartOff]->Disable();
144 mButtons[TTB_EndOn]->Disable();
145 mButtons[TTB_EndOff]->Disable();
146 mButtons[TTB_SelectSound]->Disable();
147 mButtons[TTB_SelectSilence]->Disable();
148 mButtons[TTB_Calibrate]->Enable();
149 mButtons[TTB_AutomateSelection]->Disable();
150 mButtons[TTB_MakeLabel]->Enable();
151#endif
152
153 //Old code...
154 //Process a dummy event to set up mPlaySpeed
155 //wxCommandEvent dummy;
156 //OnSpeedSlider(dummy);
157
158 //JKC: Set speed this way is better, as we don't
159 //then stop Audio if it is playing, so we can be playing
160 //audio and open a second project.
161 SetPlaySpeed( (mPlaySpeedSlider->Get()) * 100 );
162
163 // Simulate a size event to set initial placement/size
164 wxSizeEvent event(GetSize(), GetId());
165 event.SetEventObject(this);
166 GetEventHandler()->ProcessEvent(event);
167}
168
170{
171 mPlaySpeed = value;
173}
174
180 teBmps eFore, teBmps eDisabled,
181 int id,
183{
184 AButton *&r = pBar->mButtons[id];
185
186 r = ToolBar::MakeButton(pBar,
187 bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall,bmpRecoloredHiliteSmall,
188 eFore, eFore, eDisabled,
189 wxWindowID(id),
190 wxDefaultPosition,
191 false,
192 theTheme.ImageSize( bmpRecoloredUpSmall ));
193
194 r->SetLabel(label);
195// JKC: Unlike ControlToolBar, does not have a focus rect. Shouldn't it?
196// r->SetFocusRect( r->GetRect().Deflate( 4, 4 ) );
197
198 pBar->Add( r, 0, wxALIGN_CENTER );
199
200 return r;
201}
202
204 teBmps eFore, teBmps eDisabled,
205 int id, unsigned altIdx)
206{
208 bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall,bmpRecoloredHiliteSmall,
209 eFore, eFore, eDisabled,
210 theTheme.ImageSize( bmpRecoloredUpSmall ));
211}
212
214{
215 SetBackgroundColour( theTheme.Colour( clrMedium ) );
216// Very similar to code in ControlToolBar...
217// Very similar to code in EditToolBar
219
220 AddButton(this, bmpPlay, bmpPlayDisabled, TTB_PlaySpeed,
221 XO("Play at selected speed"));
222 // 3.1.0 abandoned distinct images for Shift
223 MakeAlternateImages(bmpPlay, bmpPlayDisabled, TTB_PlaySpeed, 1);
224 MakeAlternateImages(bmpCutPreview, bmpCutPreviewDisabled, TTB_PlaySpeed, 2);
226
227 //Add a slider that controls the speed of playback.
228 const int SliderWidth=100;
231 XO("Playback Speed"),
232 wxDefaultPosition,
233 wxSize(SliderWidth,25),
236 // 6 steps using page up/down, and 60 using arrow keys
237 .Line( 0.16722f )
238 .Page( 1.6722f )
239 );
240 mPlaySpeedSlider->SetSizeHints(wxSize(100, 25), wxSize(2000, 25));
242 mPlaySpeedSlider->SetLabel(_("Playback Speed"));
243 Add( mPlaySpeedSlider, 1, wxALIGN_CENTER );
244 mPlaySpeedSlider->Bind(wxEVT_SET_FOCUS,
246 this);
247 mPlaySpeedSlider->Bind(wxEVT_KILL_FOCUS,
249 this);
250
251#ifdef EXPERIMENTAL_VOICE_DETECTION
252// If we need these strings translated, then search and replace
253// YO by XO and remove this #define.
254#define YO( x ) Verbatim( x )
255 AddButton(this, bmpTnStartOn, bmpTnStartOnDisabled, TTB_StartOn,
256 YO("Adjust left selection to next onset"));
257 AddButton(this, bmpTnEndOn, bmpTnEndOnDisabled, TTB_EndOn,
258 YO("Adjust right selection to previous offset"));
259 AddButton(this, bmpTnStartOff, bmpTnStartOffDisabled, TTB_StartOff,
260 YO("Adjust left selection to next offset"));
261 AddButton(this, bmpTnEndOff, bmpTnEndOffDisabled, TTB_EndOff,
262 YO("Adjust right selection to previous onset"));
263 AddButton(this, bmpTnSelectSound, bmpTnSelectSoundDisabled, TTB_SelectSound,
264 YO("Select region of sound around cursor"));
265 AddButton(this, bmpTnSelectSilence, bmpTnSelectSilenceDisabled, TTB_SelectSilence,
266 YO("Select region of silence around cursor"));
267 AddButton(this, bmpTnAutomateSelection, bmpTnAutomateSelectionDisabled, TTB_AutomateSelection,
268 YO("Automatically make labels from words"));
269 AddButton(this, bmpTnMakeTag, bmpTnMakeTagDisabled, TTB_MakeLabel,
270 YO("Add label at selection"));
271 AddButton(this, bmpTnCalibrate, bmpTnCalibrateDisabled, TTB_Calibrate,
272 YO("Calibrate voicekey"));
273
275 TTB_SensitivitySlider,
276 YO("Adjust Sensitivity"),
277 wxDefaultPosition,
278 wxSize(SliderWidth,25),
280 .Style( SPEED_SLIDER ));
282 mSensitivitySlider->SetLabel(YO("Sensitivity").Translation());
283 Add( mSensitivitySlider, 0, wxALIGN_CENTER );
284
285 TranslatableStrings choices {
286 YO("Energy"),
287 YO("Sign Changes (Low Threshold)"),
288 YO("Sign Changes (High Threshold)"),
289 YO("Direction Changes (Low Threshold)"),
290 YO("Direction Changes (High Threshold)")
291 };
292
293 mKeyTypeChoice = safenew wxChoice(this, TTB_KeyType,
294 wxDefaultPosition,
295 wxDefaultSize,
296 transform_container<wxArrayStringEx>( choices,
297 std::mem_fn( &TranslatableString::Translation ) ) );
298 mKeyTypeChoice->SetName(YO("Key type").Translation());
299 mKeyTypeChoice->SetSelection(0);
300 Add( mKeyTypeChoice, 0, wxALIGN_CENTER );
301#endif
302
303 // Add a little space
304 Add(2, -1);
305
306 UpdatePrefs();
307}
308
310{
312
313 auto gAudioIO = AudioIO::Get();
314 bool canStopAudioStream = (!gAudioIO->IsStreamActive() ||
315 gAudioIO->IsMonitoring() ||
316 gAudioIO->GetOwningProject().get() == p );
317 bool recording = gAudioIO->GetNumCaptureChannels() > 0;
318
319 // Only interested in audio type tracks
320 bool tracks = p && TrackList::Get(*p).Any<AudioTrack>(); // PRL: PlayableTrack ?
321 SetEnabled(canStopAudioStream && tracks && !recording);
322
323#ifdef EXPERIMENTAL_VOICE_DETECTION
324 if (!p)
325 return;
326 // Is anything selected?
327 const auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
328 auto selection = !selectedRegion.isPoint() &&
329 !TrackList::Get( *p ).Selected().empty();
330
331 mButtons[TTB_Calibrate]->SetEnabled(selection);
332#endif
333}
334
336{
338
339 // Set label to pull in language change
340 SetLabel(XO("Play-at-Speed"));
341
342 // Give base class a chance
344}
345
347{
348 // We could also mention the shift- and ctrl-modified versions in the
349 // tool tip... but it would get long
350
351 static const struct Entry {
352 int tool;
353 CommandID commandName;
354 TranslatableString untranslatedLabel;
355 CommandID commandName2;
356 TranslatableString untranslatedLabel2;
357 } table[] = {
359 wxT("PlayAtSpeedLooped"), XO("Play-at-Speed"),
360 wxT("PlayAtSpeed"), XO("Play-at-Speed Once"),
361 },
362 };
363
364 for (const auto &entry : table) {
365 ComponentInterfaceSymbol commands[] = {
366 { entry.commandName, entry.untranslatedLabel },
367 { entry.commandName2, entry.untranslatedLabel2 },
368 };
370 *mButtons[entry.tool], commands, 2u );
371 }
372
373#ifdef EXPERIMENTAL_VOICE_DETECTION
374 mButtons[TTB_StartOn]->SetToolTip(YO("Left-to-On"));
375 mButtons[TTB_EndOn]->SetToolTip( YO("Right-to-Off"));
376 mButtons[TTB_StartOff]->SetToolTip( YO("Left-to-Off"));
377 mButtons[TTB_EndOff]->SetToolTip( YO("Right-to-On"));
378 mButtons[TTB_SelectSound]->SetToolTip( YO("Select-Sound"));
379 mButtons[TTB_SelectSilence]->SetToolTip( YO("Select-Silence"));
380 mButtons[TTB_AutomateSelection]->SetToolTip( YO("Make Labels"));
381 mButtons[TTB_MakeLabel]->SetToolTip( YO("Add Label"));
382 mButtons[TTB_Calibrate]->SetToolTip( YO("Calibrate"));
383
384 mSensitivitySlider->SetToolTip(YO("Sensitivity").Translation());
385 mKeyTypeChoice->SetToolTip(YO("Key type").Translation());
386#endif
387}
388
389void TranscriptionToolBar::OnFocus(wxFocusEvent &event)
390{
391 KeyboardCapture::OnFocus( *this, event );
392}
393
394void TranscriptionToolBar::OnCaptureKey(wxCommandEvent &event)
395{
396 wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
397 int keyCode = kevent->GetKeyCode();
398
399 // Pass LEFT/RIGHT/UP/DOWN/PAGEUP/PAGEDOWN through for input/output sliders
400 if (FindFocus() == mPlaySpeedSlider && (keyCode == WXK_LEFT || keyCode == WXK_RIGHT
401 || keyCode == WXK_UP || keyCode == WXK_DOWN
402 || keyCode == WXK_PAGEUP || keyCode == WXK_PAGEDOWN)) {
403 return;
404 }
405
406 event.Skip();
407
408 return;
409}
410
411//This handles key-stroke events????
412void TranscriptionToolBar::OnKeyEvent(wxKeyEvent & event)
413{
414 if (event.ControlDown()) {
415 event.Skip();
416 return;
417 }
418
419 if (event.GetKeyCode() == WXK_SPACE) {
420 auto gAudioIO = AudioIOBase::Get();
421 if (gAudioIO->IsBusy()) {
422 /*Do Stuff Here*/
423 }
424 else {
425 /*Do other stuff Here*/
426 }
427 }
428}
429
430
431
432//This changes the state of the various buttons
434{
435 if (down) {
436 button->PushDown();
437 }
438 else {
439 button->PopUp();
440 }
441}
442
444 const WaveTrack *t, sampleCount *s0, sampleCount *slen)
445{
446 // GetSamples attempts to translate the start and end selection markers into sample indices
447 // These selection numbers are doubles.
448
450 if (!p) {
451 return;
452 }
453
454 //First, get the current selection. It is part of the mViewInfo, which is
455 //part of the project
456
457 const auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
458 double start = selectedRegion.t0();
459 double end = selectedRegion.t1();
460
461 auto ss0 = sampleCount( (start - t->GetStartTime()) * t->GetRate() );
462 auto ss1 = sampleCount( (end - t->GetStartTime()) * t->GetRate() );
463
464 if (start < t->GetStartTime()) {
465 ss0 = 0;
466 }
467
468#if 0
469 //This adjusts the right samplecount to the maximum sample.
470 if (ss1 >= t->GetNumSamples()) {
471 ss1 = t->GetNumSamples();
472 }
473#endif
474
475 if (ss1 < ss0) {
476 ss1 = ss0;
477 }
478
479 *s0 = ss0;
480 *slen = ss1 - ss0;
481}
482
483// PRL: duplicating constants from TimeTrack.cpp
484//TODO-MB: are these sensible values?
485#define TIMETRACK_MIN 0.01
486#define TIMETRACK_MAX 10.0
487
488// Come here from button clicks, or commands
489void TranscriptionToolBar::PlayAtSpeed(bool newDefault, bool cutPreview)
490{
491 // Can't do anything without an active project
493 if (!p) {
494 return;
495 }
496
497 auto &projectAudioManager = ProjectAudioManager::Get( mProject );
498
499 // Fixed speed play is the old method, that uses a time track.
500 // VariSpeed play reuses Scrubbing.
501 bool bFixedSpeedPlay = !gPrefs->ReadBool(wxT("/AudioIO/VariSpeedPlay"), true);
502 // Scrubbing doesn't support note tracks, but the fixed-speed method using time tracks does.
503 if (TrackList::Get(*p).Any<NoteTrack>())
504 bFixedSpeedPlay = true;
505
506 // If cutPreview, we have to fall back to fixed speed.
507 if (newDefault)
508 cutPreview = false;
509 bFixedSpeedPlay = bFixedSpeedPlay || cutPreview;
510 if (bFixedSpeedPlay)
511 {
512 // Create a BoundedEnvelope if we haven't done so already
513 if (!mEnvelope) {
514 mEnvelope =
515 std::make_unique<BoundedEnvelope>(
516 true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
517 // values as in the constructor for TimeTrack
518 mEnvelope->SetRangeLower( 0.9 );
519 mEnvelope->SetRangeUpper( 1.1 );
520 }
521 // Set the speed range
522 //mTimeTrack->SetRangeUpper((double)mPlaySpeed / 100.0);
523 //mTimeTrack->SetRangeLower((double)mPlaySpeed / 100.0);
524 mEnvelope->Flatten((double)mPlaySpeed / 100.0);
525 }
526
527 // Pop up the button
529
530 // If IO is busy, abort immediately
531 auto gAudioIO = AudioIOBase::Get();
532 if (gAudioIO->IsBusy())
533 projectAudioManager.Stop();
534
535 // Get the current play region
536 const auto &viewInfo = ViewInfo::Get( *p );
537 const auto &playRegion = viewInfo.playRegion;
538
539 // Start playing
540 if (playRegion.GetStart() < 0)
541 return;
542
543 {
544 auto options = ProjectAudioIO::GetDefaultOptions(*p, newDefault);
545 // No need to set cutPreview options.
546 options.envelope = bFixedSpeedPlay ? mEnvelope.get() : nullptr;
547 options.variableSpeed = !bFixedSpeedPlay;
548 auto mode =
549 cutPreview ? PlayMode::cutPreviewPlay
550 : newDefault ? PlayMode::loopedPlay
552 projectAudioManager.PlayPlayRegion(
553 SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()),
554 options,
555 mode);
556 }
557}
558
559// Come here from button clicks only
560void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & event)
561{
562 auto button = mButtons[TTB_PlaySpeed];
563
564 // Let control have precedence over shift
565 const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
566 const bool looped = !cutPreview &&
567 !button->WasShiftDown();
568 OnSpeedSlider(event);
569 PlayAtSpeed(looped, cutPreview);
570}
571
572void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
573{
574 SetPlaySpeed( (mPlaySpeedSlider->Get()) * 100 );
576
577 // If IO is busy, abort immediately
578 // AWD: This is disabled to work around a hang on Linux when PulseAudio is
579 // used. If we figure that one out we can re-enable this code.
580 // auto gAudioIO = AudioIOBase::Get();
581 //if (gAudioIO->IsBusy()) {
582 // OnPlaySpeed(event);
583 //}
584}
585
586#ifdef EXPERIMENTAL_VOICE_DETECTION
587void TranscriptionToolBar::OnStartOn(wxCommandEvent & WXUNUSED(event))
588{
589 //If IO is busy, abort immediately
590 auto gAudioIO = AudioIOBase::Get();
591 if (gAudioIO->IsBusy()){
592 SetButton(false,mButtons[TTB_StartOn]);
593 return;
594 }
595
596 mVk->AdjustThreshold(GetSensitivity());
597
598 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
599 if(t ) {
600 auto wt = static_cast<const WaveTrack*>(t);
601 sampleCount start, len;
602 GetSamples(wt, &start, &len);
603
604 //Adjust length to end if selection is null
605 //if(len == 0)
606 //len = wt->GetSequence()->GetNumSamples()-start;
607
608 auto newstart = mVk->OnForward(*wt, start, len);
609 double newpos = newstart.as_double() / wt->GetRate();
610
611 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
612 selectedRegion.setT0( newpos );
614
615 SetButton(false, mButtons[TTB_StartOn]);
616 }
617}
618
619void TranscriptionToolBar::OnStartOff(wxCommandEvent & WXUNUSED(event))
620{
621 //If IO is busy, abort immediately
622 auto gAudioIO = AudioIOBase::Get();
623 if (gAudioIO->IsBusy()){
624 SetButton(false,mButtons[TTB_StartOff]);
625 return;
626 }
627 mVk->AdjustThreshold(GetSensitivity());
629
630 SetButton(false, mButtons[TTB_StartOff]);
631 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
632 if(t) {
633 auto wt = static_cast<const WaveTrack*>(t);
634 sampleCount start, len;
635 GetSamples(wt, &start, &len);
636
637 //Adjust length to end if selection is null
638 //if(len == 0)
639 //len = wt->GetSequence()->GetNumSamples()-start;
640
641 auto newstart = mVk->OffForward(*wt, start, len);
642 double newpos = newstart.as_double() / wt->GetRate();
643
644 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
645 selectedRegion.setT0( newpos );
647
648 SetButton(false, mButtons[TTB_StartOn]);
649 }
650}
651
652void TranscriptionToolBar::OnEndOn(wxCommandEvent & WXUNUSED(event))
653{
654
655 //If IO is busy, abort immediately
656 auto gAudioIO = AudioIOBase::Get();
657 if (gAudioIO->IsBusy()){
658 SetButton(false,mButtons[TTB_EndOn]);
659 return;
660 }
661
662 mVk->AdjustThreshold(GetSensitivity());
664 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
665 if(t) {
666 auto wt = static_cast<const WaveTrack*>(t);
667 sampleCount start, len;
668 GetSamples(wt, &start, &len);
669
670 //Adjust length to end if selection is null
671 if(len == 0)
672 {
673 len = start;
674 start = 0;
675 }
676 auto newEnd = mVk->OnBackward(*wt, start + len, len);
677 double newpos = newEnd.as_double() / wt->GetRate();
678
679 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
680 selectedRegion.setT1( newpos );
682
683 SetButton(false, mButtons[TTB_EndOn]);
684 }
685}
686
687
688
689void TranscriptionToolBar::OnEndOff(wxCommandEvent & WXUNUSED(event))
690{
691
692 //If IO is busy, abort immediately
693 auto gAudioIO = AudioIOBase::Get();
694 if (gAudioIO->IsBusy()){
695 SetButton(false,mButtons[TTB_EndOff]);
696 return;
697 }
698 mVk->AdjustThreshold(GetSensitivity());
700
701 auto t = *TrackList::Get( mProject ).Any< const WaveTrack >().begin();
702 if(t) {
703 auto wt = static_cast<const WaveTrack*>(t);
704 sampleCount start, len;
705 GetSamples(wt, &start, &len);
706
707 //Adjust length to end if selection is null
708 if(len == 0) {
709 len = start;
710 start = 0;
711 }
712 auto newEnd = mVk->OffBackward(*wt, start + len, len);
713 double newpos = newEnd.as_double() / wt->GetRate();
714
715 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
716 selectedRegion.setT1( newpos );
718
719 SetButton(false, mButtons[TTB_EndOff]);
720 }
721}
722
723
724
725void TranscriptionToolBar::OnSelectSound(wxCommandEvent & WXUNUSED(event))
726{
727
728 //If IO is busy, abort immediately
729 auto gAudioIO = AudioIOBase::Get();
730 if (gAudioIO->IsBusy()){
731 SetButton(false,mButtons[TTB_SelectSound]);
732 return;
733 }
734
735
736 mVk->AdjustThreshold(GetSensitivity());
737
738
740 if(auto wt = *tl->Any<const WaveTrack>().begin()) {
741 sampleCount start, len;
742 GetSamples(wt, &start, &len);
743
744 //Adjust length to end if selection is null
745 //if(len == 0)
746 //len = wt->GetSequence()->GetNumSamples()-start;
747
748 double rate = wt->GetRate();
749 auto newstart = mVk->OffBackward(*wt, start, start);
750 auto newend =
751 mVk->OffForward(*wt, start + len, (int)(tl->GetEndTime() * rate));
752
753 //reset the selection bounds.
754 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
755 selectedRegion.setTimes(
756 newstart.as_double() / rate, newend.as_double() / rate );
758
759 }
760
761 SetButton(false,mButtons[TTB_SelectSound]);
762}
763
764void TranscriptionToolBar::OnSelectSilence(wxCommandEvent & WXUNUSED(event))
765{
766
767 //If IO is busy, abort immediately
768 auto gAudioIO = AudioIOBase::Get();
769 if (gAudioIO->IsBusy()) {
770 SetButton(false,mButtons[TTB_SelectSilence]);
771 return;
772 }
773
774 mVk->AdjustThreshold(GetSensitivity());
775
776
778 if (auto wt = *tl->Any<const WaveTrack>().begin()) {
779 sampleCount start, len;
780 GetSamples(wt, &start, &len);
781
782 //Adjust length to end if selection is null
783 //if(len == 0)
784 //len = wt->GetSequence()->GetNumSamples()-start;
785 double rate = wt->GetRate();
786 auto newstart = mVk->OnBackward(*wt, start, start);
787 auto newend =
788 mVk->OnForward(*wt, start + len, (int)(tl->GetEndTime() * rate));
789
790 //reset the selection bounds.
791 auto &selectedRegion = ViewInfo::Get( mProject ).selectedRegion;
792 selectedRegion.setTimes(
793 newstart.as_double() / rate, newend.as_double() / rate);
795
796 }
797
798 SetButton(false,mButtons[TTB_SelectSilence]);
799
800}
801
802
803
804void TranscriptionToolBar::OnCalibrate(wxCommandEvent & WXUNUSED(event))
805{
806 //If IO is busy, abort immediately
807 auto gAudioIO = AudioIOBase::Get();
808 if (gAudioIO->IsBusy()){
809 SetButton(false,mButtons[TTB_Calibrate]);
810 return;
811 }
812
813
815 if(auto wt = *tl->Any<const WaveTrack>().begin()) {
816 sampleCount start, len;
817 GetSamples(wt, &start, &len);
818
819 mVk->CalibrateNoise(*wt, start, len);
820 mVk->AdjustThreshold(3);
821
822 mButtons[TTB_StartOn]->Enable();
823 mButtons[TTB_StartOff]->Enable();
824 mButtons[TTB_EndOn]->Enable();
825 mButtons[TTB_EndOff]->Enable();
826 //mThresholdSensitivity->Set(3);
827
828 SetButton(false,mButtons[TTB_Calibrate]);
829 }
830
831 mButtons[TTB_StartOn]->Enable();
832 mButtons[TTB_StartOff]->Enable();
833 mButtons[TTB_EndOn]->Enable();
834 mButtons[TTB_EndOff]->Enable();
835 mButtons[TTB_SelectSound]->Enable();
836 mButtons[TTB_SelectSilence]->Enable();
837 mButtons[TTB_AutomateSelection]->Enable();
838
839 //Make the sensitivity slider set the sensitivity by processing an event.
840 wxCommandEvent dummy;
841 OnSensitivitySlider(dummy);
842
843}
844
845#include "../LabelTrack.h"
846#include "ProjectHistory.h"
847#include "../TrackPanel.h"
848#include "TrackFocus.h"
849#include "../tracks/labeltrack/ui/LabelTrackView.h"
850namespace {
851int DoAddLabel(
852 AudacityProject &project, const SelectedRegion &region )
853{
854 auto &tracks = TrackList::Get( project );
855 auto &trackFocus = TrackFocus::Get( project );
856 auto &trackPanel = TrackPanel::Get( project );
857 auto &window = ProjectWindow::Get( project );
858
859 wxString title; // of label
860
861 // If the focused track is a label track, use that
862 const auto pFocusedTrack = trackFocus.Get();
863
864 // Look for a label track at or after the focused track
865 auto iter = pFocusedTrack
866 ? tracks.Find(pFocusedTrack)
867 : tracks.Any().begin();
868 auto lt = * iter.Filter< LabelTrack >();
869
870 // If none found, start a NEW label track and use it
871 if (!lt)
872 lt = tracks.Add( std::make_shared<LabelTrack>() );
873
874// LLL: Commented as it seemed a little forceful to remove users
875// selection when adding the label. This does not happen if
876// you select several tracks and the last one of those is a
877// label track...typing a label will not clear the selections.
878//
879// SelectNone();
880 lt->SetSelected(true);
881
882 auto index = LabelTrackView::Get(*lt).AddLabel(region, title);
883
885 .PushState(XO("Added label"), XO("Label"));
886
887 TrackFocus::Get(project).Set(lt);
888 lt->EnsureVisible();
889
890 trackPanel.SetFocus();
891
892 return index;
893}
894}
895
896//This automates selection through a selected region,
897//selecting its best guess for words and creating labels at those points.
898
899void TranscriptionToolBar::OnAutomateSelection(wxCommandEvent & WXUNUSED(event))
900{
901
902
903 //If IO is busy, abort immediately
904 auto gAudioIO = AudioIOBase::Get();
905 if (gAudioIO->IsBusy())
906 {
907 SetButton(false,mButtons[TTB_EndOff]);
908 return;
909 }
910
911 wxBusyCursor busy;
912
913 mVk->AdjustThreshold(GetSensitivity());
915 if(auto wt = *tl->Any<const WaveTrack>().begin()) {
916 sampleCount start, len;
917 GetSamples(wt, &start, &len);
918
919 //Adjust length to end if selection is null
920 if(len == 0)
921 {
922 len = start;
923 start = 0;
924 }
925 sampleCount lastlen = 0;
926 double newStartPos, newEndPos;
927
928 //This is the minimum word size in samples (.05 is 50 ms)
929 int minWordSize = (int)(wt->GetRate() * .05);
930
931 //Continue until we have processed the entire
932 //region, or we are making no progress.
933 while(len > 0 && lastlen != len)
934 {
935
936 lastlen = len;
937
938 auto newStart = mVk->OnForward(*wt, start, len);
939
940 //JKC: If no start found then don't add any labels.
941 if( newStart==start)
942 break;
943
944 //Adjust len by the NEW start position
945 len -= (newStart - start);
946
947 //Adjust len by the minimum word size
948 len -= minWordSize;
949
950
951
952 //OK, now we have found a NEW starting point. A 'word' should be at least
953 //50 ms long, so jump ahead minWordSize
954
955 auto newEnd =
956 mVk->OffForward(*wt, newStart + minWordSize, len);
957
958 //If newEnd didn't move, we should give up, because
959 // there isn't another end before the end of the selection.
960 if(newEnd == (newStart + minWordSize))
961 break;
962
963
964 //Adjust len by the NEW word end
965 len -= (newEnd - newStart);
966
967 //Calculate the start and end of the words, in seconds
968 newStartPos = newStart.as_double() / wt->GetRate();
969 newEndPos = newEnd.as_double() / wt->GetRate();
970
971
972 //Increment
973 start = newEnd;
974
975 DoAddLabel(mProject, SelectedRegion(newStartPos, newEndPos));
977 }
978 SetButton(false, mButtons[TTB_AutomateSelection]);
979 }
980}
981
982void TranscriptionToolBar::OnMakeLabel(wxCommandEvent & WXUNUSED(event))
983{
984 SetButton(false, mButtons[TTB_MakeLabel]);
985 DoAddLabel( mProject, ViewInfo::Get( mProject ).selectedRegion );
986}
987
988//This returns a double z-score between 0 and 10.
989double TranscriptionToolBar::GetSensitivity()
990{
991 return (double)mSensitivity;
992}
993
994void TranscriptionToolBar::OnSensitivitySlider(wxCommandEvent & WXUNUSED(event))
995{
996 mSensitivity = (mSensitivitySlider->Get());
997}
998
999void TranscriptionToolBar::SetKeyType(wxCommandEvent & WXUNUSED(event))
1000{
1001 int value = mKeyTypeChoice->GetSelection();
1002
1003 //Only use one key type at a time.
1004 switch(value)
1005 {
1006 case 0:
1007 mVk->SetKeyType(true,0,0,0,0);
1008 break;
1009 case 1:
1010 mVk->SetKeyType(0,true,0,0,0);
1011 break;
1012 case 2:
1013 mVk->SetKeyType(0,0,true,0,0);
1014 break;
1015 case 3:
1016 mVk->SetKeyType(0,0,0,true,0);
1017 break;
1018 case 4:
1019 mVk->SetKeyType(0,0,0,0,true);
1020 break;
1021 }
1022
1023}
1024#endif
1025
1027{
1029 mPlaySpeedSlider->Refresh();
1030 wxCommandEvent e;
1031 OnSpeedSlider(e);
1032}
1033
1035{
1037}
1038
1039void TranscriptionToolBar::SetPlaying(bool down, bool looped, bool cutPreview)
1040{
1041 AButton *const button = mButtons[TTB_PlaySpeed];
1042 if (down) {
1043 button->SetAlternateIdx(cutPreview ? 2 : looped ? 1 : 0);
1044 button->PushDown();
1045 }
1046 else {
1047 button->SetAlternateIdx(0);
1048 button->PopUp();
1049 }
1050}
1051
1053{
1054 if (adj < 0) {
1056 }
1057 else {
1059 }
1060 wxCommandEvent e;
1061 OnSpeedSlider(e);
1062}
1063
1065 []( AudacityProject &project ){
1067};
1068
1069namespace {
1071 /* i18n-hint: Clicking this menu item shows the toolbar
1072 for transcription (currently just vary play speed) */
1074 wxT("ShowTranscriptionTB"), XXO("Pla&y-at-Speed Toolbar")
1075};
1076}
1077
1078// Menu handler functions
1079
1080#include "../CommonCommandFlags.h"
1081
1082namespace {
1083void OnPlayAtSpeed(const CommandContext &context)
1084{
1085 auto &project = context.project;
1086 auto tb = &TranscriptionToolBar::Get( project );
1087
1088 if (tb) {
1089 tb->PlayAtSpeed(false, false);
1090 }
1091}
1092
1094{
1095 auto &project = context.project;
1096 auto tb = &TranscriptionToolBar::Get( project );
1097
1098 if (tb) {
1099 tb->PlayAtSpeed(true, false);
1100 }
1101}
1102
1104{
1105 auto &project = context.project;
1106 auto tb = &TranscriptionToolBar::Get( project );
1107
1108 if (tb) {
1109 tb->PlayAtSpeed(false, true);
1110 }
1111}
1112
1113void OnSetPlaySpeed(const CommandContext &context)
1114{
1115 auto &project = context.project;
1116 auto tb = &TranscriptionToolBar::Get( project );
1117
1118 if (tb) {
1119 tb->ShowPlaySpeedDialog();
1120 }
1121}
1122
1123void OnPlaySpeedInc(const CommandContext &context)
1124{
1125 auto &project = context.project;
1126 auto tb = &TranscriptionToolBar::Get( project );
1127
1128 if (tb) {
1129 tb->AdjustPlaySpeed(0.1f);
1130 }
1131}
1132
1133void OnPlaySpeedDec(const CommandContext &context)
1134{
1135 auto &project = context.project;
1136 auto tb = &TranscriptionToolBar::Get( project );
1137
1138 if (tb) {
1139 tb->AdjustPlaySpeed(-0.1f);
1140 }
1141}
1142
1143using namespace MenuRegistry;
1144
1146{
1147 static auto menu = std::shared_ptr{
1148 Menu( wxT("PlayAtSpeed"), XXO("&Play-at-Speed") ) };
1149 return menu;
1150}
1151
1153 wxT("Optional/Extra/Part1")
1154};
1155
1157{
1158 static auto items = std::shared_ptr{
1159 Items( "",
1160 /* i18n-hint: 'Normal Play-at-Speed' doesn't loop or cut preview. */
1161 Command( wxT("PlayAtSpeedLooped"), XXO("&Play-at-Speed"),
1163 Command( wxT("PlayAtSpeed"), XXO("Play-at-Speed &Once"),
1165 Command( wxT("PlayAtSpeedCutPreview"), XXO("Play C&ut Preview-at-Speed"),
1167 Command( wxT("SetPlaySpeed"), XXO("Ad&just Playback Speed..."),
1169 Command( wxT("PlaySpeedInc"), XXO("&Increase Playback Speed"),
1171 Command( wxT("PlaySpeedDec"), XXO("&Decrease Playback Speed"),
1173 ) };
1174 return items;
1175}
1176
1178 Placement{ wxT("Optional/Extra/Part1/PlayAtSpeed"),
1180};
1181
1182}
#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
static ProjectFileIORegistry::AttributeWriterEntry entry
#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:9
static const auto title
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
@ cutPreviewPlay
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:1840
bool ShowDialog(wxPoint pos=wxPoint(-1, -1))
Definition: ASlider.cpp:1855
void Increase(float steps)
Definition: ASlider.cpp:1845
void Decrease(float steps)
Definition: ASlider.cpp:1850
float Get(bool convert=true)
Definition: ASlider.cpp:1835
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:94
static AudioIO * Get()
Definition: AudioIO.cpp:126
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:95
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:78
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)
Generates classes whose instances register items at construction.
Definition: Registry.h:388
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()
Definition: TrackFocus.cpp:156
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:850
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
Definition: Track.cpp:784
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:950
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:967
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:234
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:215
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void Redraw()
Definition: Viewport.cpp:749
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2576
double GetRate() const override
Definition: WaveTrack.cpp:798
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:375
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 Items
Definition: MenuRegistry.h:427
constexpr auto Command
Definition: MenuRegistry.h:456
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
Definition: MenuRegistry.h:445
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
int DoAddLabel(AudacityProject &project, const SelectedRegion &region, bool preserveFocus=false)
Definition: LabelMenus.cpp:56
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)
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
Options & Style(int s)
Definition: ASlider.h:280