15#include "../CommonCommandFlags.h"
21#include "../ProjectWindowBase.h"
27#include "../widgets/NumericTextCtrl.h"
33#if defined(__WXMSW__) && !defined(__CYGWIN__)
35#define finite(x) _finite(x)
39#include <wx/valtext.h>
41#include <wx/wfstream.h>
42#include <wx/txtstrm.h>
43#include <wx/textctrl.h>
49#define DB_MAX_LIMIT 0.0
50#define WCAG2_PASS 20.0
55 float rms = float(0.0);
63 auto numberSelectedTracks = range.
size();
64 if (numberSelectedTracks > 1) {
67 XO(
"You can only measure one track at a time."),
73 if(numberSelectedTracks == 0) {
76 XO(
"Please select an audio track."),
83 const auto first = *range.begin();
84 const auto channels = first->Channels();
87 mT0 = std::max(
mT0, first->GetStartTime());
89 for (
auto t : channels) {
91 auto SelT0 = t->TimeToLongSamples(
mT0);
92 auto SelT1 = t->TimeToLongSamples(
mT1);
98 XO(
"Invalid audio selection.\nPlease ensure that audio is selected."),
109 XO(
"Nothing to measure.\nPlease select a section of a track."),
117 rms = t->GetRMS(
mT0,
mT1,
false);
123 ?
sqrt( meanSq/
static_cast<double>( channels.size() ) )
140 mT0 = selectedRegion.t0();
141 mT1 = selectedRegion.t1();
182 if (event.GetKeyCode() == WXK_TAB) {
195 const wxPoint & pos):
197 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX )
226 S.StartHorizontalLay(wxCENTER,
false);
230 XO(
"Contrast Analyzer, for measuring RMS volume differences between two selections of audio."));
232 S.EndHorizontalLay();
233 S.StartStatic(
XO(
"Parameters") );
235 S.StartMultiColumn(5, wxEXPAND);
239 S.AddFixedText( {} );
240 S.AddFixedText(
XO(
"Start"));
241 S.AddFixedText(
XO(
"End"));
242 S.AddFixedText( {} );
243 S.AddFixedText(
XO(
"Volume "));
246 S.AddFixedText(
XO(
"&Foreground:"),
false);
257 S.Name(
XO(
"Foreground start time"))
270 S.Name(
XO(
"Foreground end time"))
275 .ConnectRoot(wxEVT_KEY_DOWN,
277 .AddTextBox( {},
wxT(
""), 17);
280 S.AddFixedText(
XO(
"&Background:"));
291 S.Name(
XO(
"Background start time"))
304 S.Name(
XO(
"Background end time"))
309 .ConnectRoot(wxEVT_KEY_DOWN,
311 .AddTextBox( {},
wxT(
""), 17);
318 S.StartStatic(
XO(
"Result") );
320 S.StartMultiColumn(3, wxCENTER);
322 auto label =
XO(
"Co&ntrast Result:");
326 .ConnectRoot(wxEVT_KEY_DOWN,
328 .AddTextBox( {},
wxT(
""), 50);
335 .ConnectRoot(wxEVT_KEY_DOWN,
337 .AddTextBox( {},
wxT(
""), 50);
345 S.StartMultiColumn(3, wxEXPAND);
356 SetMinSize(GetSize());
369 wxCommandEvent dummyEvent;
417 auto format0 =
XO(
"RMS = %s.");
420 auto format1 =
XO(
"%s dB");
425 if( fabs( *pValue ) != std::numeric_limits<float>::infinity() ) {
426 auto number = wxString::Format(
wxT(
"%.2f"), *pValue );
427 value = format1.
Format( number );
433 value = format1.
Format(
"" );
435 return format0.
Format( value );
440 if( diffdB != diffdB )
441 return XO(
"indeterminate");
443 if( diffdB != std::numeric_limits<float>::infinity() )
446 return XO(
"%.2f dB RMS").Format( diffdB );
449 return XO(
"Infinite dB difference");
455 if( diffdB != diffdB )
456 return XO(
"Difference is indeterminate.");
458 if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
461 return XO(
"Difference = %.2f RMS dB.").Format( diffdB );
465 return XO(
"Difference = infinite RMS dB.");
485 mPassFailText->ChangeValue(
_(
"Background higher than foreground"));
533 wxString fName =
wxT(
"contrast.txt");
535 fName =
SelectFile(FileNames::Operation::Export,
536 XO(
"Export Contrast Result As:"),
541 wxFD_SAVE | wxRESIZE_BORDER,
547 wxFFileOutputStream ffStream{ fName };
549 if (!ffStream.IsOk()) {
554 wxTextOutputStream ss(ffStream);
557 <<
wxT(
"===================================") <<
'\n'
559 <<
XO(
"WCAG 2.0 Success Criteria 1.4.7 Contrast Results") <<
'\n'
563 <<
XO(
"Foreground") <<
'\n';
566 int h = (int)(t/3600);
567 int m = (int)((t - h*3600)/60);
568 float s = t - h*3600.0 - m*60.0;
571 <<
XO(
"Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
572 .Format( h, m, s ) <<
'\n';
576 m = (int)((t - h*3600)/60);
577 s = t - h*3600.0 - m*60.0;
580 <<
XO(
"Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
581 .Format( h, m, s ) <<
'\n'
584 <<
XO(
"Background") <<
'\n';
588 m = (int)((t - h*3600)/60);
589 s = t - h*3600.0 - m*60.0;
592 <<
XO(
"Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
593 .Format( h, m, s ) <<
'\n';
597 m = (int)((t - h*3600)/60);
598 s = t - h*3600.0 - m*60.0;
601 <<
XO(
"Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
602 .Format( h, m, s ) <<
'\n'
605 <<
XO(
"Results") <<
'\n';
612 ?
XO(
"Success Criteria 1.4.7 of WCAG 2.0: Pass")
613 :
XO(
"Success Criteria 1.4.7 of WCAG 2.0: Fail")) <<
'\n'
615 <<
XO(
"Data gathered") <<
'\n';
617 wxDateTime now = wxDateTime::Now();
618 int year = now.GetYear();
619 wxDateTime::Month month = now.GetMonth();
620 wxString monthName = now.GetMonthName(month);
621 int dom = now.GetDay();
622 int hour = now.GetHour();
623 int minute = now.GetMinute();
624 int second = now.GetSecond();
626 auto sNow =
XO(
"%d %s %02d %02dh %02dm %02ds")
627 .Format( dom, monthName, year, hour, minute, second );
631 <<
wxT(
"===================================") <<
'\n'
664 &window, -1,
XO(
"Contrast Analysis (WCAG 2 compliance)"),
679 contrastDialog->CentreOnParent();
680 contrastDialog->Show();
691 wxT(
"Ctrl+Shift+T") ),
692 wxT(
"Analyze/Analyzers/Windows")
@ Internal
Indicates internal failure from Audacity.
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 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)
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 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)
Generates classes whose instances register items at construction.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
static TrackList & Get(AudacityProject &project)
auto Selected() -> 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.
ExportResult Show(ExportTask exportTask)
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)