Audacity 3.2.0
Contrast.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Contrast.cpp
6
7\class ContrastDialog
8\brief Dialog used for Contrast menu item
9
10*//*******************************************************************/
11
12
13#include "Contrast.h"
14
15#include "../CommonCommandFlags.h"
16#include "../WaveTrack.h"
17#include "Prefs.h"
18#include "Project.h"
19#include "../ProjectFileIO.h"
20#include "ProjectRate.h"
21#include "../ProjectWindow.h"
22#include "../SelectFile.h"
23#include "../ShuttleGui.h"
24#include "FileNames.h"
25#include "ViewInfo.h"
26#include "../widgets/HelpSystem.h"
27#include "../widgets/NumericTextCtrl.h"
28#include "../widgets/AudacityMessageBox.h"
29#include "../widgets/VetoDialogHook.h"
30
31#include <cmath>
32#include <limits>
33
34#if defined(__WXMSW__) && !defined(__CYGWIN__)
35#include <float.h>
36#define finite(x) _finite(x)
37#endif
38
39#include <wx/button.h>
40#include <wx/valtext.h>
41#include <wx/log.h>
42#include <wx/wfstream.h>
43#include <wx/txtstrm.h>
44#include <wx/textctrl.h>
45
47
48#define DB_MAX_LIMIT 0.0 // Audio is massively distorted.
49#define WCAG2_PASS 20.0 // dB difference required to pass WCAG2 test.
50
51
52bool ContrastDialog::GetDB(float &dB)
53{
54 float rms = float(0.0);
55
56 // For stereo tracks: sqrt((mean(L)+mean(R))/2)
57 double meanSq = 0.0;
58
59 auto p = FindProjectFromWindow( this );
60 auto range =
62 auto numberSelectedTracks = range.size();
63 if (numberSelectedTracks > 1) {
65 nullptr,
66 XO("You can only measure one track at a time."),
67 XO("Error"),
68 wxOK);
69 m.ShowModal();
70 return false;
71 }
72 if(numberSelectedTracks == 0) {
74 nullptr,
75 XO("Please select an audio track."),
76 XO("Error"),
77 wxOK);
78 m.ShowModal();
79 return false;
80 }
81
82 const auto channels = TrackList::Channels( *range.begin() );
83 for ( auto t : channels ) {
84 wxASSERT(mT0 <= mT1);
85
86 // Ignore whitespace beyond ends of track.
87 if(mT0 < t->GetStartTime())
88 mT0 = t->GetStartTime();
89 if(mT1 > t->GetEndTime())
90 mT1 = t->GetEndTime();
91
92 auto SelT0 = t->TimeToLongSamples(mT0);
93 auto SelT1 = t->TimeToLongSamples(mT1);
94
95 if(SelT0 > SelT1)
96 {
98 nullptr,
99 XO("Invalid audio selection.\nPlease ensure that audio is selected."),
100 XO("Error"),
101 wxOK);
102 m.ShowModal();
103 return false;
104 }
105
106 if(SelT0 == SelT1)
107 {
109 nullptr,
110 XO("Nothing to measure.\nPlease select a section of a track."),
111 XO("Error"),
112 wxOK);
113 m.ShowModal();
114 return false;
115 }
116
117 // Don't throw in this analysis dialog
118 rms = t->GetRMS(mT0, mT1, false);
119 meanSq += rms * rms;
120 }
121 // TODO: This works for stereo, provided the audio clips are in both channels.
122 // We should really count gaps between clips as silence.
123 rms = (meanSq > 0.0)
124 ? sqrt( meanSq/static_cast<double>( channels.size() ) )
125 : 0.0;
126
127 // Gives warning C4056, Overflow in floating-point constant arithmetic
128 // -INFINITY is intentional here.
129 // Looks like we are stuck with this warning, as
130 // #pragma warning( disable : 4056)
131 // even around the whole function does not disable it successfully.
132
133 dB = (rms == 0.0)? -INFINITY : LINEAR_TO_DB(rms);
134 return true;
135}
136
138{
139 auto p = FindProjectFromWindow( this );
140 auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
141 mT0 = selectedRegion.t0();
142 mT1 = selectedRegion.t1();
143}
144
145
146// WDR: class implementations
147
148//----------------------------------------------------------------------------
149// ContrastDialog
150//----------------------------------------------------------------------------
151
152// WDR: event table for ContrastDialog
153
154enum {
157 //ID_BUTTON_GETURL,
160 //ID_BUTTON_CLOSE,
170
171BEGIN_EVENT_TABLE(ContrastDialog,wxDialogWrapper)
179
180void ContrastDialog::OnChar(wxKeyEvent &event)
181{
182 // Is this still required?
183 if (event.GetKeyCode() == WXK_TAB) {
184 // pass to next handler
185 event.Skip();
186 return;
187 }
188
189 // ignore any other key
190 event.Skip(false);
191 return;
192}
193
194ContrastDialog::ContrastDialog(wxWindow * parent, wxWindowID id,
196 const wxPoint & pos):
197 wxDialogWrapper(parent, id, title, pos, wxDefaultSize,
198 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX )
199{
200 SetName();
201
202 mT0 = 0.0;
203 mT1 = 0.0;
204 foregrounddB = 0.0;
205 backgrounddB = 0.0;
206 mForegroundIsDefined = false;
207 mBackgroundIsDefined = false;
208
209 // NULL out the control members until the controls are created.
210 mForegroundStartT = NULL;
211 mForegroundEndT = NULL;
212 mBackgroundStartT = NULL;
213 mBackgroundEndT = NULL;
214 wxString number;
215
216 auto p = FindProjectFromWindow( this );
218
219 const auto options = NumericTextCtrl::Options{}
220 .AutoPos(true)
221 .MenuEnabled(false)
222 .ReadOnly(true);
223
224 ShuttleGui S(this, eIsCreating);
225
226 S.SetBorder(5);
227 S.StartHorizontalLay(wxCENTER, false);
228 {
229 S.AddTitle(
230 /* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
231 XO("Contrast Analyzer, for measuring RMS volume differences between two selections of audio."));
232 }
233 S.EndHorizontalLay();
234 S.StartStatic( XO("Parameters") );
235 {
236 S.StartMultiColumn(5, wxEXPAND);
237 {
238
239 // Headings
240 S.AddFixedText( {} ); // spacer
241 S.AddFixedText(XO("Start"));
242 S.AddFixedText(XO("End"));
243 S.AddFixedText( {} ); // spacer
244 S.AddFixedText(XO("Volume "));
245
246 //Foreground
247 S.AddFixedText(XO("&Foreground:"), false);
248 if (S.GetMode() == eIsCreating)
249 {
254 0.0,
256 options);
257 }
258 S.Name(XO("Foreground start time"))
259 .AddWindow(mForegroundStartT);
260
261 if (S.GetMode() == eIsCreating)
262 {
267 0.0,
269 options);
270 }
271 S.Name(XO("Foreground end time"))
272 .AddWindow(mForegroundEndT);
273
274 m_pButton_UseCurrentF = S.Id(ID_BUTTON_USECURRENTF).AddButton(XXO("&Measure selection"));
276 .ConnectRoot(wxEVT_KEY_DOWN,
278 .AddTextBox( {}, wxT(""), 17);
279
280 //Background
281 S.AddFixedText(XO("&Background:"));
282 if (S.GetMode() == eIsCreating)
283 {
288 0.0,
290 options);
291 }
292 S.Name(XO("Background start time"))
293 .AddWindow(mBackgroundStartT);
294
295 if (S.GetMode() == eIsCreating)
296 {
301 0.0,
303 options);
304 }
305 S.Name(XO("Background end time"))
306 .AddWindow(mBackgroundEndT);
307
308 m_pButton_UseCurrentB = S.Id(ID_BUTTON_USECURRENTB).AddButton(XXO("Mea&sure selection"));
310 .ConnectRoot(wxEVT_KEY_DOWN,
312 .AddTextBox( {}, wxT(""), 17);
313 }
314 S.EndMultiColumn();
315 }
316 S.EndStatic();
317
318 //Result
319 S.StartStatic( XO("Result") );
320 {
321 S.StartMultiColumn(3, wxCENTER);
322 {
323 auto label = XO("Co&ntrast Result:");
324 S.AddFixedText(label);
326 .Name(label)
327 .ConnectRoot(wxEVT_KEY_DOWN,
329 .AddTextBox( {}, wxT(""), 50);
330 m_pButton_Reset = S.Id(ID_BUTTON_RESET).AddButton(XXO("R&eset"));
331
332 label = XO("&Difference:");
333 S.AddFixedText(label);
335 .Name(label)
336 .ConnectRoot(wxEVT_KEY_DOWN,
338 .AddTextBox( {}, wxT(""), 50);
339 m_pButton_Export = S.Id(ID_BUTTON_EXPORT).AddButton(XXO("E&xport..."));
340 }
341 S.EndMultiColumn();
342 }
343 S.EndStatic();
344 S.AddStandardButtons(eCloseButton |eHelpButton);
345#if 0
346 S.StartMultiColumn(3, wxEXPAND);
347 {
348 S.SetStretchyCol(1);
349 m_pButton_GetURL = S.Id(ID_BUTTON_GETURL).AddButton(XO("&Help"));
350 S.AddFixedText({}); // spacer
351 m_pButton_Close = S.Id(ID_BUTTON_CLOSE).AddButton(XO("&Close"));
352 }
353 S.EndMultiColumn();
354#endif
355 Layout();
356 Fit();
357 SetMinSize(GetSize());
358 Center();
359}
360
361void ContrastDialog::OnGetURL(wxCommandEvent & WXUNUSED(event))
362{
363 // Original help page is back on-line (March 2016), but the manual should be more reliable.
364 // http://www.eramp.com/WCAG_2_audio_contrast_tool_help.htm
365 HelpSystem::ShowHelp(this, L"Contrast");
366}
367
368void ContrastDialog::OnClose(wxCommandEvent & WXUNUSED(event))
369{
370 wxCommandEvent dummyEvent;
371 OnReset(dummyEvent);
372
373 Show(false);
374}
375
376void ContrastDialog::OnGetForeground(wxCommandEvent & /*event*/)
377{
378 auto p = FindProjectFromWindow( this );
379 auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
380
381 if( TrackList::Get( *p ).Selected< const WaveTrack >() ) {
382 mForegroundStartT->SetValue(selectedRegion.t0());
383 mForegroundEndT->SetValue(selectedRegion.t1());
384 }
385
388 m_pButton_UseCurrentF->SetFocus();
389 results();
390}
391
392void ContrastDialog::OnGetBackground(wxCommandEvent & /*event*/)
393{
394 auto p = FindProjectFromWindow( this );
395 auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
396
397 if( TrackList::Get( *p ).Selected< const WaveTrack >() ) {
398 mBackgroundStartT->SetValue(selectedRegion.t0());
399 mBackgroundEndT->SetValue(selectedRegion.t1());
400 }
401
404 m_pButton_UseCurrentB->SetFocus();
405 results();
406}
407
408namespace {
409 // PRL: I gathered formatting into these functions, and eliminated some
410 // repetitions, and removed the redundant word "Average" as applied to RMS.
411 // Should these variations in formats be collapsed further?
412
413 // Pass nullptr when value is not yet defined
415 {
416
417 /* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
418 auto format0 = XO("RMS = %s.");
419
420 /* i18n-hint: dB abbreviates decibels */
421 auto format1 = XO("%s dB");
422
423 TranslatableString value;
424
425 if ( pValue ) {
426 if( fabs( *pValue ) != std::numeric_limits<float>::infinity() ) {
427 auto number = wxString::Format( wxT("%.2f"), *pValue );
428 value = format1.Format( number );
429 }
430 else
431 value = XO("zero");
432 }
433 else
434 value = format1.Format( "" );
435
436 return format0.Format( value );
437 }
438
440 {
441 if( diffdB != diffdB ) // test for NaN, reliant on IEEE implementation
442 return XO("indeterminate");
443 else {
444 if( diffdB != std::numeric_limits<float>::infinity() )
445 /* i18n-hint: dB abbreviates decibels
446 * RMS abbreviates root mean square, a certain averaging method */
447 return XO("%.2f dB RMS").Format( diffdB );
448 else
449 /* i18n-hint: dB abbreviates decibels */
450 return XO("Infinite dB difference");
451 }
452 }
453
455 {
456 if( diffdB != diffdB ) //test for NaN, reliant on IEEE implementation
457 return XO("Difference is indeterminate.");
458 else
459 if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
460 /* i18n-hint: dB abbreviates decibels
461 RMS abbreviates root mean square, a certain averaging method */
462 return XO("Difference = %.2f RMS dB.").Format( diffdB );
463 else
464 /* i18n-hint: dB abbreviates decibels
465 RMS abbreviates root mean square, a certain averaging method */
466 return XO("Difference = infinite RMS dB.");
467 }
468}
469
471{
472 mPassFailText->SetName(wxT(""));
473 mPassFailText->ChangeValue(wxT(""));
474 mDiffText->ChangeValue(wxT(""));
475
476 // foreground and background defined.
478 float diffdB = std::fabs(foregrounddB - backgrounddB);
480 mPassFailText->ChangeValue(_("Foreground level too high"));
481 }
482 else if (backgrounddB > DB_MAX_LIMIT) {
483 mPassFailText->ChangeValue(_("Background level too high"));
484 }
485 else if (backgrounddB > foregrounddB) {
486 mPassFailText->ChangeValue(_("Background higher than foreground"));
487 }
488 else if(diffdB > WCAG2_PASS) {
489 /* i18n-hint: WCAG2 is the 'Web Content Accessibility Guidelines (WCAG) 2.0', see http://www.w3.org/TR/WCAG20/ */
490 mPassFailText->ChangeValue(_("WCAG2 Pass"));
491 }
492 else {
493 /* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
494 mPassFailText->ChangeValue(_("WCAG2 Fail"));
495 }
496
497 /* i18n-hint: i.e. difference in loudness at the moment. */
498 mDiffText->SetName(_("Current difference"));
499 mDiffText->ChangeValue( FormatDifference( diffdB ).Translation() );
500 }
501
503 mForegroundRMSText->SetName(_("Measured foreground level")); // Read by screen-readers
504 if(std::isinf(- foregrounddB))
505 mForegroundRMSText->ChangeValue(_("zero"));
506 else
507 // i18n-hint: short form of 'decibels'
508 mForegroundRMSText->ChangeValue(wxString::Format(_("%.2f dB"), foregrounddB));
509 }
510 else {
511 mForegroundRMSText->SetName(_("No foreground measured")); // Read by screen-readers
512 mForegroundRMSText->ChangeValue(wxT(""));
513 mPassFailText->ChangeValue(_("Foreground not yet measured"));
514 }
515
517 mBackgroundRMSText->SetName(_("Measured background level"));
518 if(std::isinf(- backgrounddB))
519 mBackgroundRMSText->ChangeValue(_("zero"));
520 else
521 mBackgroundRMSText->ChangeValue(wxString::Format(_("%.2f dB"), backgrounddB));
522 }
523 else {
524 mBackgroundRMSText->SetName(_("No background measured"));
525 mBackgroundRMSText->ChangeValue(wxT(""));
526 mPassFailText->ChangeValue(_("Background not yet measured"));
527 }
528}
529
530void ContrastDialog::OnExport(wxCommandEvent & WXUNUSED(event))
531{
532 // TODO: Handle silence checks better (-infinity dB)
533 auto project = FindProjectFromWindow( this );
534 wxString fName = wxT("contrast.txt");
535
536 fName = SelectFile(FileNames::Operation::Export,
537 XO("Export Contrast Result As:"),
538 wxEmptyString,
539 fName,
540 wxT("txt"),
542 wxFD_SAVE | wxRESIZE_BORDER,
543 this);
544
545 if (fName.empty())
546 return;
547
548 wxFFileOutputStream ffStream{ fName };
549
550 if (!ffStream.IsOk()) {
551 AudacityMessageBox( XO("Couldn't write to file: %s").Format( fName ) );
552 return;
553 }
554
555 wxTextOutputStream ss(ffStream);
556
557 ss
558 << wxT("===================================") << '\n'
559 /* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
560 << XO("WCAG 2.0 Success Criteria 1.4.7 Contrast Results") << '\n'
561 << '\n'
562 << XO("Filename = %s.").Format( ProjectFileIO::Get(*project).GetFileName() ) << '\n'
563 << '\n'
564 << XO("Foreground") << '\n';
565
566 float t = (float)mForegroundStartT->GetValue();
567 int h = (int)(t/3600); // there must be a standard function for this!
568 int m = (int)((t - h*3600)/60);
569 float s = t - h*3600.0 - m*60.0;
570
571 ss
572 << XO("Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
573 .Format( h, m, s ) << '\n';
574
575 t = (float)mForegroundEndT->GetValue();
576 h = (int)(t/3600);
577 m = (int)((t - h*3600)/60);
578 s = t - h*3600.0 - m*60.0;
579
580 ss
581 << XO("Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
582 .Format( h, m, s ) << '\n'
583 << FormatRMSMessage( mForegroundIsDefined ? &foregrounddB : nullptr ) << '\n'
584 << '\n'
585 << XO("Background") << '\n';
586
587 t = (float)mBackgroundStartT->GetValue();
588 h = (int)(t/3600);
589 m = (int)((t - h*3600)/60);
590 s = t - h*3600.0 - m*60.0;
591
592 ss
593 << XO("Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
594 .Format( h, m, s ) << '\n';
595
596 t = (float)mBackgroundEndT->GetValue();
597 h = (int)(t/3600);
598 m = (int)((t - h*3600)/60);
599 s = t - h*3600.0 - m*60.0;
600
601 ss
602 << XO("Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
603 .Format( h, m, s ) << '\n'
604 << FormatRMSMessage( mBackgroundIsDefined ? &backgrounddB : nullptr ) << '\n'
605 << '\n'
606 << XO("Results") << '\n';
607
608 float diffdB = foregrounddB - backgrounddB;
609
610 ss
611 << FormatDifferenceForExport( diffdB ) << '\n'
612 << (( diffdB > 20. )
613 ? XO("Success Criteria 1.4.7 of WCAG 2.0: Pass")
614 : XO("Success Criteria 1.4.7 of WCAG 2.0: Fail")) << '\n'
615 << '\n'
616 << XO("Data gathered") << '\n';
617
618 wxDateTime now = wxDateTime::Now();
619 int year = now.GetYear();
620 wxDateTime::Month month = now.GetMonth();
621 wxString monthName = now.GetMonthName(month);
622 int dom = now.GetDay();
623 int hour = now.GetHour();
624 int minute = now.GetMinute();
625 int second = now.GetSecond();
626 /* i18n-hint: day of month, month, year, hour, minute, second */
627 auto sNow = XO("%d %s %02d %02dh %02dm %02ds")
628 .Format( dom, monthName, year, hour, minute, second );
629
630 ss <<
631 sNow << '\n'
632 << wxT("===================================") << '\n'
633 << '\n';
634}
635
636void ContrastDialog::OnReset(wxCommandEvent & /*event*/)
637{
642 mForegroundIsDefined = false;
643 mBackgroundIsDefined = false;
644
645 mForegroundRMSText->SetName(_("No foreground measured")); // Read by screen-readers
646 mBackgroundRMSText->SetName(_("No background measured"));
647 mForegroundRMSText->ChangeValue(wxT("")); // Displayed value
648 mBackgroundRMSText->ChangeValue(wxT(""));
649 mPassFailText->ChangeValue(wxT(""));
650 mDiffText->ChangeValue(wxT(""));
651}
652
653// Remaining code hooks this add-on into the application
656#include "ProjectWindows.h"
657
658namespace {
659
660// Contrast window attached to each project is built on demand by:
661AttachedWindows::RegisteredFactory sContrastDialogKey{
662 []( AudacityProject &parent ) -> wxWeakRef< wxWindow > {
663 auto &window = ProjectWindow::Get( parent );
664 return safenew ContrastDialog(
665 &window, -1, XO("Contrast Analysis (WCAG 2 compliance)"),
666 wxPoint{ 150, 150 }
667 );
668 }
669};
670
671// Define our extra menu item that invokes that factory
673 void OnContrast(const CommandContext &context)
674 {
675 auto &project = context.project;
676 CommandManager::Get(project).RegisterLastAnalyzer(context); //Register Contrast as Last Analyzer
677 auto contrastDialog = &GetAttachedWindows(project)
679
680 contrastDialog->CentreOnParent();
681 if( VetoDialogHook::Call( contrastDialog ) )
682 return;
683 contrastDialog->Show();
684 }
685};
686
688 // Handler is not stateful. Doesn't need a factory registered with
689 // AudacityProject.
690 static Handler instance;
691 return instance;
692}
693
694// Register that menu item
695
696using namespace MenuTable;
697AttachedItem sAttachment{ wxT("Analyze/Analyzers/Windows"),
699 Command( wxT("ContrastAnalyser"), XXO("Contrast..."),
700 &Handler::OnContrast,
702 wxT("Ctrl+Shift+T") ) )
703};
704
705}
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
END_EVENT_TABLE()
wxEvtHandler CommandHandlerObject
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
#define WCAG2_PASS
Definition: Contrast.cpp:49
#define DB_MAX_LIMIT
Definition: Contrast.cpp:48
@ ID_BACKGROUNDEND_T
Definition: Contrast.cpp:164
@ ID_FOREGROUNDDB_TEXT
Definition: Contrast.cpp:165
@ ID_BACKGROUNDSTART_T
Definition: Contrast.cpp:163
@ ID_BUTTON_RESET
Definition: Contrast.cpp:159
@ ID_BUTTON_USECURRENTF
Definition: Contrast.cpp:155
@ ID_BACKGROUNDDB_TEXT
Definition: Contrast.cpp:166
@ ID_RESULTSDB_TEXT
Definition: Contrast.cpp:168
@ ID_RESULTS_TEXT
Definition: Contrast.cpp:167
@ ID_BUTTON_USECURRENTB
Definition: Contrast.cpp:156
@ ID_FOREGROUNDSTART_T
Definition: Contrast.cpp:161
@ ID_FOREGROUNDEND_T
Definition: Contrast.cpp:162
@ ID_BUTTON_EXPORT
Definition: Contrast.cpp:158
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:503
static const auto title
an object holding per-project preferred sample rate
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
AUDACITY_DLL_API AttachedWindows & GetAttachedWindows(AudacityProject &project)
accessors for certain important windows associated with each project
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
@ eIsCreating
Definition: ShuttleGui.h:39
@ eCloseButton
Definition: ShuttleGui.h:610
@ eHelpButton
Definition: ShuttleGui.h:604
TranslatableString label
Definition: TagsEditor.cpp:163
#define S(N)
Definition: ToChars.cpp:64
int id
Wrap wxMessageDialog so that caption IS translatable.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:251
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:309
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
void RegisterLastAnalyzer(const CommandContext &context)
static CommandManager & Get(AudacityProject &project)
NumericTextCtrl * mBackgroundStartT
Definition: Contrast.h:43
wxButton * m_pButton_Close
Definition: Contrast.h:39
void OnClose(wxCommandEvent &event)
Definition: Contrast.cpp:368
bool mBackgroundIsDefined
Definition: Contrast.h:73
double mT0
Definition: Contrast.h:46
void OnChar(wxKeyEvent &event)
Definition: Contrast.cpp:180
NumericTextCtrl * mBackgroundEndT
Definition: Contrast.h:44
wxTextCtrl * mBackgroundRMSText
Definition: Contrast.h:66
wxButton * m_pButton_UseCurrentB
Definition: Contrast.h:35
void OnExport(wxCommandEvent &event)
Definition: Contrast.cpp:530
void OnGetBackground(wxCommandEvent &event)
Definition: Contrast.cpp:392
ContrastDialog(wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos)
Definition: Contrast.cpp:194
double mProjectRate
Definition: Contrast.h:48
bool mForegroundIsDefined
Definition: Contrast.h:72
void SetStartAndEndTime()
Definition: Contrast.cpp:137
void results()
Definition: Contrast.cpp:470
double mT1
Definition: Contrast.h:47
NumericTextCtrl * mForegroundStartT
Definition: Contrast.h:41
bool GetDB(float &dB)
Definition: Contrast.cpp:52
void OnReset(wxCommandEvent &event)
Definition: Contrast.cpp:636
wxButton * m_pButton_Export
Definition: Contrast.h:37
void OnGetURL(wxCommandEvent &event)
Definition: Contrast.cpp:361
float foregrounddB
Definition: Contrast.h:70
wxTextCtrl * mForegroundRMSText
Definition: Contrast.h:65
wxButton * m_pButton_Reset
Definition: Contrast.h:38
wxTextCtrl * mDiffText
Definition: Contrast.h:68
wxButton * m_pButton_UseCurrentF
Definition: Contrast.h:34
NumericTextCtrl * mForegroundEndT
Definition: Contrast.h:42
float backgrounddB
Definition: Contrast.h:71
void OnGetForeground(wxCommandEvent &event)
Definition: Contrast.cpp:376
wxTextCtrl * mPassFailText
Definition: Contrast.h:67
wxButton * m_pButton_GetURL
Definition: Contrast.h:36
FILES_API const FileType AllFiles
Definition: FileNames.h:71
FILES_API const FileType TextFiles
Definition: FileNames.h:74
Abstract base class used in importing a file.
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
static NumericFormatSymbol HundredthsFormat()
void SetValue(double newValue)
static ProjectFileIO & Get(AudacityProject &project)
const FilePath & GetFileName() const
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
static ProjectWindow & Get(AudacityProject &project)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1480
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:467
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1446
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1533
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
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
#define INFINITY
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
TranslatableString FormatRMSMessage(float *pValue)
Definition: Contrast.cpp:414
AttachedWindows::RegisteredFactory sContrastDialogKey
Definition: Contrast.cpp:661
TranslatableString FormatDifferenceForExport(float diffdB)
Definition: Contrast.cpp:454
TranslatableString FormatDifference(float diffdB)
Definition: Contrast.cpp:439
CommandHandlerObject & findCommandHandler(AudacityProject &)
Definition: Contrast.cpp:687
Options & MenuEnabled(bool enable)
Options & AutoPos(bool enable)
Options & ReadOnly(bool enable)
void OnContrast(const CommandContext &context)
Definition: Contrast.cpp:673