15#include "../CommonCommandFlags.h"
21#include "../ProjectWindowBase.h"
28#include "../widgets/NumericTextCtrl.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."),
84 const auto first = *range.begin();
85 const auto channels = first->Channels();
88 mT0 = std::max(
mT0, first->GetStartTime());
90 for (
auto t : channels) {
92 auto SelT0 = t->TimeToLongSamples(
mT0);
93 auto SelT1 = t->TimeToLongSamples(
mT1);
99 XO(
"Invalid audio selection.\nPlease ensure that audio is selected."),
110 XO(
"Nothing to measure.\nPlease select a section of a track."),
124 ?
sqrt( meanSq/
static_cast<double>( channels.size() ) )
141 mT0 = selectedRegion.t0();
142 mT1 = selectedRegion.t1();
183 if (event.GetKeyCode() == WXK_TAB) {
196 const wxPoint & pos):
198 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX )
227 S.StartHorizontalLay(wxCENTER,
false);
231 XO(
"Contrast Analyzer, for measuring RMS volume differences between two selections of audio."));
233 S.EndHorizontalLay();
234 S.StartStatic(
XO(
"Parameters") );
236 S.StartMultiColumn(5, wxEXPAND);
240 S.AddFixedText( {} );
241 S.AddFixedText(
XO(
"Start"));
242 S.AddFixedText(
XO(
"End"));
243 S.AddFixedText( {} );
244 S.AddFixedText(
XO(
"Volume "));
247 S.AddFixedText(
XO(
"&Foreground:"),
false);
258 S.Name(
XO(
"Foreground start time"))
271 S.Name(
XO(
"Foreground end time"))
276 .ConnectRoot(wxEVT_KEY_DOWN,
278 .AddTextBox( {},
wxT(
""), 17);
281 S.AddFixedText(
XO(
"&Background:"));
292 S.Name(
XO(
"Background start time"))
305 S.Name(
XO(
"Background end time"))
310 .ConnectRoot(wxEVT_KEY_DOWN,
312 .AddTextBox( {},
wxT(
""), 17);
319 S.StartStatic(
XO(
"Result") );
321 S.StartMultiColumn(3, wxCENTER);
323 auto label =
XO(
"Co&ntrast Result:");
327 .ConnectRoot(wxEVT_KEY_DOWN,
329 .AddTextBox( {},
wxT(
""), 50);
336 .ConnectRoot(wxEVT_KEY_DOWN,
338 .AddTextBox( {},
wxT(
""), 50);
346 S.StartMultiColumn(3, wxEXPAND);
357 SetMinSize(GetSize());
370 wxCommandEvent dummyEvent;
418 auto format0 =
XO(
"RMS = %s.");
421 auto format1 =
XO(
"%s dB");
426 if( fabs( *pValue ) != std::numeric_limits<float>::infinity() ) {
427 auto number = wxString::Format(
wxT(
"%.2f"), *pValue );
428 value = format1.
Format( number );
434 value = format1.
Format(
"" );
436 return format0.
Format( value );
441 if( diffdB != diffdB )
442 return XO(
"indeterminate");
444 if( diffdB != std::numeric_limits<float>::infinity() )
447 return XO(
"%.2f dB RMS").Format( diffdB );
450 return XO(
"Infinite dB difference");
456 if( diffdB != diffdB )
457 return XO(
"Difference is indeterminate.");
459 if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
462 return XO(
"Difference = %.2f RMS dB.").Format( diffdB );
466 return XO(
"Difference = infinite RMS dB.");
486 mPassFailText->ChangeValue(
_(
"Background higher than foreground"));
534 wxString fName =
wxT(
"contrast.txt");
536 fName =
SelectFile(FileNames::Operation::Export,
537 XO(
"Export Contrast Result As:"),
542 wxFD_SAVE | wxRESIZE_BORDER,
548 wxFFileOutputStream ffStream{ fName };
550 if (!ffStream.IsOk()) {
555 wxTextOutputStream ss(ffStream);
558 <<
wxT(
"===================================") <<
'\n'
560 <<
XO(
"WCAG 2.0 Success Criteria 1.4.7 Contrast Results") <<
'\n'
564 <<
XO(
"Foreground") <<
'\n';
567 int h = (int)(t/3600);
568 int m = (int)((t - h*3600)/60);
569 float s = t - h*3600.0 - m*60.0;
572 <<
XO(
"Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
573 .Format( h, m, s ) <<
'\n';
577 m = (int)((t - h*3600)/60);
578 s = t - h*3600.0 - m*60.0;
581 <<
XO(
"Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
582 .Format( h, m, s ) <<
'\n'
585 <<
XO(
"Background") <<
'\n';
589 m = (int)((t - h*3600)/60);
590 s = t - h*3600.0 - m*60.0;
593 <<
XO(
"Time started = %2d hour(s), %2d minute(s), %.2f seconds.")
594 .Format( h, m, s ) <<
'\n';
598 m = (int)((t - h*3600)/60);
599 s = t - h*3600.0 - m*60.0;
602 <<
XO(
"Time ended = %2d hour(s), %2d minute(s), %.2f seconds.")
603 .Format( h, m, s ) <<
'\n'
606 <<
XO(
"Results") <<
'\n';
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'
616 <<
XO(
"Data gathered") <<
'\n';
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();
627 auto sNow =
XO(
"%d %s %02d %02dh %02dm %02ds")
628 .Format( dom, monthName, year, hour, minute, second );
632 <<
wxT(
"===================================") <<
'\n'
665 &window, -1,
XO(
"Contrast Analysis (WCAG 2 compliance)"),
680 contrastDialog->CentreOnParent();
681 contrastDialog->Show();
692 wxT(
"Ctrl+Shift+T") ),
693 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.
IMPORT_EXPORT_API ExportResult Show(ExportTask exportTask)
WAVE_TRACK_API float GetRMS(const WaveChannel &channel, double t0, double t1, bool mayThrow=true)
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)