15#include "../CommonCommandFlags.h"
21#include "../ProjectWindow.h"
27#include "../widgets/NumericTextCtrl.h"
29#include "../widgets/VetoDialogHook.h"
34#if defined(__WXMSW__) && !defined(__CYGWIN__)
36#define finite(x) _finite(x)
40#include <wx/valtext.h>
42#include <wx/wfstream.h>
43#include <wx/txtstrm.h>
44#include <wx/textctrl.h>
50#define DB_MAX_LIMIT 0.0
51#define WCAG2_PASS 20.0
56 float rms = float(0.0);
64 auto numberSelectedTracks = range.
size();
65 if (numberSelectedTracks > 1) {
68 XO(
"You can only measure one track at a time."),
74 if(numberSelectedTracks == 0) {
77 XO(
"Please select an audio track."),
85 for (
auto t : channels ) {
89 if(mT0 < t->GetStartTime())
90 mT0 = t->GetStartTime();
91 if(
mT1 > t->GetEndTime())
92 mT1 = t->GetEndTime();
94 auto SelT0 = t->TimeToLongSamples(
mT0);
95 auto SelT1 = t->TimeToLongSamples(
mT1);
101 XO(
"Invalid audio selection.\nPlease ensure that audio is selected."),
112 XO(
"Nothing to measure.\nPlease select a section of a track."),
120 rms = t->GetRMS(
mT0,
mT1,
false);
126 ?
sqrt( meanSq/
static_cast<double>( channels.size() ) )
143 mT0 = selectedRegion.t0();
144 mT1 = selectedRegion.t1();
185 if (event.GetKeyCode() == WXK_TAB) {
198 const wxPoint & pos):
200 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX )
229 S.StartHorizontalLay(wxCENTER,
false);
233 XO(
"Contrast Analyzer, for measuring RMS volume differences between two selections of audio."));
235 S.EndHorizontalLay();
236 S.StartStatic(
XO(
"Parameters") );
238 S.StartMultiColumn(5, wxEXPAND);
242 S.AddFixedText( {} );
243 S.AddFixedText(
XO(
"Start"));
244 S.AddFixedText(
XO(
"End"));
245 S.AddFixedText( {} );
246 S.AddFixedText(
XO(
"Volume "));
249 S.AddFixedText(
XO(
"&Foreground:"),
false);
260 S.Name(
XO(
"Foreground start time"))
273 S.Name(
XO(
"Foreground end time"))
278 .ConnectRoot(wxEVT_KEY_DOWN,
280 .AddTextBox( {},
wxT(
""), 17);
283 S.AddFixedText(
XO(
"&Background:"));
294 S.Name(
XO(
"Background start time"))
307 S.Name(
XO(
"Background end time"))
312 .ConnectRoot(wxEVT_KEY_DOWN,
314 .AddTextBox( {},
wxT(
""), 17);
321 S.StartStatic(
XO(
"Result") );
323 S.StartMultiColumn(3, wxCENTER);
325 auto label =
XO(
"Co&ntrast Result:");
329 .ConnectRoot(wxEVT_KEY_DOWN,
331 .AddTextBox( {},
wxT(
""), 50);
338 .ConnectRoot(wxEVT_KEY_DOWN,
340 .AddTextBox( {},
wxT(
""), 50);
348 S.StartMultiColumn(3, wxEXPAND);
359 SetMinSize(GetSize());
372 wxCommandEvent dummyEvent;
420 auto format0 =
XO(
"RMS = %s.");
423 auto format1 =
XO(
"%s dB");
428 if( fabs( *pValue ) != std::numeric_limits<float>::infinity() ) {
429 auto number = wxString::Format(
wxT(
"%.2f"), *pValue );
430 value = format1.
Format( number );
436 value = format1.
Format(
"" );
438 return format0.
Format( value );
443 if( diffdB != diffdB )
444 return XO(
"indeterminate");
446 if( diffdB != std::numeric_limits<float>::infinity() )
449 return XO(
"%.2f dB RMS").Format( diffdB );
452 return XO(
"Infinite dB difference");
458 if( diffdB != diffdB )
459 return XO(
"Difference is indeterminate.");
461 if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
464 return XO(
"Difference = %.2f RMS dB.").Format( diffdB );
468 return XO(
"Difference = infinite RMS dB.");
488 mPassFailText->ChangeValue(
_(
"Background higher than foreground"));
536 wxString fName =
wxT(
"contrast.txt");
538 fName =
SelectFile(FileNames::Operation::Export,
539 XO(
"Export Contrast Result As:"),
544 wxFD_SAVE | wxRESIZE_BORDER,
550 wxFFileOutputStream ffStream{ fName };
552 if (!ffStream.IsOk()) {
557 wxTextOutputStream ss(ffStream);
560 <<
wxT(
"===================================") <<
'\n'
562 <<
XO(
"WCAG 2.0 Success Criteria 1.4.7 Contrast Results") <<
'\n'
566 <<
XO(
"Foreground") <<
'\n';
569 int h = (int)(t/3600);
570 int m = (int)((t - h*3600)/60);
571 float s = t - h*3600.0 - m*60.0;
574 <<
XO(
"Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
575 .Format( h, m, s ) <<
'\n';
579 m = (int)((t - h*3600)/60);
580 s = t - h*3600.0 - m*60.0;
583 <<
XO(
"Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
584 .Format( h, m, s ) <<
'\n'
587 <<
XO(
"Background") <<
'\n';
591 m = (int)((t - h*3600)/60);
592 s = t - h*3600.0 - m*60.0;
595 <<
XO(
"Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
596 .Format( h, m, s ) <<
'\n';
600 m = (int)((t - h*3600)/60);
601 s = t - h*3600.0 - m*60.0;
604 <<
XO(
"Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
605 .Format( h, m, s ) <<
'\n'
608 <<
XO(
"Results") <<
'\n';
615 ?
XO(
"Success Criteria 1.4.7 of WCAG 2.0: Pass")
616 :
XO(
"Success Criteria 1.4.7 of WCAG 2.0: Fail")) <<
'\n'
618 <<
XO(
"Data gathered") <<
'\n';
620 wxDateTime now = wxDateTime::Now();
621 int year = now.GetYear();
622 wxDateTime::Month month = now.GetMonth();
623 wxString monthName = now.GetMonthName(month);
624 int dom = now.GetDay();
625 int hour = now.GetHour();
626 int minute = now.GetMinute();
627 int second = now.GetSecond();
629 auto sNow =
XO(
"%d %s %02d %02dh %02dm %02ds")
630 .Format( dom, monthName, year, hour, minute, second );
634 <<
wxT(
"===================================") <<
'\n'
667 &window, -1,
XO(
"Contrast Analysis (WCAG 2 compliance)"),
677 auto &project = context.
project;
682 contrastDialog->CentreOnParent();
685 contrastDialog->Show();
696 wxT(
"Ctrl+Shift+T") )
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
XXO("&Cut/Copy/Paste Toolbar")
const NumericConverterType & NumericConverterType_TIME()
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)
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...
size_t size() const
How many attachment pointers are in the Site.
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
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
wxButton * m_pButton_Close
void OnClose(wxCommandEvent &event)
bool mBackgroundIsDefined
void OnChar(wxKeyEvent &event)
NumericTextCtrl * mBackgroundEndT
wxTextCtrl * mBackgroundRMSText
wxButton * m_pButton_UseCurrentB
void OnExport(wxCommandEvent &event)
void OnGetBackground(wxCommandEvent &event)
ContrastDialog(wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos)
bool mForegroundIsDefined
void SetStartAndEndTime()
NumericTextCtrl * mForegroundStartT
void OnReset(wxCommandEvent &event)
wxButton * m_pButton_Export
void OnGetURL(wxCommandEvent &event)
wxTextCtrl * mForegroundRMSText
wxButton * m_pButton_Reset
wxButton * m_pButton_UseCurrentF
NumericTextCtrl * mForegroundEndT
void OnGetForeground(wxCommandEvent &event)
wxTextCtrl * mPassFailText
wxButton * m_pButton_GetURL
FILES_API const FileType AllFiles
FILES_API const FileType TextFiles
static FormatterContext SampleRateContext(double sampleRate)
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)
void SetValue(double newValue)
static ProjectFileIO & Get(AudacityProject &project)
const FilePath & GetFileName() const
static ProjectRate & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
auto SelectedLeaders() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
auto Selected() -> TrackIterRange< TrackType >
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
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
static ViewInfo & Get(AudacityProject &project)
A Track that contains audio waveform data.
void OnContrast(const CommandContext &context)
TranslatableString FormatRMSMessage(float *pValue)
AttachedWindows::RegisteredFactory sContrastDialogKey
TranslatableString FormatDifferenceForExport(float diffdB)
TranslatableString FormatDifference(float diffdB)
__finl float_x4 __vecc sqrt(const float_x4 &a)
Options & MenuEnabled(bool enable)
Options & AutoPos(bool enable)
Options & ReadOnly(bool enable)