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 "ProjectFileIO.h"
18#include "ProjectRate.h"
19#include "../ProjectWindowBase.h"
20#include "SelectFile.h"
21#include "ShuttleGui.h"
22#include "FileNames.h"
23#include "ViewInfo.h"
24#include "HelpSystem.h"
25#include "../widgets/NumericTextCtrl.h"
26#include "AudacityMessageBox.h"
27
28#include <cmath>
29#include <limits>
30
31#if defined(__WXMSW__) && !defined(__CYGWIN__)
32#include <float.h>
33#define finite(x) _finite(x)
34#endif
35
36#include <wx/button.h>
37#include <wx/valtext.h>
38#include <wx/log.h>
39#include <wx/wfstream.h>
40#include <wx/txtstrm.h>
41#include <wx/textctrl.h>
42
44
46
47#define DB_MAX_LIMIT 0.0 // Audio is massively distorted.
48#define WCAG2_PASS 20.0 // dB difference required to pass WCAG2 test.
49
50// WDR: class implementations
51
52//----------------------------------------------------------------------------
53// ContrastDialog
54//----------------------------------------------------------------------------
55
56// WDR: event table for ContrastDialog
57
58enum {
61 //ID_BUTTON_GETURL,
64 //ID_BUTTON_CLOSE,
73};
74
75BEGIN_EVENT_TABLE(ContrastDialog,wxDialogWrapper)
83
84void ContrastDialog::OnChar(wxKeyEvent &event)
85{
86 // Is this still required?
87 if (event.GetKeyCode() == WXK_TAB) {
88 // pass to next handler
89 event.Skip();
90 return;
91 }
92
93 // ignore any other key
94 event.Skip(false);
95 return;
96}
97
98ContrastDialog::ContrastDialog(wxWindow * parent, wxWindowID id,
100 const wxPoint & pos):
101 wxDialogWrapper(parent, id, title, pos, wxDefaultSize,
102 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX )
103{
104 SetName();
105
106 mT0 = 0.0;
107 mT1 = 0.0;
108 foregrounddB = 0.0;
109 backgrounddB = 0.0;
110 mForegroundIsDefined = false;
111 mBackgroundIsDefined = false;
112
113 // NULL out the control members until the controls are created.
114 mForegroundStartT = NULL;
115 mForegroundEndT = NULL;
116 mBackgroundStartT = NULL;
117 mBackgroundEndT = NULL;
118 wxString number;
119
120 auto p = FindProjectFromWindow( this );
122
123 const auto options = NumericTextCtrl::Options{}
124 .AutoPos(true)
125 .MenuEnabled(false)
126 .ReadOnly(true);
127
128 ShuttleGui S(this, eIsCreating);
129
130 S.SetBorder(5);
131 S.StartHorizontalLay(wxCENTER, false);
132 {
133 S.AddTitle(
134 /* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
135 XO("Contrast Analyzer, for measuring RMS volume differences between two selections of audio."));
136 }
137 S.EndHorizontalLay();
138 S.StartStatic( XO("Parameters") );
139 {
140 S.StartMultiColumn(5, wxEXPAND);
141 {
142
143 // Headings
144 S.AddFixedText( {} ); // spacer
145 S.AddFixedText(XO("Start"));
146 S.AddFixedText(XO("End"));
147 S.AddFixedText( {} ); // spacer
148 S.AddFixedText(XO("Volume "));
149
150 //Foreground
151 S.AddFixedText(XO("&Foreground:"), false);
152 if (S.GetMode() == eIsCreating)
153 {
156 S.GetParent(), ID_FOREGROUNDSTART_T,
159 0.0,
160 options);
161 }
162 S.Name(XO("Foreground start time"))
163 .AddWindow(mForegroundStartT);
164
165 if (S.GetMode() == eIsCreating)
166 {
169 S.GetParent(), ID_FOREGROUNDEND_T,
172 0.0,
173 options);
174 }
175 S.Name(XO("Foreground end time"))
176 .AddWindow(mForegroundEndT);
177
178 m_pButton_UseCurrentF = S.Id(ID_BUTTON_USECURRENTF).AddButton(XXO("&Measure selection"));
180 .ConnectRoot(wxEVT_KEY_DOWN,
182 .AddTextBox( {}, wxT(""), 17);
183
184 //Background
185 S.AddFixedText(XO("&Background:"));
186 if (S.GetMode() == eIsCreating)
187 {
190 S.GetParent(), ID_BACKGROUNDSTART_T,
193 0.0,
194 options);
195 }
196 S.Name(XO("Background start time"))
197 .AddWindow(mBackgroundStartT);
198
199 if (S.GetMode() == eIsCreating)
200 {
203 S.GetParent(), ID_BACKGROUNDEND_T,
206 0.0,
207 options);
208 }
209 S.Name(XO("Background end time"))
210 .AddWindow(mBackgroundEndT);
211
212 m_pButton_UseCurrentB = S.Id(ID_BUTTON_USECURRENTB).AddButton(XXO("Mea&sure selection"));
214 .ConnectRoot(wxEVT_KEY_DOWN,
216 .AddTextBox( {}, wxT(""), 17);
217 }
218 S.EndMultiColumn();
219 }
220 S.EndStatic();
221
222 //Result
223 S.StartStatic( XO("Result") );
224 {
225 S.StartMultiColumn(3, wxCENTER);
226 {
227 auto label = XO("Co&ntrast Result:");
228 S.AddFixedText(label);
230 .Name(label)
231 .ConnectRoot(wxEVT_KEY_DOWN,
233 .AddTextBox( {}, wxT(""), 50);
234 m_pButton_Reset = S.Id(ID_BUTTON_RESET).AddButton(XXO("R&eset"));
235
236 label = XO("&Difference:");
237 S.AddFixedText(label);
239 .Name(label)
240 .ConnectRoot(wxEVT_KEY_DOWN,
242 .AddTextBox( {}, wxT(""), 50);
243 m_pButton_Export = S.Id(ID_BUTTON_EXPORT).AddButton(XXO("E&xport..."));
244 }
245 S.EndMultiColumn();
246 }
247 S.EndStatic();
248 S.AddStandardButtons(eCloseButton |eHelpButton);
249#if 0
250 S.StartMultiColumn(3, wxEXPAND);
251 {
252 S.SetStretchyCol(1);
253 m_pButton_GetURL = S.Id(ID_BUTTON_GETURL).AddButton(XO("&Help"));
254 S.AddFixedText({}); // spacer
255 m_pButton_Close = S.Id(ID_BUTTON_CLOSE).AddButton(XO("&Close"));
256 }
257 S.EndMultiColumn();
258#endif
259 Layout();
260 Fit();
261 SetMinSize(GetSize());
262 Center();
263}
264
265void ContrastDialog::OnGetURL(wxCommandEvent & WXUNUSED(event))
266{
267 // Original help page is back on-line (March 2016), but the manual should be more reliable.
268 // http://www.eramp.com/WCAG_2_audio_contrast_tool_help.htm
269 HelpSystem::ShowHelp(this, L"Contrast");
270}
271
272void ContrastDialog::OnClose(wxCommandEvent & WXUNUSED(event))
273{
274 wxCommandEvent dummyEvent;
275 OnReset(dummyEvent);
276
277 Show(false);
278}
279
280void ContrastDialog::OnGetForeground(wxCommandEvent & /*event*/)
281{
282 auto p = FindProjectFromWindow( this );
283 auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
284
285 if (TrackList::Get(*p).Selected<const WaveTrack>()) {
286 mForegroundStartT->SetValue(selectedRegion.t0());
287 mForegroundEndT->SetValue(selectedRegion.t1());
288 }
289
292 m_pButton_UseCurrentF->SetFocus();
293 results();
294}
295
296void ContrastDialog::OnGetBackground(wxCommandEvent & /*event*/)
297{
298 auto p = FindProjectFromWindow( this );
299 auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
300
301 if (TrackList::Get(*p).Selected<const WaveTrack>()) {
302 mBackgroundStartT->SetValue(selectedRegion.t0());
303 mBackgroundEndT->SetValue(selectedRegion.t1());
304 }
305
308 m_pButton_UseCurrentB->SetFocus();
309 results();
310}
311
312namespace {
313 // PRL: I gathered formatting into these functions, and eliminated some
314 // repetitions, and removed the redundant word "Average" as applied to RMS.
315 // Should these variations in formats be collapsed further?
316
317 // Pass nullptr when value is not yet defined
319 {
320
321 /* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
322 auto format0 = XO("RMS = %s.");
323
324 /* i18n-hint: dB abbreviates decibels */
325 auto format1 = XO("%s dB");
326
327 TranslatableString value;
328
329 if ( pValue ) {
330 if( fabs( *pValue ) != std::numeric_limits<float>::infinity() ) {
331 auto number = wxString::Format( wxT("%.2f"), *pValue );
332 value = format1.Format( number );
333 }
334 else
335 value = XO("zero");
336 }
337 else
338 value = format1.Format( "" );
339
340 return format0.Format( value );
341 }
342
344 {
345 if( diffdB != diffdB ) // test for NaN, reliant on IEEE implementation
346 return XO("indeterminate");
347 else {
348 if( diffdB != std::numeric_limits<float>::infinity() )
349 /* i18n-hint: dB abbreviates decibels
350 * RMS abbreviates root mean square, a certain averaging method */
351 return XO("%.2f dB RMS").Format( diffdB );
352 else
353 /* i18n-hint: dB abbreviates decibels */
354 return XO("Infinite dB difference");
355 }
356 }
357
359 {
360 if( diffdB != diffdB ) //test for NaN, reliant on IEEE implementation
361 return XO("Difference is indeterminate.");
362 else
363 if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
364 /* i18n-hint: dB abbreviates decibels
365 RMS abbreviates root mean square, a certain averaging method */
366 return XO("Difference = %.2f RMS dB.").Format( diffdB );
367 else
368 /* i18n-hint: dB abbreviates decibels
369 RMS abbreviates root mean square, a certain averaging method */
370 return XO("Difference = infinite RMS dB.");
371 }
372}
373
375{
376 mPassFailText->SetName(wxT(""));
377 mPassFailText->ChangeValue(wxT(""));
378 mDiffText->ChangeValue(wxT(""));
379
380 // foreground and background defined.
382 float diffdB = std::fabs(foregrounddB - backgrounddB);
384 mPassFailText->ChangeValue(_("Foreground level too high"));
385 }
386 else if (backgrounddB > DB_MAX_LIMIT) {
387 mPassFailText->ChangeValue(_("Background level too high"));
388 }
389 else if (backgrounddB > foregrounddB) {
390 mPassFailText->ChangeValue(_("Background higher than foreground"));
391 }
392 else if(diffdB > WCAG2_PASS) {
393 /* i18n-hint: WCAG2 is the 'Web Content Accessibility Guidelines (WCAG) 2.0', see http://www.w3.org/TR/WCAG20/ */
394 mPassFailText->ChangeValue(_("WCAG2 Pass"));
395 }
396 else {
397 /* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
398 mPassFailText->ChangeValue(_("WCAG2 Fail"));
399 }
400
401 /* i18n-hint: i.e. difference in loudness at the moment. */
402 mDiffText->SetName(_("Current difference"));
403 mDiffText->ChangeValue( FormatDifference( diffdB ).Translation() );
404 }
405
407 mForegroundRMSText->SetName(_("Measured foreground level")); // Read by screen-readers
408 if(std::isinf(- foregrounddB))
409 mForegroundRMSText->ChangeValue(_("zero"));
410 else
411 // i18n-hint: short form of 'decibels'
412 mForegroundRMSText->ChangeValue(wxString::Format(_("%.2f dB"), foregrounddB));
413 }
414 else {
415 mForegroundRMSText->SetName(_("No foreground measured")); // Read by screen-readers
416 mForegroundRMSText->ChangeValue(wxT(""));
417 mPassFailText->ChangeValue(_("Foreground not yet measured"));
418 }
419
421 mBackgroundRMSText->SetName(_("Measured background level"));
422 if(std::isinf(- backgrounddB))
423 mBackgroundRMSText->ChangeValue(_("zero"));
424 else
425 mBackgroundRMSText->ChangeValue(wxString::Format(_("%.2f dB"), backgrounddB));
426 }
427 else {
428 mBackgroundRMSText->SetName(_("No background measured"));
429 mBackgroundRMSText->ChangeValue(wxT(""));
430 mPassFailText->ChangeValue(_("Background not yet measured"));
431 }
432}
433
434void ContrastDialog::OnExport(wxCommandEvent & WXUNUSED(event))
435{
436 // TODO: Handle silence checks better (-infinity dB)
437 auto project = FindProjectFromWindow( this );
438 wxString fName = wxT("contrast.txt");
439
440 fName = SelectFile(FileNames::Operation::Export,
441 XO("Export Contrast Result As:"),
442 wxEmptyString,
443 fName,
444 wxT("txt"),
446 wxFD_SAVE | wxRESIZE_BORDER,
447 this);
448
449 if (fName.empty())
450 return;
451
452 wxFFileOutputStream ffStream{ fName };
453
454 if (!ffStream.IsOk()) {
455 AudacityMessageBox( XO("Couldn't write to file: %s").Format( fName ) );
456 return;
457 }
458
459 wxTextOutputStream ss(ffStream);
460
461 ss
462 << wxT("===================================") << '\n'
463 /* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
464 << XO("WCAG 2.0 Success Criteria 1.4.7 Contrast Results") << '\n'
465 << '\n'
466 << XO("Filename = %s.").Format( ProjectFileIO::Get(*project).GetFileName() ) << '\n'
467 << '\n'
468 << XO("Foreground") << '\n';
469
470 float t = (float)mForegroundStartT->GetValue();
471 int h = (int)(t/3600); // there must be a standard function for this!
472 int m = (int)((t - h*3600)/60);
473 float s = t - h*3600.0 - m*60.0;
474
475 ss
476 << XO("Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
477 .Format( h, m, s ) << '\n';
478
479 t = (float)mForegroundEndT->GetValue();
480 h = (int)(t/3600);
481 m = (int)((t - h*3600)/60);
482 s = t - h*3600.0 - m*60.0;
483
484 ss
485 << XO("Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
486 .Format( h, m, s ) << '\n'
487 << FormatRMSMessage( mForegroundIsDefined ? &foregrounddB : nullptr ) << '\n'
488 << '\n'
489 << XO("Background") << '\n';
490
491 t = (float)mBackgroundStartT->GetValue();
492 h = (int)(t/3600);
493 m = (int)((t - h*3600)/60);
494 s = t - h*3600.0 - m*60.0;
495
496 ss
497 << XO("Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
498 .Format( h, m, s ) << '\n';
499
500 t = (float)mBackgroundEndT->GetValue();
501 h = (int)(t/3600);
502 m = (int)((t - h*3600)/60);
503 s = t - h*3600.0 - m*60.0;
504
505 ss
506 << XO("Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
507 .Format( h, m, s ) << '\n'
508 << FormatRMSMessage( mBackgroundIsDefined ? &backgrounddB : nullptr ) << '\n'
509 << '\n'
510 << XO("Results") << '\n';
511
512 float diffdB = foregrounddB - backgrounddB;
513
514 ss
515 << FormatDifferenceForExport( diffdB ) << '\n'
516 << (( diffdB > 20. )
517 ? XO("Success Criteria 1.4.7 of WCAG 2.0: Pass")
518 : XO("Success Criteria 1.4.7 of WCAG 2.0: Fail")) << '\n'
519 << '\n'
520 << XO("Data gathered") << '\n';
521
522 wxDateTime now = wxDateTime::Now();
523 int year = now.GetYear();
524 wxDateTime::Month month = now.GetMonth();
525 wxString monthName = now.GetMonthName(month);
526 int dom = now.GetDay();
527 int hour = now.GetHour();
528 int minute = now.GetMinute();
529 int second = now.GetSecond();
530 /* i18n-hint: day of month, month, year, hour, minute, second */
531 auto sNow = XO("%d %s %02d %02dh %02dm %02ds")
532 .Format( dom, monthName, year, hour, minute, second );
533
534 ss <<
535 sNow << '\n'
536 << wxT("===================================") << '\n'
537 << '\n';
538}
539
540void ContrastDialog::OnReset(wxCommandEvent & /*event*/)
541{
546 mForegroundIsDefined = false;
547 mBackgroundIsDefined = false;
548
549 mForegroundRMSText->SetName(_("No foreground measured")); // Read by screen-readers
550 mBackgroundRMSText->SetName(_("No background measured"));
551 mForegroundRMSText->ChangeValue(wxT("")); // Displayed value
552 mBackgroundRMSText->ChangeValue(wxT(""));
553 mPassFailText->ChangeValue(wxT(""));
554 mDiffText->ChangeValue(wxT(""));
555}
556
558{
559 return *FindProjectFromWindow(this);
560}
561
562// Remaining code hooks this add-on into the application
563#include "CommandContext.h"
564#include "CommandManager.h"
565#include "ProjectWindows.h"
566
567namespace {
568
569// Contrast window attached to each project is built on demand by:
570AttachedWindows::RegisteredFactory sContrastDialogKey{
571 []( AudacityProject &parent ) -> wxWeakRef< wxWindow > {
572 auto &window = GetProjectFrame(parent);
573 return safenew ContrastDialog(
574 &window, -1, XO("Contrast Analysis (WCAG 2 compliance)"),
575 wxPoint{ 150, 150 }
576 );
577 }
578};
579
580// Define our extra menu item that invokes that factory
581namespace {
582 void OnContrast(const CommandContext &context)
583 {
584 auto &project = context.project;
586 auto contrastDialog = &GetAttachedWindows(project)
588
589 contrastDialog->CentreOnParent();
590 contrastDialog->Show();
591 }
592}
593
594// Register that menu item
595
596using namespace MenuRegistry;
598 Command( wxT("ContrastAnalyser"), XXO("Contrast..."),
601 wxT("Ctrl+Shift+T") ),
602 wxT("Analyze/Analyzers/Windows")
603};
604
605}
wxT("CloseDown"))
@ Internal
Indicates internal failure from Audacity.
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
END_EVENT_TABLE()
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
#define WCAG2_PASS
Definition: Contrast.cpp:48
@ ID_BACKGROUNDEND_T
Definition: Contrast.cpp:68
@ ID_FOREGROUNDDB_TEXT
Definition: Contrast.cpp:69
@ ID_BACKGROUNDSTART_T
Definition: Contrast.cpp:67
@ ID_BUTTON_RESET
Definition: Contrast.cpp:63
@ ID_BUTTON_USECURRENTF
Definition: Contrast.cpp:59
@ ID_BACKGROUNDDB_TEXT
Definition: Contrast.cpp:70
@ ID_RESULTSDB_TEXT
Definition: Contrast.cpp:72
@ ID_RESULTS_TEXT
Definition: Contrast.cpp:71
@ ID_BUTTON_USECURRENTB
Definition: Contrast.cpp:60
@ ID_FOREGROUNDSTART_T
Definition: Contrast.cpp:65
@ ID_FOREGROUNDEND_T
Definition: Contrast.cpp:66
@ ID_BUTTON_EXPORT
Definition: Contrast.cpp:62
#define DB_MAX_LIMIT
Definition: Contrast.cpp:47
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:10
static const auto title
const NumericConverterType & NumericConverterType_TIME()
an object holding per-project preferred sample rate
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
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:37
@ eCloseButton
Definition: ShuttleGui.h:619
@ eHelpButton
Definition: ShuttleGui.h:613
TranslatableString label
Definition: TagsEditor.cpp:165
const auto project
#define S(N)
Definition: ToChars.cpp:64
int id
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:318
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
void RegisterLastAnalyzer(const CommandContext &context)
static CommandManager & Get(AudacityProject &project)
float backgrounddB
Definition: ContrastBase.h:25
bool mForegroundIsDefined
Definition: ContrastBase.h:26
double mProjectRate
Definition: ContrastBase.h:17
bool GetDB(float &dB)
bool mBackgroundIsDefined
Definition: ContrastBase.h:27
void SetStartAndEndTime()
float foregrounddB
Definition: ContrastBase.h:24
NumericTextCtrl * mBackgroundStartT
Definition: Contrast.h:42
wxButton * m_pButton_Close
Definition: Contrast.h:38
AudacityProject & GetProject() override
Definition: Contrast.cpp:557
void OnClose(wxCommandEvent &event)
Definition: Contrast.cpp:272
void OnChar(wxKeyEvent &event)
Definition: Contrast.cpp:84
NumericTextCtrl * mBackgroundEndT
Definition: Contrast.h:43
wxTextCtrl * mBackgroundRMSText
Definition: Contrast.h:57
wxButton * m_pButton_UseCurrentB
Definition: Contrast.h:34
void OnExport(wxCommandEvent &event)
Definition: Contrast.cpp:434
void OnGetBackground(wxCommandEvent &event)
Definition: Contrast.cpp:296
ContrastDialog(wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos)
Definition: Contrast.cpp:98
void results()
Definition: Contrast.cpp:374
NumericTextCtrl * mForegroundStartT
Definition: Contrast.h:40
void OnReset(wxCommandEvent &event)
Definition: Contrast.cpp:540
wxButton * m_pButton_Export
Definition: Contrast.h:36
void OnGetURL(wxCommandEvent &event)
Definition: Contrast.cpp:265
wxTextCtrl * mForegroundRMSText
Definition: Contrast.h:56
wxButton * m_pButton_Reset
Definition: Contrast.h:37
wxTextCtrl * mDiffText
Definition: Contrast.h:59
wxButton * m_pButton_UseCurrentF
Definition: Contrast.h:33
NumericTextCtrl * mForegroundEndT
Definition: Contrast.h:41
void OnGetForeground(wxCommandEvent &event)
Definition: Contrast.cpp:280
wxTextCtrl * mPassFailText
Definition: Contrast.h:58
wxButton * m_pButton_GetURL
Definition: Contrast.h:35
FILES_API const FileType AllFiles
Definition: FileNames.h:70
FILES_API const FileType TextFiles
Definition: FileNames.h:73
Abstract base class used in importing a file.
static FormatterContext SampleRateContext(double sampleRate)
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:231
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
Generates classes whose instances register items at construction.
Definition: Registry.h:388
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:967
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:203
IMPORT_EXPORT_API ExportResult Show(ExportTask exportTask)
constexpr auto Command
Definition: MenuRegistry.h:456
NUMERIC_FORMATS_API NumericFormatSymbol HundredthsFormat()
TranslatableString FormatRMSMessage(float *pValue)
Definition: Contrast.cpp:318
AttachedWindows::RegisteredFactory sContrastDialogKey
Definition: Contrast.cpp:570
TranslatableString FormatDifferenceForExport(float diffdB)
Definition: Contrast.cpp:358
TranslatableString FormatDifference(float diffdB)
Definition: Contrast.cpp:343
Options & MenuEnabled(bool enable)
Options & AutoPos(bool enable)
Options & ReadOnly(bool enable)