diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 4a9e63021..68deb14f5 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -93,6 +93,7 @@ It handles initialization and termination by subclassing wxApp. #include "commands/Keyboard.h" #include "widgets/ErrorDialog.h" #include "prefs/DirectoriesPrefs.h" +#include "prefs/SpectrogramSettings.h" //temporarilly commented out till it is added to all projects //#include "Profiler.h" @@ -1011,7 +1012,11 @@ void AudacityApp::InitLang( const wxString & lang ) // // This must go _after_ creating the wxLocale instance because // creating the wxLocale instance sets the application-wide locale. + Internat::Init(); + + // Some static arrays unconnected with any project want to be informed of language changes. + SpectrogramSettings::InvalidateNames(); } void AudacityApp::OnFatalException() diff --git a/src/Menus.cpp b/src/Menus.cpp index 92c00da52..157fe7550 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -4765,12 +4765,7 @@ void AudacityProject::DoNextPeakFrequency(bool up) for (Track *t = iter.First(); t; t = iter.Next()) { WaveTrack *const wt = static_cast(t); const int display = wt->GetDisplay(); - if (display == WaveTrack::SpectrumDisplay || - display == WaveTrack::SpectrumLogDisplay || - display == WaveTrack::SpectralSelectionDisplay || - display == WaveTrack::SpectralSelectionLogDisplay - - ) { + if (display == WaveTrack::Spectrum) { pTrack = wt; break; } diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index 4dc811d20..b23940050 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -464,10 +464,7 @@ void TrackArtist::DrawTrack(const Track * t, DrawWaveform(wt, dc, rect, selectedRegion, zoomInfo, drawEnvelope, bigPoints, drawSliders, true, muted); break; - case WaveTrack::SpectrumDisplay: - case WaveTrack::SpectrumLogDisplay: - case WaveTrack::SpectralSelectionDisplay: - case WaveTrack::SpectralSelectionLogDisplay: + case WaveTrack::Spectrum: case WaveTrack::PitchDisplay: DrawSpectrum(wt, dc, rect, selectedRegion, zoomInfo); break; @@ -793,66 +790,71 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect) vruler->SetLabelEdges(true); vruler->SetLog(false); } - else if ( - (display == WaveTrack::SpectrumDisplay) || - (display == WaveTrack::SpectralSelectionDisplay) ) - { - // Spectrum + else if (display == WaveTrack::Spectrum) { + switch (wt->GetSpectrogramSettings().scaleType) { + default: + wxASSERT(false); + case SpectrogramSettings::stLinear: + { + // Spectrum - if (rect.height < 60) - return; + if (rect.height < 60) + return; - const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); - const double rate = wt->GetRate(); - const int maxFreq = settings.GetMaxFreq(rate); - const int minFreq = settings.GetMinFreq(rate); + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + const double rate = wt->GetRate(); + const int maxFreq = settings.GetMaxFreq(rate); + const int minFreq = settings.GetMinFreq(rate); - /* + /* draw the ruler we will use Hz if maxFreq is < 2000, otherwise we represent kHz, and append to the numbers a "k" - */ - vruler->SetBounds(rect.x, rect.y+1, rect.x + rect.width, rect.y + rect.height-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetFormat(Ruler::RealFormat); - vruler->SetLabelEdges(true); - // use kHz in scale, if appropriate - if (maxFreq>=2000) { - vruler->SetRange((maxFreq/1000.), (minFreq/1000.)); - vruler->SetUnits(wxT("k")); - } else { - // use Hz - vruler->SetRange(int(maxFreq), int(minFreq)); - vruler->SetUnits(wxT("")); + */ + vruler->SetBounds(rect.x, rect.y + 1, rect.x + rect.width, rect.y + rect.height - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetFormat(Ruler::RealFormat); + vruler->SetLabelEdges(true); + // use kHz in scale, if appropriate + if (maxFreq >= 2000) { + vruler->SetRange((maxFreq / 1000.), (minFreq / 1000.)); + vruler->SetUnits(wxT("k")); + } + else { + // use Hz + vruler->SetRange(int(maxFreq), int(minFreq)); + vruler->SetUnits(wxT("")); + } + vruler->SetLog(false); } - vruler->SetLog(false); - } - else if ( - (display == WaveTrack::SpectrumLogDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay) ) - { - // SpectrumLog + break; + case SpectrogramSettings::stLogarithmic: + { + // SpectrumLog - if (rect.height < 10) - return; + if (rect.height < 10) + return; - const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); - const double rate = wt->GetRate(); - const int maxFreq = settings.GetLogMaxFreq(rate); - const int minFreq = settings.GetLogMinFreq(rate); + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + const double rate = wt->GetRate(); + const int maxFreq = settings.GetLogMaxFreq(rate); + const int minFreq = settings.GetLogMinFreq(rate); - /* + /* draw the ruler we will use Hz if maxFreq is < 2000, otherwise we represent kHz, and append to the numbers a "k" - */ - vruler->SetBounds(rect.x, rect.y+1, rect.x + rect.width, rect.y + rect.height-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetFormat(Ruler::IntFormat); - vruler->SetLabelEdges(true); - vruler->SetRange(maxFreq, minFreq); - vruler->SetUnits(wxT("")); - vruler->SetLog(true); + */ + vruler->SetBounds(rect.x, rect.y + 1, rect.x + rect.width, rect.y + rect.height - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetFormat(Ruler::IntFormat); + vruler->SetLabelEdges(true); + vruler->SetRange(maxFreq, minFreq); + vruler->SetUnits(wxT("")); + vruler->SetLog(true); + } + break; + } } else if (display == WaveTrack::PitchDisplay) { // Pitch @@ -2034,8 +2036,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, const int display = track->GetDisplay(); const bool autocorrelation = (WaveTrack::PitchDisplay == display); - const bool logF = (WaveTrack::SpectrumLogDisplay == display - || WaveTrack::SpectralSelectionLogDisplay == display); + const bool logF = settings.scaleType == SpectrogramSettings::stLogarithmic; + enum { DASH_LENGTH = 10 /* pixels */ }; const ClipParameters params(true, track, clip, rect, selectedRegion, zoomInfo); @@ -2104,8 +2106,14 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, t0, pps, autocorrelation); } - const int minFreq = logF ? settings.GetLogMinFreq(rate) : settings.GetMinFreq(rate); - const int maxFreq = logF ? settings.GetLogMaxFreq(rate) : settings.GetMaxFreq(rate); + // Legacy special-case treatment of log scale + const SpectrogramSettings::ScaleType scaleType = settings.scaleType; + const int minFreq = + scaleType == SpectrogramSettings::stLinear + ? settings.GetMinFreq(rate) : settings.GetLogMinFreq(rate); + const int maxFreq = + scaleType == SpectrogramSettings::stLinear + ? settings.GetMaxFreq(rate) : settings.GetLogMaxFreq(rate); float minBin = ((double)minFreq / binUnit); float maxBin = ((double)maxFreq / binUnit); @@ -2140,7 +2148,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, #endif //EXPERIMENTAL_FFT_Y_GRID if (!updated && clip->mSpecPxCache->valid && - (clip->mSpecPxCache->len == hiddenMid.height * hiddenMid.width) + (clip->mSpecPxCache->len == hiddenMid.height * hiddenMid.width) + && scaleType == clip->mSpecPxCache->scaleType && gain == clip->mSpecPxCache->gain && range == clip->mSpecPxCache->range && minFreq == clip->mSpecPxCache->minFreq @@ -2163,6 +2172,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, delete clip->mSpecPxCache; clip->mSpecPxCache = new SpecPxCache(hiddenMid.width * hiddenMid.height); clip->mSpecPxCache->valid = true; + clip->mSpecPxCache->scaleType = scaleType; clip->mSpecPxCache->gain = gain; clip->mSpecPxCache->range = range; clip->mSpecPxCache->minFreq = minFreq; @@ -2334,6 +2344,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, (zoomInfo.PositionToTime(0, -leftOffset) - tOffset) ); + const bool isSpectral = settings.SpectralSelectionEnabled(); const bool hidden = (ZoomInfo::HIDDEN == zoomInfo.GetFisheyeState()); const int begin = hidden ? 0 @@ -2389,12 +2400,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, AColor::ColorGradientUnselected; // If we are in the time selected range, then we may use a different color set. if (ssel0 <= w0 && w1 < ssel1) - { - bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) || - (track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay)); selected = ChooseColorSet(bin0, bin1, selBinLo, selBinCenter, selBinHi, (xx + leftOffset - hiddenLeftOffset) / DASH_LENGTH, isSpectral); - } unsigned char rv, gv, bv; const float value = uncached @@ -2429,13 +2436,9 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, AColor::ColorGradientChoice selected = AColor::ColorGradientUnselected; // If we are in the time selected range, then we may use a different color set. if (ssel0 <= w0 && w1 < ssel1) - { - bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) || - (track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay)); selected = ChooseColorSet( bin0, bin1, selBinLo, selBinCenter, selBinHi, (xx + leftOffset - hiddenLeftOffset) / DASH_LENGTH, isSpectral); - } unsigned char rv, gv, bv; const float value = uncached @@ -2475,23 +2478,6 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, #endif //EXPERIMENTAL_FFT_Y_GRID } -void TrackArtist::InvalidateSpectrumCache(TrackList *tracks) -{ - TrackListOfKindIterator iter(Track::Wave, tracks); - for (Track *t = iter.First(); t; t = iter.Next()) { - InvalidateSpectrumCache((WaveTrack *)t); - } -} - -void TrackArtist::InvalidateSpectrumCache(WaveTrack *track) -{ - WaveClipList::compatibility_iterator it; - for (it = track->GetClipIterator(); it; it = it->GetNext()) { - it->GetData()->mSpecPxCache->valid = false; - } -} - - #ifdef USE_MIDI /* Note: recall that Allegro attributes end in a type identifying letter. diff --git a/src/TrackArtist.h b/src/TrackArtist.h index b0deb0fe8..ebb280e3d 100644 --- a/src/TrackArtist.h +++ b/src/TrackArtist.h @@ -71,9 +71,6 @@ class AUDACITY_DLL_API TrackArtist { void UpdatePrefs(); - void InvalidateSpectrumCache(TrackList *tracks); - void InvalidateSpectrumCache(WaveTrack *track); - void SetBackgroundBrushes(wxBrush unselectedBrush, wxBrush selectedBrush, wxPen unselectedPen, wxPen selectedPen) { this->unselectedBrush = unselectedBrush; diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 72b92a049..ea113b475 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -327,9 +327,6 @@ enum { OnWaveformID, OnWaveformDBID, OnSpectrumID, - OnSpectrumLogID, - OnSpectralSelID, - OnSpectralSelLogID, OnPitchID, OnViewSettingsID, @@ -727,13 +724,7 @@ void TrackPanel::BuildMenus(void) BuildCommonDropMenuItems(mWaveTrackMenu); // does name, up/down etc mWaveTrackMenu->Append(OnWaveformID, _("Wa&veform")); mWaveTrackMenu->Append(OnWaveformDBID, _("&Waveform (dB)")); - mWaveTrackMenu->Append(OnSpectrumID, _("&Spectrogram")); - /* i18n-hint: short form of 'logarithm'*/ - mWaveTrackMenu->Append(OnSpectrumLogID, _("Spectrogram l&og(f)")); - /* i18n-hint: Spectral Selection is spectrogram with ability to select frequencies too'*/ - mWaveTrackMenu->Append(OnSpectralSelID, _("S&pectral Selection")); - /* i18n-hint: short form of 'logarithm'*/ - mWaveTrackMenu->Append(OnSpectralSelLogID, _("Spectral Selection lo&g(f)")); + mWaveTrackMenu->Append(OnSpectrumID, _("&Spectrum")); mWaveTrackMenu->Append(OnPitchID, _("Pitc&h (EAC)")); mWaveTrackMenu->Append(OnViewSettingsID, _("View& Settings...")); // PRL: all the other letters already taken for accelerators! mWaveTrackMenu->AppendSeparator(); @@ -1811,16 +1802,18 @@ void TrackPanel::SetCursorAndTipWhenInLabelTrack( LabelTrack * pLT, namespace { // This returns true if we're a spectral editing track. -inline bool isSpectrogramTrack(const Track *pTrack, bool *pLogf = NULL) { +inline bool isSpectralSelectionTrack(const Track *pTrack, bool *pLogf = NULL) { if (pTrack && pTrack->GetKind() == Track::Wave) { - const int display = - static_cast(pTrack)->GetDisplay(); - const bool logF = (display == WaveTrack::SpectrumLogDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay); - if (pLogf) + const WaveTrack *const wt = static_cast(pTrack); + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + const int display = wt->GetDisplay(); + if (pLogf) { + const bool logF = + settings.scaleType == SpectrogramSettings::stLogarithmic; *pLogf = logF; - return (display == WaveTrack::SpectralSelectionLogDisplay) || (display == WaveTrack::SpectralSelectionDisplay); + } + return (display == WaveTrack::Spectrum) && settings.SpectralSelectionEnabled(); } else { if (pLogf) @@ -1950,7 +1943,7 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, #ifdef EXPERIMENTAL_SPECTRAL_EDITING bool logF; if ( (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) && - isSpectrogramTrack(t, &logF) ) { + isSpectralSelectionTrack(t, &logF)) { // Not shift-down, but center frequency snapping toggle is on *ppTip = _("Click and drag to set frequency bandwidth."); *ppCursor = mEnvelopeCursor; @@ -2688,7 +2681,7 @@ void TrackPanel::SelectionHandleClick(wxMouseEvent & event, #ifdef EXPERIMENTAL_SPECTRAL_EDITING bool logF; if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER && - isSpectrogramTrack(pTrack, &logF)) { + isSpectralSelectionTrack(pTrack, &logF)) { // Ignore whether we are inside the time selection. // Exit center-snapping, start dragging the width. mFreqSelMode = FREQ_SEL_PINNED_CENTER; @@ -3082,7 +3075,7 @@ void TrackPanel::MoveSnappingFreqSelection (int mouseYCoordinate, bool logF; if (pTrack && pTrack->GetSelected() && - isSpectrogramTrack(pTrack, &logF)) { + isSpectralSelectionTrack(pTrack, &logF)) { WaveTrack *const wt = static_cast(pTrack); // PRL: // What happens if center snapping selection began in one spectrogram track, @@ -3126,7 +3119,7 @@ void TrackPanel::StartFreqSelection (int mouseYCoordinate, int trackTopEdge, mFreqSelPin = SelectedRegion::UndefinedFrequency; bool logF; - if (isSpectrogramTrack(pTrack, &logF)) { + if (isSpectralSelectionTrack(pTrack, &logF)) { mFreqSelTrack = static_cast(pTrack); mFreqSelMode = FREQ_SEL_FREE; mFreqSelPin = @@ -3150,10 +3143,8 @@ void TrackPanel::ExtendFreqSelection(int mouseYCoordinate, int trackTopEdge, // started, and that is of a spectrogram display type. const WaveTrack* wt = mFreqSelTrack; - const int display = wt->GetDisplay(); - const bool logF = (display == WaveTrack::SpectrumLogDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay) - ; + const bool logF = + wt->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLogarithmic; const double rate = wt->GetRate(); const double frequency = PositionToFrequency(wt, true, mouseYCoordinate, @@ -3685,7 +3676,7 @@ bool mayDragWidth, bool onlyWithinSnapDistance, // within the time boundaries if (!mViewInfo->selectedRegion.isPoint() && t0 <= selend && selend < t1 && - isSpectrogramTrack(pTrack, &logF)) { + isSpectralSelectionTrack(pTrack, &logF)) { const WaveTrack *const wt = static_cast(pTrack); const wxInt64 bottomSel = (f0 >= 0) ? FrequencyToPosition(wt, f0, rect.y, rect.height, logF) @@ -4694,11 +4685,12 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) float min, max, c, l, binSize = 0.0; const double rate = track->GetRate(); - const bool spectrum = (track->GetDisplay() == WaveTrack::SpectrumDisplay) || - (track->GetDisplay() == WaveTrack::SpectralSelectionDisplay); - const bool spectrumLog = (track->GetDisplay() == WaveTrack::SpectrumLogDisplay) || - (track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay); - if(spectrum) { + const bool spectral = (track->GetDisplay() == WaveTrack::Spectrum); + const bool spectrumLinear = spectral && + (track->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLinear); + const bool spectrumLog = spectral && + (track->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLogarithmic); + if (spectrumLinear) { const SpectrogramSettings &settings = track->GetSpectrogramSettings(); min = settings.GetMinFreq(rate); max = settings.GetMaxFreq(rate); @@ -4706,17 +4698,16 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) binSize = rate / fftLength; minBins = std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less } + else if (spectrumLog) { + const SpectrogramSettings &settings = track->GetSpectrogramSettings(); + min = settings.GetLogMinFreq(rate); + max = settings.GetLogMaxFreq(rate); + const int fftLength = settings.GetFFTLength(false); + binSize = rate / fftLength; + minBins = std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less + } else - if(spectrumLog) { - const SpectrogramSettings &settings = track->GetSpectrogramSettings(); - min = settings.GetLogMinFreq(rate); - max = settings.GetLogMaxFreq(rate); - const int fftLength = settings.GetFFTLength(false); - binSize = rate / fftLength; - minBins = std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less - } - else - track->GetDisplayBounds(&min, &max); + track->GetDisplayBounds(&min, &max); if (IsDragZooming()) { // Drag Zoom float p1, p2, tmin, tmax; @@ -4746,7 +4737,7 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) min = (tmax * (1.0-p2) + tmin * p2); // Enforce vertical zoom limits - if(spectrum) { + if(spectrumLinear) { if(min < 0.) min = 0.; if(max < min + minBins * binSize) @@ -4771,7 +4762,7 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) // Zoom out to -1.0...1.0 first, then, and only // then, if they click again, allow one more // zoom out. - if(spectrum) { + if (spectrumLinear) { if (event.ShiftDown() && event.RightUp()) { // Zoom out full min = 0.0; @@ -4840,7 +4831,7 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) else { // Zoom IN float p1; - if(spectrum) { + if (spectrumLinear) { c = 0.5*(min+max); // Enforce maximum vertical zoom l = std::max( minBins * binSize, (c - min)); @@ -4889,7 +4880,7 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) } } - if(spectrum) { + if (spectrumLinear) { SpectrogramSettings &settings = track->GetSpectrogramSettings(); settings.SetMinFreq(min); settings.SetMaxFreq(max); @@ -4899,7 +4890,6 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) settings.SetMinFreq(min); settings.SetMaxFreq(max); } - mTrackArtist->InvalidateSpectrumCache(mTracks); } else if(spectrumLog) { SpectrogramSettings &settings = track->GetSpectrogramSettings(); @@ -4911,7 +4901,6 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) settings.SetLogMinFreq(min); settings.SetLogMaxFreq(max); } - mTrackArtist->InvalidateSpectrumCache(mTracks); } else { track->SetDisplayBounds(min, max); @@ -8568,10 +8557,7 @@ void TrackPanel::OnTrackMenu(Track *t) theMenu->Enable(OnWaveformID, display != WaveTrack::WaveformDisplay); theMenu->Enable(OnWaveformDBID, display != WaveTrack::WaveformDBDisplay); - theMenu->Enable(OnSpectrumID, display != WaveTrack::SpectrumDisplay); - theMenu->Enable(OnSpectrumLogID, display != WaveTrack::SpectrumLogDisplay); - theMenu->Enable(OnSpectralSelID, display != WaveTrack::SpectralSelectionDisplay); - theMenu->Enable(OnSpectralSelLogID, display != WaveTrack::SpectralSelectionLogDisplay); + theMenu->Enable(OnSpectrumID, display != WaveTrack::Spectrum); theMenu->Enable(OnPitchID, display != WaveTrack::PitchDisplay); theMenu->Enable(OnViewSettingsID, true); @@ -9087,26 +9073,17 @@ void TrackPanel::OnSetDisplay(wxCommandEvent & event) case OnWaveformDBID: id = WaveTrack::WaveformDBDisplay; break; case OnSpectrumID: - id = WaveTrack::SpectrumDisplay; break; - case OnSpectrumLogID: - id = WaveTrack::SpectrumLogDisplay; break; - case OnSpectralSelID: - id = WaveTrack::SpectralSelectionDisplay; break; - case OnSpectralSelLogID: - id = WaveTrack::SpectralSelectionLogDisplay; break; + id = WaveTrack::Spectrum; break; case OnPitchID: id = WaveTrack::PitchDisplay; break; } WaveTrack *wt = (WaveTrack *) mPopupMenuTarget; if (wt->GetDisplay() != id) { wt->SetDisplay(WaveTrack::WaveTrackDisplay(id)); - mTrackArtist->InvalidateSpectrumCache(wt); - WaveTrack *l = (WaveTrack *) wt->GetLink(); - if (l) { + WaveTrack *l = static_cast(wt->GetLink()); + if (l) l->SetDisplay(WaveTrack::WaveTrackDisplay(id)); - mTrackArtist->InvalidateSpectrumCache(l); - } #ifdef EXPERIMENTAL_OUTPUT_DISPLAY if (wt->GetDisplay() == WaveTrack::WaveformDisplay) { wt->SetVirtualState(false); diff --git a/src/WaveClip.h b/src/WaveClip.h index 07bd5230b..686472923 100644 --- a/src/WaveClip.h +++ b/src/WaveClip.h @@ -127,6 +127,7 @@ public: len = cacheLen; values = new float[len]; valid = false; + scaleType = 0; range = gain = -1; minFreq = maxFreq = -1; } @@ -140,6 +141,7 @@ public: float *values; bool valid; + int scaleType; int range; int gain; int minFreq; diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 44f3c5cf5..5048a2e9a 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -235,9 +235,12 @@ WaveTrack::ConvertLegacyDisplayValue(int oldValue) case WaveformDB: newValue = WaveTrack::WaveformDBDisplay; break; case Spectrogram: - newValue = WaveTrack::SpectrumDisplay; break; + case SpectrogramLogF: + newValue = WaveTrack::Spectrum; break; + /* case SpectrogramLogF: newValue = WaveTrack::SpectrumLogDisplay; break; + */ case Pitch: newValue = WaveTrack::PitchDisplay; break; } @@ -248,11 +251,24 @@ WaveTrack::ConvertLegacyDisplayValue(int oldValue) WaveTrack::WaveTrackDisplay WaveTrack::ValidateWaveTrackDisplay(WaveTrackDisplay display) { - // To do, in future: detect obsolete values between min and max - if (display >= int(MinDisplay) && display <= int(MaxDisplay)) + switch (display) { + // non-obsolete codes + case WaveformDisplay: + case WaveformDBDisplay: + case Spectrum: + case PitchDisplay: return display; - else + + // obsolete codes + case obsolete1: // was SpectrumLogDisplay + case obsolete2: // was SpectralSelectionDisplay + case obsolete3: // was SpectralSelectionLogDisplay + return Spectrum; + + // codes out of bounds (from future prefs files?) + default: return MinDisplay; + } } void WaveTrack::GetDisplayBounds(float *min, float *max) diff --git a/src/WaveTrack.h b/src/WaveTrack.h index 3e72dfb04..aefb834eb 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -418,10 +418,12 @@ class AUDACITY_DLL_API WaveTrack: public Track { MinDisplay = WaveformDisplay, WaveformDBDisplay, - SpectrumDisplay, - SpectrumLogDisplay, - SpectralSelectionDisplay, - SpectralSelectionLogDisplay, + Spectrum, + + obsolete1, // was SpectrumLogDisplay + obsolete2, // was SpectralSelectionDisplay + obsolete3, // was SpectralSelectionLogDisplay + PitchDisplay, // Add values here, and update MaxDisplay. @@ -441,14 +443,10 @@ class AUDACITY_DLL_API WaveTrack: public Track { static WaveTrackDisplay ValidateWaveTrackDisplay(WaveTrackDisplay display); void SetDisplay(WaveTrackDisplay display) { - if(mDisplay < 2) + if (mDisplay < Spectrum) // remember last display mode for wave and wavedb so they can remap the vertical ruler mLastDisplay = mDisplay; mDisplay = display; - if( mDisplay == SpectralSelectionDisplay ){ - } - if( mDisplay == SpectralSelectionLogDisplay ){ - } } WaveTrackDisplay GetDisplay() const { return mDisplay; } int GetLastDisplay() {return mLastDisplay;} diff --git a/src/effects/nyquist/Nyquist.cpp b/src/effects/nyquist/Nyquist.cpp index 718cd1ba4..04030efa7 100644 --- a/src/effects/nyquist/Nyquist.cpp +++ b/src/effects/nyquist/Nyquist.cpp @@ -45,6 +45,7 @@ effects from this one class. #include "../../FileNames.h" #include "../../Internat.h" #include "../../LabelTrack.h" +#include "../../prefs/SpectrogramSettings.h" #include "../../Project.h" #include "../../ShuttleGui.h" #include "../../WaveClip.h" @@ -603,8 +604,8 @@ bool NyquistEffect::Process() const WaveTrack::WaveTrackDisplay display = mCurTrack[0]->GetDisplay(); const bool bAllowSpectralEditing = - (display == WaveTrack::SpectralSelectionDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay); + (display == WaveTrack::Spectrum) && + mCurTrack[0]->GetSpectrogramSettings().SpectralSelectionEnabled(); if (bAllowSpectralEditing) { #if defined(EXPERIMENTAL_SPECTRAL_EDITING) @@ -790,10 +791,7 @@ bool NyquistEffect::ProcessOne() { case WaveTrack::WaveformDisplay: view = wxT("\"Waveform\""); break; case WaveTrack::WaveformDBDisplay: view = wxT("\"Waveform (dB)\""); break; - case WaveTrack::SpectrumDisplay: view = wxT("\"Spectrogram\""); break; - case WaveTrack::SpectrumLogDisplay: view = wxT("\"Spectrogram log(f)\""); break; - case WaveTrack::SpectralSelectionDisplay: view = wxT("\"Spectral Selection\""); break; - case WaveTrack::SpectralSelectionLogDisplay: view = wxT("\"Spectral Selection log(f)\""); break; + case WaveTrack::Spectrum: view = wxT("\"Spectrum\""); break; case WaveTrack::PitchDisplay: view = wxT("\"Pitch (EAC)\""); break; default: view = wxT("NIL"); break; } diff --git a/src/prefs/SpectrogramSettings.cpp b/src/prefs/SpectrogramSettings.cpp index d67f1ed41..173d2f58a 100644 --- a/src/prefs/SpectrogramSettings.cpp +++ b/src/prefs/SpectrogramSettings.cpp @@ -26,6 +26,33 @@ Paul Licameli #include #include +SpectrogramSettings::Globals::Globals() +{ + LoadPrefs(); +} + +void SpectrogramSettings::Globals::SavePrefs() +{ +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + gPrefs->Write(wxT("/Spectrum/EnableSpectralSelection"), spectralSelection); +#endif +} + +void SpectrogramSettings::Globals::LoadPrefs() +{ +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + spectralSelection + = (gPrefs->Read(wxT("/Spectrum/EnableSpectralSelection"), 0L) != 0); +#endif +} + +SpectrogramSettings::Globals +&SpectrogramSettings::Globals::Get() +{ + static Globals instance; + return instance; +} + SpectrogramSettings::SpectrogramSettings() : hFFT(0) , window(0) @@ -47,6 +74,10 @@ SpectrogramSettings::SpectrogramSettings(const SpectrogramSettings &other) , zeroPaddingFactor(other.zeroPaddingFactor) #endif , isGrayscale(other.isGrayscale) + , scaleType(other.scaleType) +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + , spectralSelection(other.spectralSelection) +#endif #ifdef EXPERIMENTAL_FFT_Y_GRID , fftYGrid(other.fftYGrid) #endif @@ -79,6 +110,10 @@ SpectrogramSettings &SpectrogramSettings::operator= (const SpectrogramSettings & zeroPaddingFactor = other.zeroPaddingFactor; #endif isGrayscale = other.isGrayscale; + scaleType = other.scaleType; +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + spectralSelection = other.spectralSelection; +#endif #ifdef EXPERIMENTAL_FFT_Y_GRID fftYGrid = other.fftYGrid; #endif @@ -102,6 +137,35 @@ SpectrogramSettings& SpectrogramSettings::defaults() return instance; } +namespace +{ + wxArrayString &scaleNamesArray() + { + static wxArrayString theArray; + return theArray; + } +} + +//static +void SpectrogramSettings::InvalidateNames() +{ + scaleNamesArray().Clear(); +} + +//static +const wxArrayString &SpectrogramSettings::GetScaleNames() +{ + wxArrayString &theArray = scaleNamesArray(); + + if (theArray.IsEmpty()) { + // Keep in correspondence with enum SpectrogramSettings::ScaleType: + theArray.Add(_("Linear")); + theArray.Add(_("Logarithmic")); + } + + return theArray; +} + bool SpectrogramSettings::Validate(bool quiet) { if (!quiet && @@ -155,6 +219,10 @@ bool SpectrogramSettings::Validate(bool quiet) // preference files, which could be or from future versions. Validate quietly. windowType = std::max(0, std::min(NumWindowFuncs() - 1, windowType)); + scaleType = + ScaleType(std::max(0, + std::min(int(SpectrogramSettings::stNumScaleTypes) - 1, + int(scaleType)))); ConvertToEnumeratedWindowSizes(); ConvertToActualWindowSizes(); @@ -181,6 +249,12 @@ void SpectrogramSettings::LoadPrefs() isGrayscale = (gPrefs->Read(wxT("/Spectrum/Grayscale"), 0L) != 0); + scaleType = ScaleType(gPrefs->Read(wxT("/Spectrum/ScaleType"), 0L)); + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + spectralSelection = (gPrefs->Read(wxT("/Spectrum/EnableSpectralSelection"), 0L) != 0); +#endif + #ifdef EXPERIMENTAL_FFT_Y_GRID fftYGrid = (gPrefs->Read(wxT("/Spectrum/FFTYGrid"), 0L) != 0); #endif //EXPERIMENTAL_FFT_Y_GRID @@ -235,6 +309,12 @@ void SpectrogramSettings::SavePrefs() gPrefs->Write(wxT("/Spectrum/Grayscale"), isGrayscale); + gPrefs->Write(wxT("/Spectrum/ScaleType"), scaleType); + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + gPrefs->Write(wxT("/Spectrum/EnableSpectralSelection"), spectralSelection); +#endif + #ifdef EXPERIMENTAL_FFT_Y_GRID gPrefs->Write(wxT("/Spectrum/FFTYGrid"), fftYGrid); #endif //EXPERIMENTAL_FFT_Y_GRID @@ -443,3 +523,12 @@ int SpectrogramSettings::GetFFTLength(bool autocorrelation) const #endif ; } + +bool SpectrogramSettings::SpectralSelectionEnabled() const +{ +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + return Globals::Get().spectralSelection; +#else + return spectralSelection; +#endif +} diff --git a/src/prefs/SpectrogramSettings.h b/src/prefs/SpectrogramSettings.h index f67e47b70..3f4a34dca 100644 --- a/src/prefs/SpectrogramSettings.h +++ b/src/prefs/SpectrogramSettings.h @@ -13,14 +13,33 @@ Paul Licameli #include "../Experimental.h" +#undef SPECTRAL_SELECTION_GLOBAL_SWITCH + struct FFTParam; class SpectrumPrefs; +class wxArrayString; class SpectrogramSettings { friend class SpectrumPrefs; public: + // Singleton for settings that are not per-track + class Globals + { + public: + static Globals &Get(); + void SavePrefs(); + +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + bool spectralSelection; +#endif + + private: + Globals(); + void LoadPrefs(); + }; + enum { LogMinWindowSize = 3, LogMaxWindowSize = 15, @@ -28,6 +47,19 @@ public: NumWindowSizes = LogMaxWindowSize - LogMinWindowSize + 1, }; + // Do not assume that this enumeration will remain the + // same as NumberScaleType in future. That enum may become + // more general purpose. + enum ScaleType { + stLinear, + stLogarithmic, + + stNumScaleTypes, + }; + + static void InvalidateNames(); // in case of language change + static const wxArrayString &GetScaleNames(); + static SpectrogramSettings &defaults(); SpectrogramSettings(); SpectrogramSettings(const SpectrogramSettings &other); @@ -58,6 +90,7 @@ public: int GetMaxFreq(double rate) const; int GetLogMinFreq(double rate) const; int GetLogMaxFreq(double rate) const; + bool SpectralSelectionEnabled() const; void SetMinFreq(int freq); void SetMaxFreq(int freq); @@ -79,6 +112,12 @@ public: bool isGrayscale; + ScaleType scaleType; + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + bool spectralSelection; // But should this vary per track? -- PRL +#endif + #ifdef EXPERIMENTAL_FFT_Y_GRID bool fftYGrid; #endif //EXPERIMENTAL_FFT_Y_GRID @@ -98,5 +137,4 @@ public: mutable float *window; #endif }; - #endif diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index c63847909..8c085ff22 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -59,12 +59,14 @@ enum { #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS ID_WINDOW_TYPE, ID_PADDING_SIZE, + ID_SCALE, ID_MINIMUM, ID_MAXIMUM, ID_GAIN, ID_RANGE, ID_FREQUENCY_GAIN, ID_GRAYSCALE, + ID_SPECTRAL_SELECTION, #endif ID_DEFAULTS, ID_APPLY, @@ -93,6 +95,7 @@ void SpectrumPrefs::Populate(int windowSize) mTypeChoices.Add(WindowFuncName(i)); } + mScaleChoices = SpectrogramSettings::GetScaleNames(); //------------------------- Main section -------------------- // Now construct the GUI itself. @@ -182,6 +185,10 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) { S.StartTwoColumn(); { + S.Id(ID_SCALE).TieChoice(_("S&cale") + wxString(wxT(":")), + *(int*)&mTempSettings.scaleType, + &mScaleChoices); + mMinFreq = S.Id(ID_MINIMUM).TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), mTempSettings.minFreq, @@ -212,6 +219,11 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) S.Id(ID_GRAYSCALE).TieCheckBox(_("S&how the spectrum using grayscale colors"), mTempSettings.isGrayscale); +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + S.Id(ID_SPECTRAL_SELECTION).TieCheckBox(_("Ena&ble spectral selection"), + mTempSettings.spectralSelection); +#endif + #ifdef EXPERIMENTAL_FFT_Y_GRID S.TieCheckBox(_("Show a grid along the &Y-axis"), mTempSettings.fftYGrid); @@ -248,6 +260,15 @@ void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) } // S.EndStatic(); +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + S.StartStatic(_("Global settings")); + { + S.TieCheckBox(_("Ena&ble spectral selection"), + SpectrogramSettings::Globals::Get().spectralSelection); + } + S.EndStatic(); +#endif + S.StartMultiColumn(2, wxALIGN_RIGHT); { S.Id(ID_APPLY).AddButton(_("Appl&y")); @@ -331,7 +352,10 @@ bool SpectrumPrefs::Apply() ShuttleGui S(this, eIsGettingFromDialog); PopulateOrExchange(S); + mTempSettings.ConvertToActualWindowSizes(); + SpectrogramSettings::Globals::Get().SavePrefs(); // always + if (mWt) { if (mDefaulted) { mWt->SetSpectrogramSettings(NULL); @@ -358,11 +382,9 @@ bool SpectrumPrefs::Apply() if (mWt && isOpenPage) { // Future: open page will determine the track view type - /* mWt->SetDisplay(WaveTrack::Spectrum); if (partner) partner->SetDisplay(WaveTrack::Spectrum); - */ } return true; @@ -421,14 +443,17 @@ BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) // 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_CHOICE(ID_SCALE, 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) + EVT_CHECKBOX(ID_SPECTRAL_SELECTION, 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 dc07c7115..1496b0c6d 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -74,6 +74,7 @@ class SpectrumPrefs:public PrefsPanel #endif wxArrayString mTypeChoices; + wxArrayString mScaleChoices; #ifdef EXPERIMENTAL_FIND_NOTES diff --git a/src/prefs/TracksPrefs.cpp b/src/prefs/TracksPrefs.cpp index 7bed5d735..6f86435fd 100644 --- a/src/prefs/TracksPrefs.cpp +++ b/src/prefs/TracksPrefs.cpp @@ -65,17 +65,8 @@ void TracksPrefs::Populate() mViewChoices.Add(_("Waveform (dB)")); mViewCodes.Add(int(WaveTrack::WaveformDBDisplay)); - mViewChoices.Add(_("Spectrogram")); - mViewCodes.Add(int(WaveTrack::SpectrumDisplay)); - - mViewChoices.Add(_("Spectrogram log(f)")); - mViewCodes.Add(int(WaveTrack::SpectrumLogDisplay)); - - mViewChoices.Add(_("Spectral Selection")); - mViewCodes.Add(int(WaveTrack::SpectralSelectionDisplay)); - - mViewChoices.Add(_("Spectral Selection log(f)")); - mViewCodes.Add(int(WaveTrack::SpectralSelectionLogDisplay)); + mViewChoices.Add(_("Spectrum")); + mViewCodes.Add(WaveTrack::Spectrum); mViewChoices.Add(_("Pitch (EAC)")); mViewCodes.Add(int(WaveTrack::PitchDisplay));