From 113edcc70aadf5561f87214decce0955d2db8857 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 13 Jun 2015 23:26:40 -0400 Subject: [PATCH 1/5] SpectrumPrefs takes SpectrogramSettings object as parameter, and... ... writes global preferences explicitly, and only when it is the default settings object. Also impose validation of settings when constructing from preferences. --- src/prefs/SpectrogramSettings.cpp | 193 ++++++++++++++++++++++++------ src/prefs/SpectrogramSettings.h | 23 +++- src/prefs/SpectrumPrefs.cpp | 169 +++++++++++++------------- src/prefs/SpectrumPrefs.h | 15 ++- 4 files changed, 277 insertions(+), 123 deletions(-) diff --git a/src/prefs/SpectrogramSettings.cpp b/src/prefs/SpectrogramSettings.cpp index ceffd4471..d67f1ed41 100644 --- a/src/prefs/SpectrogramSettings.cpp +++ b/src/prefs/SpectrogramSettings.cpp @@ -15,6 +15,10 @@ Paul Licameli #include "../Audacity.h" #include "SpectrogramSettings.h" + +#include +#include + #include "../FFT.h" #include "../Prefs.h" #include "../RealFFTf.h" @@ -26,7 +30,7 @@ SpectrogramSettings::SpectrogramSettings() : hFFT(0) , window(0) { - UpdatePrefs(); + LoadPrefs(); } SpectrogramSettings::SpectrogramSettings(const SpectrogramSettings &other) @@ -98,49 +102,82 @@ SpectrogramSettings& SpectrogramSettings::defaults() return instance; } -void SpectrogramSettings::UpdatePrefs() +bool SpectrogramSettings::Validate(bool quiet) { - bool destroy = false; + if (!quiet && + maxFreq < 100) { + wxMessageBox(_("Maximum frequency must be 100 Hz or above")); + return false; + } + else + maxFreq = std::max(100, maxFreq); + + if (!quiet && + minFreq < 0) { + wxMessageBox(_("Minimum frequency must be at least 0 Hz")); + return false; + } + else + minFreq = std::max(0, minFreq); + + if (!quiet && + maxFreq <= minFreq) { + wxMessageBox(_("Minimum frequency must be less than maximum frequency")); + return false; + } + else + maxFreq = std::max(1 + minFreq, maxFreq); + + if (!quiet && + range <= 0) { + wxMessageBox(_("The range must be at least 1 dB")); + return false; + } + else + range = std::max(1, range); + + if (!quiet && + frequencyGain < 0) { + wxMessageBox(_("The frequency gain cannot be negative")); + return false; + } + else if (!quiet && + frequencyGain > 60) { + wxMessageBox(_("The frequency gain must be no more than 60 dB/dec")); + return false; + } + else + frequencyGain = + std::max(0, std::min(60, frequencyGain)); + + // The rest are controlled by drop-down menus so they can't go wrong + // in the Preferences dialog, but we also come here after reading fom saved + // preference files, which could be or from future versions. Validate quietly. + windowType = + std::max(0, std::min(NumWindowFuncs() - 1, windowType)); + ConvertToEnumeratedWindowSizes(); + ConvertToActualWindowSizes(); + + return true; +} + +void SpectrogramSettings::LoadPrefs() +{ + minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), 0L); - minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), -1L); maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L); - // These preferences are not written anywhere in the program as of now, - // but I keep this legacy here. Who knows, someone might edit prefs files - // directly. PRL - logMaxFreq = gPrefs->Read(wxT("/SpectrumLog/MaxFreq"), -1); - if (logMaxFreq < 0) - logMaxFreq = maxFreq; - logMinFreq = gPrefs->Read(wxT("/SpectrumLog/MinFreq"), -1); - if (logMinFreq < 0) - logMinFreq = minFreq; - if (logMinFreq < 1) - logMinFreq = 1; - range = gPrefs->Read(wxT("/Spectrum/Range"), 80L); gain = gPrefs->Read(wxT("/Spectrum/Gain"), 20L); frequencyGain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L); - const int newWindowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); - if (newWindowSize != windowSize) { - destroy = true; - windowSize = newWindowSize; - } + windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - const int newZeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1); - if (newZeroPaddingFactor != zeroPaddingFactor) { - destroy = true; - zeroPaddingFactor = newZeroPaddingFactor; - } + zeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1); #endif - int newWindowType; - gPrefs->Read(wxT("/Spectrum/WindowType"), &newWindowType, 3); - if (newWindowType != windowType) { - destroy = true; - windowType = newWindowType; - } + gPrefs->Read(wxT("/Spectrum/WindowType"), &windowType, eWinFuncHanning); isGrayscale = (gPrefs->Read(wxT("/Spectrum/Grayscale"), 0L) != 0); @@ -155,8 +192,64 @@ void SpectrogramSettings::UpdatePrefs() findNotesQuantize = (gPrefs->Read(wxT("/Spectrum/FindNotesQuantize"), 0L) != 0); #endif //EXPERIMENTAL_FIND_NOTES - if (destroy) - DestroyWindows(); + // Enforce legal values + Validate(true); + + // These preferences are not written anywhere in the program as of now, + // but I keep this legacy here. Who knows, someone might edit prefs files + // directly. PRL + logMinFreq = gPrefs->Read(wxT("/SpectrumLog/MinFreq"), -1); + if (logMinFreq < 0) + logMinFreq = minFreq; + if (logMinFreq < 1) + logMinFreq = 1; + logMaxFreq = gPrefs->Read(wxT("/SpectrumLog/MaxFreq"), -1); + if (logMaxFreq < 0) + logMaxFreq = maxFreq; + logMaxFreq = + std::max(logMinFreq + 1, logMaxFreq); + + InvalidateCaches(); +} + +void SpectrogramSettings::SavePrefs() +{ + gPrefs->Write(wxT("/Spectrum/MinFreq"), minFreq); + gPrefs->Write(wxT("/Spectrum/MaxFreq"), maxFreq); + + // Nothing wrote these. They only varied from the linear scale bounds in-session. -- PRL + // gPrefs->Write(wxT("/SpectrumLog/MaxFreq"), logMinFreq); + // gPrefs->Write(wxT("/SpectrumLog/MinFreq"), logMaxFreq); + + gPrefs->Write(wxT("/Spectrum/Range"), range); + gPrefs->Write(wxT("/Spectrum/Gain"), gain); + gPrefs->Write(wxT("/Spectrum/FrequencyGain"), frequencyGain); + + gPrefs->Write(wxT("/Spectrum/FFTSize"), windowSize); + +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + gPrefs->Write(wxT("/Spectrum/ZeroPaddingFactor"), zeroPaddingFactor); +#endif + + gPrefs->Write(wxT("/Spectrum/WindowType"), windowType); + + gPrefs->Write(wxT("/Spectrum/Grayscale"), isGrayscale); + +#ifdef EXPERIMENTAL_FFT_Y_GRID + gPrefs->Write(wxT("/Spectrum/FFTYGrid"), fftYGrid); +#endif //EXPERIMENTAL_FFT_Y_GRID + +#ifdef EXPERIMENTAL_FIND_NOTES + gPrefs->Write(wxT("/Spectrum/FFTFindNotes"), fftFindNotes); + gPrefs->Write(wxT("/Spectrum/FindNotesMinA"), findNotesMinA); + gPrefs->Write(wxT("/Spectrum/FindNotesN"), numberOfMaxima); + gPrefs->Write(wxT("/Spectrum/FindNotesQuantize"), findNotesQuantize); +#endif //EXPERIMENTAL_FIND_NOTES +} + +void SpectrogramSettings::InvalidateCaches() +{ + DestroyWindows(); } SpectrogramSettings::~SpectrogramSettings() @@ -257,6 +350,38 @@ void SpectrogramSettings::CacheWindows() const #endif // EXPERIMENTAL_USE_REALFFTF } +void SpectrogramSettings::ConvertToEnumeratedWindowSizes() +{ + unsigned size; + int logarithm; + + logarithm = -LogMinWindowSize; + size = unsigned(windowSize); + while (size > 1) + size >>= 1, ++logarithm; + windowSize = std::max(0, std::min(NumWindowSizes - 1, logarithm)); + +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + // Choices for zero padding begin at 1 + logarithm = 0; + size = unsigned(zeroPaddingFactor); + while (zeroPaddingFactor > 1) + zeroPaddingFactor >>= 1, ++logarithm; + zeroPaddingFactor = std::max(0, + std::min(LogMaxWindowSize - (windowSize + LogMinWindowSize), + logarithm + )); +#endif +} + +void SpectrogramSettings::ConvertToActualWindowSizes() +{ + windowSize = 1 << (windowSize + LogMinWindowSize); +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + zeroPaddingFactor = 1 << zeroPaddingFactor; +#endif +} + int SpectrogramSettings::GetMinFreq(double rate) const { const int top = lrint(rate / 2.); diff --git a/src/prefs/SpectrogramSettings.h b/src/prefs/SpectrogramSettings.h index 3d13aa528..f67e47b70 100644 --- a/src/prefs/SpectrogramSettings.h +++ b/src/prefs/SpectrogramSettings.h @@ -14,19 +14,39 @@ Paul Licameli #include "../Experimental.h" struct FFTParam; +class SpectrumPrefs; class SpectrogramSettings { + friend class SpectrumPrefs; public: + + enum { + LogMinWindowSize = 3, + LogMaxWindowSize = 15, + + NumWindowSizes = LogMaxWindowSize - LogMinWindowSize + 1, + }; + static SpectrogramSettings &defaults(); SpectrogramSettings(); SpectrogramSettings(const SpectrogramSettings &other); SpectrogramSettings& operator= (const SpectrogramSettings &other); ~SpectrogramSettings(); - void UpdatePrefs(); + bool IsDefault() const + { + return this == &defaults(); + } + + bool Validate(bool quiet); + void LoadPrefs(); + void SavePrefs(); + void InvalidateCaches(); void DestroyWindows(); void CacheWindows() const; + void ConvertToEnumeratedWindowSizes(); + void ConvertToActualWindowSizes(); private: int minFreq; @@ -78,4 +98,5 @@ public: mutable float *window; #endif }; + #endif diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index 766a43747..6cee1e767 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -21,26 +21,30 @@ #include #include -#include "../Prefs.h" +#include "../FFT.h" #include "../Project.h" #include "../ShuttleGui.h" -#include "../FFT.h" +#include "../WaveTrack.h" #include -SpectrumPrefs::SpectrumPrefs(wxWindow * parent) +SpectrumPrefs::SpectrumPrefs(wxWindow * parent, WaveTrack *wt) : PrefsPanel(parent, _("Spectrograms")) +, mWt(wt) { - int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); - Populate(windowSize); + SpectrogramSettings *const pSettings = mWt + ? &mWt->GetIndependentSpectrogramSettings() + : &SpectrogramSettings::defaults(); + + mTempSettings = *pSettings; + mTempSettings.ConvertToEnumeratedWindowSizes(); + Populate(pSettings->windowSize); } SpectrumPrefs::~SpectrumPrefs() { } -enum { maxWindowSize = 32768 }; - enum { ID_WINDOW_SIZE = 10001, #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS @@ -63,26 +67,18 @@ void SpectrumPrefs::Populate(int windowSize) mSizeChoices.Add(wxT("8192")); mSizeChoices.Add(wxT("16384")); mSizeChoices.Add(_("32768 - most narrowband")); - - int lastCode = 0; - for (size_t i = 0; i < mSizeChoices.GetCount(); i++) { - mSizeCodes.Add(lastCode = 1 << (i + 3)); - } - wxASSERT(lastCode == maxWindowSize); + wxASSERT(mSizeChoices.size() == SpectrogramSettings::NumWindowSizes); PopulatePaddingChoices(windowSize); for (int i = 0; i < NumWindowFuncs(); i++) { mTypeChoices.Add(WindowFuncName(i)); - mTypeCodes.Add(i); } //------------------------- Main section -------------------- // Now construct the GUI itself. - // Use 'eIsCreatingFromPrefs' so that the GUI is - // initialised with values from gPrefs. - ShuttleGui S(this, eIsCreatingFromPrefs); + ShuttleGui S(this, eIsCreating); PopulateOrExchange(S); // ----------------------- End of main section -------------- } @@ -107,14 +103,12 @@ void SpectrumPrefs::PopulatePaddingChoices(int windowSize) pPaddingSizeControl->Clear(); } - mZeroPaddingCodes.Clear(); - int padding = 1; int numChoices = 0; + const int maxWindowSize = 1 << (SpectrogramSettings::LogMaxWindowSize); while (windowSize <= maxWindowSize) { const wxString numeral = wxString::Format(wxT("%d"), padding); mZeroPaddingChoices.Add(numeral); - mZeroPaddingCodes.Add(padding); if (pPaddingSizeControl) pPaddingSizeControl->Append(numeral); windowSize <<= 1; @@ -138,25 +132,19 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) S.StartMultiColumn(2); { S.Id(ID_WINDOW_SIZE).TieChoice(_("Window &size:"), - wxT("/Spectrum/FFTSize"), - 256, - mSizeChoices, - mSizeCodes); + mTempSettings.windowSize, + &mSizeChoices); S.SetSizeHints(mSizeChoices); S.TieChoice(_("Window &type:"), - wxT("/Spectrum/WindowType"), - 3, - mTypeChoices, - mTypeCodes); + mTempSettings.windowType, + &mTypeChoices); S.SetSizeHints(mTypeChoices); #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS S.Id(ID_PADDING_SIZE).TieChoice(_("&Zero padding factor") + wxString(wxT(":")), - wxT("/Spectrum/ZeroPaddingFactor"), - mZeroPaddingChoice, - mZeroPaddingChoices, - mZeroPaddingCodes); + mTempSettings.zeroPaddingFactor, + &mZeroPaddingChoices); S.SetSizeHints(mZeroPaddingChoices); #endif } @@ -170,44 +158,37 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) { mMinFreq = S.TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), - wxT("/Spectrum/MinFreq"), - 0, + mTempSettings.minFreq, 12); mMaxFreq = S.TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), - wxT("/Spectrum/MaxFreq"), - 8000, + mTempSettings.maxFreq, 12); mGain = S.TieNumericTextBox(_("&Gain (dB):"), - wxT("/Spectrum/Gain"), - 20, + mTempSettings.gain, 8); mRange = S.TieNumericTextBox(_("&Range (dB):"), - wxT("/Spectrum/Range"), - 80, + mTempSettings.range, 8); mFrequencyGain = S.TieNumericTextBox(_("Frequency g&ain (dB/dec):"), - wxT("/Spectrum/FrequencyGain"), - 0, + mTempSettings.frequencyGain, 4); } S.EndTwoColumn(); S.TieCheckBox(_("S&how the spectrum using grayscale colors"), - wxT("/Spectrum/Grayscale"), - false); + mTempSettings.isGrayscale); #ifdef EXPERIMENTAL_FFT_Y_GRID S.TieCheckBox(_("Show a grid along the &Y-axis"), - wxT("/Spectrum/FFTYGrid"), - false); + mTempSettings.fftYGrid); #endif //EXPERIMENTAL_FFT_Y_GRID } S.EndStatic(); @@ -220,25 +201,21 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) { mFindNotesMinA = S.TieNumericTextBox(_("Minimum Amplitude (dB):"), - wxT("/Spectrum/FindNotesMinA"), - -30L, + mTempSettings.fftFindNotes, 8); mFindNotesN = S.TieNumericTextBox(_("Max. Number of Notes (1..128):"), - wxT("/Spectrum/FindNotesN"), - 5L, + mTempSettings.findNotesMinA, 8); } S.EndTwoColumn(); S.TieCheckBox(_("&Find Notes"), - wxT("/Spectrum/FFTFindNotes"), - false); + mTempSettings.numberOfMaxima); S.TieCheckBox(_("&Quantize Notes"), - wxT("/Spectrum/FindNotesQuantize"), - false); + mTempSettings.findNotesQuantize); } S.EndStatic(); #endif //EXPERIMENTAL_FIND_NOTES @@ -246,59 +223,40 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) bool SpectrumPrefs::Validate() { + // Do checking for whole numbers + + // ToDo: use wxIntegerValidator when available + long maxFreq; if (!mMaxFreq->GetValue().ToLong(&maxFreq)) { wxMessageBox(_("The maximum frequency must be an integer")); return false; } - if (maxFreq < 100) { - wxMessageBox(_("Maximum frequency must be 100 Hz or above")); - return false; - } long minFreq; if (!mMinFreq->GetValue().ToLong(&minFreq)) { wxMessageBox(_("The minimum frequency must be an integer")); return false; } - if (minFreq < 0) { - wxMessageBox(_("Minimum frequency must be at least 0 Hz")); - return false; - } - - if (maxFreq < minFreq) { - wxMessageBox(_("Minimum frequency must be less than maximum frequency")); - return false; - } long gain; if (!mGain->GetValue().ToLong(&gain)) { wxMessageBox(_("The gain must be an integer")); return false; } + long range; if (!mRange->GetValue().ToLong(&range)) { wxMessageBox(_("The range must be a positive integer")); return false; } - if (range <= 0) { - wxMessageBox(_("The range must be at least 1 dB")); - return false; - } long frequencygain; if (!mFrequencyGain->GetValue().ToLong(&frequencygain)) { wxMessageBox(_("The frequency gain must be an integer")); return false; } - if (frequencygain < 0) { - wxMessageBox(_("The frequency gain cannot be negative")); - return false; - } - if (frequencygain > 60) { - wxMessageBox(_("The frequency gain must be no more than 60 dB/dec")); - return false; - } + #ifdef EXPERIMENTAL_FIND_NOTES long findNotesMinA; if (!mFindNotesMinA->GetValue().ToLong(&findNotesMinA)) { @@ -317,15 +275,52 @@ bool SpectrumPrefs::Validate() } #endif //EXPERIMENTAL_FIND_NOTES - return true; + ShuttleGui S(this, eIsGettingFromDialog); + PopulateOrExchange(S); + + // Delegate range checking to SpectrogramSettings class + mTempSettings.ConvertToActualWindowSizes(); + const bool result = mTempSettings.Validate(false); + mTempSettings.ConvertToEnumeratedWindowSizes(); + return result; } bool SpectrumPrefs::Apply() { - ShuttleGui S(this, eIsSavingToPrefs); + const bool isOpenPage = this->IsShown(); + + WaveTrack *const partner = + mWt ? static_cast(mWt->GetLink()) : 0; + + ShuttleGui S(this, eIsGettingFromDialog); PopulateOrExchange(S); - SpectrogramSettings::defaults().UpdatePrefs(); + mTempSettings.ConvertToActualWindowSizes(); + if (mWt) { + SpectrogramSettings *pSettings = + &mWt->GetIndependentSpectrogramSettings(); + *pSettings = mTempSettings; + if (partner) { + pSettings = &partner->GetIndependentSpectrogramSettings(); + *pSettings = mTempSettings; + } + } + else { + SpectrogramSettings *const pSettings = + &SpectrogramSettings::defaults(); + *pSettings = mTempSettings; + pSettings->SavePrefs(); + } + mTempSettings.ConvertToEnumeratedWindowSizes(); + + if (mWt && isOpenPage) { + // Future: open page will determine the track view type + /* + mWt->SetDisplay(WaveTrack::Spectrum); + if (partner) + partner->SetDisplay(WaveTrack::Spectrum); + */ + } return true; } @@ -334,7 +329,8 @@ void SpectrumPrefs::OnWindowSize(wxCommandEvent &) { wxChoice *const pWindowSizeControl = static_cast(wxWindow::FindWindowById(ID_WINDOW_SIZE, this)); - int windowSize = 1 << (pWindowSizeControl->GetSelection() + 3); + int windowSize = 1 << + (pWindowSizeControl->GetSelection() + SpectrogramSettings::LogMinWindowSize); PopulatePaddingChoices(windowSize); } @@ -342,7 +338,12 @@ BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) EVT_CHOICE(ID_WINDOW_SIZE, SpectrumPrefs::OnWindowSize) END_EVENT_TABLE() +SpectrumPrefsFactory::SpectrumPrefsFactory(WaveTrack *wt) +: mWt(wt) +{ +} + PrefsPanel *SpectrumPrefsFactory::Create(wxWindow *parent) { - return new SpectrumPrefs(parent); + return new SpectrumPrefs(parent, mWt); } diff --git a/src/prefs/SpectrumPrefs.h b/src/prefs/SpectrumPrefs.h index 8e316f36a..07f60cdae 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -33,11 +33,13 @@ class wxTextCtrl; struct FFTParam; class ShuttleGui; +class SpectrogramSettings; +class WaveTrack; class SpectrumPrefs:public PrefsPanel { public: - SpectrumPrefs(wxWindow * parent); + SpectrumPrefs(wxWindow * parent, WaveTrack *wt); virtual ~SpectrumPrefs(); virtual bool Apply(); virtual bool Validate(); @@ -50,6 +52,8 @@ class SpectrumPrefs:public PrefsPanel void OnWindowSize(wxCommandEvent &event); DECLARE_EVENT_TABLE() + WaveTrack *const mWt; + wxTextCtrl *mMinFreq; wxTextCtrl *mMaxFreq; wxTextCtrl *mGain; @@ -57,28 +61,31 @@ class SpectrumPrefs:public PrefsPanel wxTextCtrl *mFrequencyGain; wxArrayString mSizeChoices; - wxArrayInt mSizeCodes; #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS int mZeroPaddingChoice; wxArrayString mZeroPaddingChoices; - wxArrayInt mZeroPaddingCodes; #endif wxArrayString mTypeChoices; - wxArrayInt mTypeCodes; #ifdef EXPERIMENTAL_FIND_NOTES wxTextCtrl *mFindNotesMinA; wxTextCtrl *mFindNotesN; #endif + + SpectrogramSettings mTempSettings; }; class SpectrumPrefsFactory : public PrefsPanelFactory { public: + explicit SpectrumPrefsFactory(WaveTrack *wt = 0); virtual PrefsPanel *Create(wxWindow *parent); + +private: + WaveTrack *const mWt; }; #endif From 298bc981bf5f6fa4faab2059976ee0c1370b337b Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 14 Jun 2015 16:20:15 -0400 Subject: [PATCH 2/5] Future static text box distinguishing track settings from globals? ... ... Leave this idea just commented out for now. --- src/prefs/SpectrumPrefs.cpp | 142 ++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 69 deletions(-) diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index 6cee1e767..e0b005cbf 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -127,98 +127,102 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) { S.SetBorder(2); - S.StartStatic(_("FFT Window")); + // S.StartStatic(_("Track Settings")); { - S.StartMultiColumn(2); + S.StartStatic(_("FFT Window")); { - S.Id(ID_WINDOW_SIZE).TieChoice(_("Window &size:"), - mTempSettings.windowSize, - &mSizeChoices); - S.SetSizeHints(mSizeChoices); + S.StartMultiColumn(2); + { + S.Id(ID_WINDOW_SIZE).TieChoice(_("Window &size:"), + mTempSettings.windowSize, + &mSizeChoices); + S.SetSizeHints(mSizeChoices); - S.TieChoice(_("Window &type:"), - mTempSettings.windowType, - &mTypeChoices); - S.SetSizeHints(mTypeChoices); + S.TieChoice(_("Window &type:"), + mTempSettings.windowType, + &mTypeChoices); + S.SetSizeHints(mTypeChoices); #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - S.Id(ID_PADDING_SIZE).TieChoice(_("&Zero padding factor") + wxString(wxT(":")), - mTempSettings.zeroPaddingFactor, - &mZeroPaddingChoices); - S.SetSizeHints(mZeroPaddingChoices); + S.Id(ID_PADDING_SIZE).TieChoice(_("&Zero padding factor") + wxString(wxT(":")), + mTempSettings.zeroPaddingFactor, + &mZeroPaddingChoices); + S.SetSizeHints(mZeroPaddingChoices); #endif + } + S.EndMultiColumn(); } - S.EndMultiColumn(); - } - S.EndStatic(); + S.EndStatic(); - S.StartStatic(_("Display")); - { - S.StartTwoColumn(); + S.StartStatic(_("Display")); { - mMinFreq = - S.TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), - mTempSettings.minFreq, - 12); + S.StartTwoColumn(); + { + mMinFreq = + S.TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), + mTempSettings.minFreq, + 12); - mMaxFreq = - S.TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), - mTempSettings.maxFreq, - 12); + mMaxFreq = + S.TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), + mTempSettings.maxFreq, + 12); - mGain = - S.TieNumericTextBox(_("&Gain (dB):"), - mTempSettings.gain, - 8); + mGain = + S.TieNumericTextBox(_("&Gain (dB):"), + mTempSettings.gain, + 8); - mRange = - S.TieNumericTextBox(_("&Range (dB):"), - mTempSettings.range, - 8); + mRange = + S.TieNumericTextBox(_("&Range (dB):"), + mTempSettings.range, + 8); - mFrequencyGain = - S.TieNumericTextBox(_("Frequency g&ain (dB/dec):"), - mTempSettings.frequencyGain, - 4); - } - S.EndTwoColumn(); + mFrequencyGain = + S.TieNumericTextBox(_("Frequency g&ain (dB/dec):"), + mTempSettings.frequencyGain, + 4); + } + S.EndTwoColumn(); - S.TieCheckBox(_("S&how the spectrum using grayscale colors"), - mTempSettings.isGrayscale); + S.TieCheckBox(_("S&how the spectrum using grayscale colors"), + mTempSettings.isGrayscale); #ifdef EXPERIMENTAL_FFT_Y_GRID - S.TieCheckBox(_("Show a grid along the &Y-axis"), - mTempSettings.fftYGrid); + S.TieCheckBox(_("Show a grid along the &Y-axis"), + mTempSettings.fftYGrid); #endif //EXPERIMENTAL_FFT_Y_GRID - } - S.EndStatic(); + } + S.EndStatic(); #ifdef EXPERIMENTAL_FIND_NOTES - /* i18n-hint: FFT stands for Fast Fourier Transform and probably shouldn't be translated*/ - S.StartStatic(_("FFT Find Notes")); - { - S.StartTwoColumn(); + /* i18n-hint: FFT stands for Fast Fourier Transform and probably shouldn't be translated*/ + S.StartStatic(_("FFT Find Notes")); { - mFindNotesMinA = - S.TieNumericTextBox(_("Minimum Amplitude (dB):"), - mTempSettings.fftFindNotes, - 8); + S.StartTwoColumn(); + { + mFindNotesMinA = + S.TieNumericTextBox(_("Minimum Amplitude (dB):"), + mTempSettings.fftFindNotes, + 8); - mFindNotesN = - S.TieNumericTextBox(_("Max. Number of Notes (1..128):"), - mTempSettings.findNotesMinA, - 8); + mFindNotesN = + S.TieNumericTextBox(_("Max. Number of Notes (1..128):"), + mTempSettings.findNotesMinA, + 8); + } + S.EndTwoColumn(); + + S.TieCheckBox(_("&Find Notes"), + mTempSettings.numberOfMaxima); + + S.TieCheckBox(_("&Quantize Notes"), + mTempSettings.findNotesQuantize); } - S.EndTwoColumn(); - - S.TieCheckBox(_("&Find Notes"), - mTempSettings.numberOfMaxima); - - S.TieCheckBox(_("&Quantize Notes"), - mTempSettings.findNotesQuantize); - } - S.EndStatic(); + S.EndStatic(); #endif //EXPERIMENTAL_FIND_NOTES + } + // S.EndStatic(); } bool SpectrumPrefs::Validate() From e8e3b8bec5d945238b8cf755e58566107fa33a2b Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 15 Jun 2015 13:54:34 -0400 Subject: [PATCH 3/5] Checkbox for defaulting track spectrogram settings (not seen in Preferences) --- src/prefs/SpectrumPrefs.cpp | 115 +++++++++++++++++++++++++++++------- src/prefs/SpectrumPrefs.h | 9 +++ 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index e0b005cbf..1f96fd0dc 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "../FFT.h" #include "../Project.h" @@ -31,14 +32,21 @@ SpectrumPrefs::SpectrumPrefs(wxWindow * parent, WaveTrack *wt) : PrefsPanel(parent, _("Spectrograms")) , mWt(wt) +, mPopulating(false) { - SpectrogramSettings *const pSettings = mWt - ? &mWt->GetIndependentSpectrogramSettings() - : &SpectrogramSettings::defaults(); + if (mWt) { + SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + mDefaulted = (&SpectrogramSettings::defaults() == &settings); + mTempSettings = settings; + } + else { + mTempSettings = SpectrogramSettings::defaults(); + mDefaulted = false; + } - mTempSettings = *pSettings; + const int windowSize = mTempSettings.windowSize; mTempSettings.ConvertToEnumeratedWindowSizes(); - Populate(pSettings->windowSize); + Populate(windowSize); } SpectrumPrefs::~SpectrumPrefs() @@ -48,8 +56,16 @@ SpectrumPrefs::~SpectrumPrefs() enum { ID_WINDOW_SIZE = 10001, #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - ID_PADDING_SIZE = 10002, + ID_WINDOW_TYPE, + ID_PADDING_SIZE, + ID_MINIMUM, + ID_MAXIMUM, + ID_GAIN, + ID_RANGE, + ID_FREQUENCY_GAIN, + ID_GRAYSCALE, #endif + ID_DEFAULTS, }; void SpectrumPrefs::Populate(int windowSize) @@ -125,10 +141,16 @@ void SpectrumPrefs::PopulatePaddingChoices(int windowSize) void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) { + mPopulating = true; + S.SetBorder(2); // S.StartStatic(_("Track Settings")); { + mDefaultsCheckbox = 0; + if (mWt) { + mDefaultsCheckbox = S.Id(ID_DEFAULTS).TieCheckBox(_("Defaults"), mDefaulted); + } S.StartStatic(_("FFT Window")); { S.StartMultiColumn(2); @@ -138,7 +160,7 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) &mSizeChoices); S.SetSizeHints(mSizeChoices); - S.TieChoice(_("Window &type:"), + S.Id(ID_WINDOW_TYPE).TieChoice(_("Window &type:"), mTempSettings.windowType, &mTypeChoices); S.SetSizeHints(mTypeChoices); @@ -159,33 +181,33 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) S.StartTwoColumn(); { mMinFreq = - S.TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), + S.Id(ID_MINIMUM).TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), mTempSettings.minFreq, 12); mMaxFreq = - S.TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), + S.Id(ID_MAXIMUM).TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), mTempSettings.maxFreq, 12); mGain = - S.TieNumericTextBox(_("&Gain (dB):"), + S.Id(ID_GAIN).TieNumericTextBox(_("&Gain (dB):"), mTempSettings.gain, 8); mRange = - S.TieNumericTextBox(_("&Range (dB):"), + S.Id(ID_RANGE).TieNumericTextBox(_("&Range (dB):"), mTempSettings.range, 8); mFrequencyGain = - S.TieNumericTextBox(_("Frequency g&ain (dB/dec):"), + S.Id(ID_FREQUENCY_GAIN).TieNumericTextBox(_("Frequency g&ain (dB/dec):"), mTempSettings.frequencyGain, 4); } S.EndTwoColumn(); - S.TieCheckBox(_("S&how the spectrum using grayscale colors"), + S.Id(ID_GRAYSCALE).TieCheckBox(_("S&how the spectrum using grayscale colors"), mTempSettings.isGrayscale); #ifdef EXPERIMENTAL_FFT_Y_GRID @@ -223,6 +245,8 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) #endif //EXPERIMENTAL_FIND_NOTES } // S.EndStatic(); + + mPopulating = false; } bool SpectrumPrefs::Validate() @@ -301,17 +325,24 @@ bool SpectrumPrefs::Apply() mTempSettings.ConvertToActualWindowSizes(); if (mWt) { - SpectrogramSettings *pSettings = - &mWt->GetIndependentSpectrogramSettings(); - *pSettings = mTempSettings; - if (partner) { - pSettings = &partner->GetIndependentSpectrogramSettings(); + if (mDefaulted) { + mWt->SetSpectrogramSettings(NULL); + if (partner) + partner->SetSpectrogramSettings(NULL); + } + else { + SpectrogramSettings *pSettings = + &mWt->GetIndependentSpectrogramSettings(); *pSettings = mTempSettings; + if (partner) { + pSettings = &partner->GetIndependentSpectrogramSettings(); + *pSettings = mTempSettings; + } } } - else { - SpectrogramSettings *const pSettings = - &SpectrogramSettings::defaults(); + + if (!mWt || mDefaulted) { + SpectrogramSettings *const pSettings = &SpectrogramSettings::defaults(); *pSettings = mTempSettings; pSettings->SavePrefs(); } @@ -329,17 +360,57 @@ bool SpectrumPrefs::Apply() return true; } -void SpectrumPrefs::OnWindowSize(wxCommandEvent &) +void SpectrumPrefs::OnControl(wxCommandEvent&) { + // Common routine for most controls + // If any per-track setting is changed, break the association with defaults + // Skip this, and View Settings... will be able to change defaults instead + // when the checkbox is on, as in the original design. + + if (mDefaultsCheckbox && !mPopulating) { + mDefaulted = false; + mDefaultsCheckbox->SetValue(false); + } +} + +void SpectrumPrefs::OnWindowSize(wxCommandEvent &evt) +{ + // Restrict choice of zero padding, so that product of window + // size and padding may not exceed the largest window size. wxChoice *const pWindowSizeControl = static_cast(wxWindow::FindWindowById(ID_WINDOW_SIZE, this)); int windowSize = 1 << (pWindowSizeControl->GetSelection() + SpectrogramSettings::LogMinWindowSize); PopulatePaddingChoices(windowSize); + + // Do the common part + OnControl(evt); +} + +void SpectrumPrefs::OnDefaults(wxCommandEvent &) +{ + if (mDefaultsCheckbox->IsChecked()) { + mTempSettings = SpectrogramSettings::defaults(); + mTempSettings.ConvertToEnumeratedWindowSizes(); + mDefaulted = true; + ShuttleGui S(this, eIsSettingToDialog); + PopulateOrExchange(S); + } } BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) EVT_CHOICE(ID_WINDOW_SIZE, SpectrumPrefs::OnWindowSize) + EVT_CHECKBOX(ID_DEFAULTS, SpectrumPrefs::OnDefaults) + + // Several controls with common routine that unchecks the default box + EVT_CHOICE(ID_WINDOW_TYPE, SpectrumPrefs::OnControl) + EVT_CHOICE(ID_PADDING_SIZE, SpectrumPrefs::OnControl) + EVT_TEXT(ID_MINIMUM, SpectrumPrefs::OnControl) + EVT_TEXT(ID_MAXIMUM, SpectrumPrefs::OnControl) + EVT_TEXT(ID_GAIN, SpectrumPrefs::OnControl) + EVT_TEXT(ID_RANGE, SpectrumPrefs::OnControl) + EVT_TEXT(ID_FREQUENCY_GAIN, SpectrumPrefs::OnControl) + EVT_CHECKBOX(ID_GRAYSCALE, SpectrumPrefs::OnControl) END_EVENT_TABLE() SpectrumPrefsFactory::SpectrumPrefsFactory(WaveTrack *wt) diff --git a/src/prefs/SpectrumPrefs.h b/src/prefs/SpectrumPrefs.h index 07f60cdae..b6e8b8a23 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -30,6 +30,8 @@ #include "PrefsPanel.h" #include "SpectrogramSettings.h" +class wxChoice; +class wxCheckBox; class wxTextCtrl; struct FFTParam; class ShuttleGui; @@ -49,10 +51,13 @@ class SpectrumPrefs:public PrefsPanel void PopulatePaddingChoices(int windowSize); void PopulateOrExchange(ShuttleGui & S); + void OnControl(wxCommandEvent &event); void OnWindowSize(wxCommandEvent &event); + void OnDefaults(wxCommandEvent&); DECLARE_EVENT_TABLE() WaveTrack *const mWt; + bool mDefaulted; wxTextCtrl *mMinFreq; wxTextCtrl *mMaxFreq; @@ -75,7 +80,11 @@ class SpectrumPrefs:public PrefsPanel wxTextCtrl *mFindNotesN; #endif + wxCheckBox *mDefaultsCheckbox; + SpectrogramSettings mTempSettings; + + bool mPopulating; }; class SpectrumPrefsFactory : public PrefsPanelFactory From e6be4f5777328aadd6f716e0b6122a3c6f68ff62 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Tue, 16 Jun 2015 12:03:29 -0400 Subject: [PATCH 4/5] Apply button for Spectrograms Preferences and View Settings --- src/prefs/SpectrumPrefs.cpp | 18 ++++++++++++++++++ src/prefs/SpectrumPrefs.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index 1f96fd0dc..c63847909 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -26,6 +26,7 @@ #include "../Project.h" #include "../ShuttleGui.h" #include "../WaveTrack.h" +#include "../TrackPanel.h" #include @@ -66,6 +67,7 @@ enum { ID_GRAYSCALE, #endif ID_DEFAULTS, + ID_APPLY, }; void SpectrumPrefs::Populate(int windowSize) @@ -246,6 +248,12 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) } // S.EndStatic(); + S.StartMultiColumn(2, wxALIGN_RIGHT); + { + S.Id(ID_APPLY).AddButton(_("Appl&y")); + } + S.EndMultiColumn(); + mPopulating = false; } @@ -398,6 +406,14 @@ void SpectrumPrefs::OnDefaults(wxCommandEvent &) } } +void SpectrumPrefs::OnApply(wxCommandEvent &) +{ + if (Validate()) { + Apply(); + ::GetActiveProject()->GetTrackPanel()->Refresh(false); + } +} + BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) EVT_CHOICE(ID_WINDOW_SIZE, SpectrumPrefs::OnWindowSize) EVT_CHECKBOX(ID_DEFAULTS, SpectrumPrefs::OnDefaults) @@ -411,6 +427,8 @@ BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) EVT_TEXT(ID_RANGE, SpectrumPrefs::OnControl) EVT_TEXT(ID_FREQUENCY_GAIN, SpectrumPrefs::OnControl) EVT_CHECKBOX(ID_GRAYSCALE, SpectrumPrefs::OnControl) + + EVT_BUTTON(ID_APPLY, SpectrumPrefs::OnApply) END_EVENT_TABLE() SpectrumPrefsFactory::SpectrumPrefsFactory(WaveTrack *wt) diff --git a/src/prefs/SpectrumPrefs.h b/src/prefs/SpectrumPrefs.h index b6e8b8a23..dc07c7115 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -54,6 +54,7 @@ class SpectrumPrefs:public PrefsPanel void OnControl(wxCommandEvent &event); void OnWindowSize(wxCommandEvent &event); void OnDefaults(wxCommandEvent&); + void OnApply(wxCommandEvent &); DECLARE_EVENT_TABLE() WaveTrack *const mWt; From 1f6f43bba7b2dc5b78cd610c07058dca068375c0 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 13 Jun 2015 23:27:17 -0400 Subject: [PATCH 5/5] Track control "View Settings..." makes alternative SpectrumPrefs accessible --- src/TrackPanel.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- src/TrackPanel.h | 1 + 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 066c2702c..32f4fabb9 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -217,7 +217,8 @@ is time to refresh some aspect of the screen. #include "ondemand/ODManager.h" -#include "prefs/SpectrogramSettings.h" +#include "prefs/PrefsDialog.h" +#include "prefs/SpectrumPrefs.h" #include "toolbars/ControlToolBar.h" #include "toolbars/ToolManager.h" @@ -330,6 +331,7 @@ enum { OnSpectralSelID, OnSpectralSelLogID, OnPitchID, + OnViewSettingsID, OnSplitStereoID, OnSplitStereoMonoID, @@ -369,6 +371,7 @@ BEGIN_EVENT_TABLE(TrackPanel, wxWindow) EVT_MENU_RANGE(OnChannelLeftID, OnChannelMonoID, TrackPanel::OnChannelChange) EVT_MENU_RANGE(OnWaveformID, OnPitchID, TrackPanel::OnSetDisplay) + EVT_MENU(OnViewSettingsID, TrackPanel::OnViewSettings) EVT_MENU_RANGE(OnRate8ID, OnRate384ID, TrackPanel::OnRateChange) EVT_MENU_RANGE(On16BitID, OnFloatID, TrackPanel::OnFormatChange) EVT_MENU(OnRateOtherID, TrackPanel::OnRateOther) @@ -731,9 +734,10 @@ void TrackPanel::BuildMenus(void) mWaveTrackMenu->Append(OnSpectralSelID, _("S&pectral Selection")); /* i18n-hint: short form of 'logarithm'*/ mWaveTrackMenu->Append(OnSpectralSelLogID, _("Spectral Selection lo&g(f)")); - mWaveTrackMenu->Append(OnPitchID, _("Pitc&h (EAC)")); + mWaveTrackMenu->Append(OnViewSettingsID, _("View& Settings...")); // PRL: all the other letters already taken for accelerators! mWaveTrackMenu->AppendSeparator(); + mWaveTrackMenu->AppendRadioItem(OnChannelMonoID, _("&Mono")); mWaveTrackMenu->AppendRadioItem(OnChannelLeftID, _("&Left Channel")); mWaveTrackMenu->AppendRadioItem(OnChannelRightID, _("&Right Channel")); @@ -8569,6 +8573,7 @@ void TrackPanel::OnTrackMenu(Track *t) theMenu->Enable(OnSpectralSelID, display != WaveTrack::SpectralSelectionDisplay); theMenu->Enable(OnSpectralSelLogID, display != WaveTrack::SpectralSelectionLogDisplay); theMenu->Enable(OnPitchID, display != WaveTrack::PitchDisplay); + theMenu->Enable(OnViewSettingsID, true); WaveTrack * track = (WaveTrack *)t; SetMenuCheck(*mRateMenu, IdOfRate((int) track->GetRate())); @@ -9030,6 +9035,37 @@ void TrackPanel::OnMergeStereo(wxCommandEvent & WXUNUSED(event)) Refresh(false); } +class ViewSettingsDialog : public PrefsDialog +{ +public: + ViewSettingsDialog(wxWindow *parent, PrefsDialog::Factories &factories) + : PrefsDialog(parent, _("View Settings: "), factories) + { + } + + virtual long GetPreferredPage() + { + // Future: choose Spectrum or Waveform page + return 0; + } + + virtual void SavePreferredPage() + { + } +}; + +void TrackPanel::OnViewSettings(wxCommandEvent &) +{ + WaveTrack *const wt = static_cast(mPopupMenuTarget); + SpectrumPrefsFactory spectrumFactory(wt); + PrefsDialog::Factories factories; + factories.push_back(&spectrumFactory); + ViewSettingsDialog dialog(this, factories); + if (0 != dialog.ShowModal()) + // Redraw + Refresh(false); +} + /// Set the Display mode based on the menu choice in the Track Menu. /// Note that gModes MUST BE IN THE SAME ORDER AS THE MENU CHOICES!! /// const wxChar *gModes[] = { wxT("waveform"), wxT("waveformDB"), diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 02e9eb4aa..c93eaab3c 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -459,6 +459,7 @@ protected: virtual void MoveTrack(Track* target, int eventId); virtual void OnChangeOctave (wxCommandEvent &event); virtual void OnChannelChange(wxCommandEvent &event); + virtual void OnViewSettings(wxCommandEvent &event); virtual void OnSetDisplay (wxCommandEvent &event); virtual void OnSetTimeTrackRange (wxCommandEvent &event); virtual void OnTimeTrackLin(wxCommandEvent &event);