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