From 2c6401b564fe48e73e88a65123e067b9052f49ef Mon Sep 17 00:00:00 2001 From: lllucius Date: Mon, 22 Dec 2014 08:03:41 +0000 Subject: [PATCH] Committing Paul's spectral nagivation commands patch From: http://audacity.238276.n2.nabble.com/Patch-spectral-peak-snapping-navigation-commands-td7565648.html --- src/Menus.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/Menus.h | 3 +++ src/TrackPanel.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/TrackPanel.h | 3 +++ 4 files changed, 82 insertions(+) diff --git a/src/Menus.cpp b/src/Menus.cpp index 3f2fd9b4d..a31b1baab 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -574,7 +574,11 @@ void AudacityProject::CreateMenusAndCommands() c->AddItem(wxT("SelectNone"), _("&None"), FN(OnSelectNone), wxT("Ctrl+Shift+A")); #ifdef EXPERIMENTAL_SPECTRAL_EDITING + c->BeginSubMenu(_("S&pectral")); c->AddItem(wxT("ToggleSpectralSelection"), _("To&ggle spectral selection"), FN(OnToggleSpectralSelection), wxT("Q")); + c->AddItem(wxT("NextHigherPeakFrequency"), _("Next Higher Peak Frequency"), FN(OnNextHigherPeakFrequency)); + c->AddItem(wxT("NextLowerPeakFrequency"), _("Next Lower Peak Frequency"), FN(OnNextLowerPeakFrequency)); + c->EndSubMenu(); #endif c->AddItem(wxT("SetLeftSelection"), _("&Left at Playback Position"), FN(OnSetLeftSelection), wxT("[")); @@ -4728,6 +4732,39 @@ void AudacityProject::OnToggleSpectralSelection() mTrackPanel->Refresh(false); ModifyState(false); } + +void AudacityProject::DoNextPeakFrequency(bool up) +{ + // Find the first selected wave track that is in a spectrogram view. + WaveTrack *pTrack = 0; + SelectedTrackListOfKindIterator iter(Track::Wave, mTracks); + 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) { + pTrack = wt; + break; + } + } + + if (pTrack) { + mTrackPanel->SnapCenterOnce(pTrack, up); + mTrackPanel->Refresh(false); + ModifyState(false); + } +} + +void AudacityProject::OnNextHigherPeakFrequency() +{ + DoNextPeakFrequency(true); +} + + +void AudacityProject::OnNextLowerPeakFrequency() +{ + DoNextPeakFrequency(false); +} #endif void AudacityProject::OnSelectCursorEnd() diff --git a/src/Menus.h b/src/Menus.h index aae806819..dfecb8d3e 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -245,6 +245,9 @@ void OnSelectAll(); void OnSelectNone(); #ifdef EXPERIMENTAL_SPECTRAL_EDITING void OnToggleSpectralSelection(); +void DoNextPeakFrequency(bool up); +void OnNextHigherPeakFrequency(); +void OnNextLowerPeakFrequency(); #endif void OnSelectCursorEnd(); void OnSelectStartCursor(); diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 451b917aa..3ab8ed021 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -2644,6 +2644,45 @@ inline double findMaxRatio(double center, double rate) } +void TrackPanel::SnapCenterOnce(WaveTrack *pTrack, bool up) +{ + const int windowSize = mTrackArtist->GetSpectrumWindowSize(); + const double rate = pTrack->GetRate(); + const double nyq = rate / 2.0; + const double binFrequency = rate / windowSize; + + double f1 = mViewInfo->selectedRegion.f1(); + double centerFrequency = mViewInfo->selectedRegion.fc(); + if (centerFrequency <= 0) { + centerFrequency = up ? binFrequency : nyq; + f1 = centerFrequency * sqrt(2.0); + } + + const double ratio = f1 / centerFrequency; + const int originalBin = floor(0.5 + centerFrequency / binFrequency); + const int limitingBin = up ? floor(0.5 + nyq / binFrequency) : 1; + + // This is crude and wasteful, doing the FFT each time the command is called. + // It would be better to cache the data, but then invalidation of the cache would + // need doing in all places that change the time selection. + StartSnappingFreqSelection(pTrack); + double snappedFrequency = centerFrequency; + int bin = originalBin; + if (up) { + while (snappedFrequency <= centerFrequency && + bin < limitingBin) + snappedFrequency = mFrequencySnapper->FindPeak(++bin * binFrequency, NULL); + } + else { + while (snappedFrequency >= centerFrequency && + bin > limitingBin) + snappedFrequency = mFrequencySnapper->FindPeak(--bin * binFrequency, NULL); + } + + mViewInfo->selectedRegion.setFrequencies + (snappedFrequency / ratio, snappedFrequency * ratio); +} + void TrackPanel::StartSnappingFreqSelection (WaveTrack *pTrack) { static const sampleCount minLength = 8; diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 102913c91..86b704045 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -328,6 +328,9 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel { double quietSeekStepPositive, double audioSeekStepPositive); #ifdef EXPERIMENTAL_SPECTRAL_EDITING +public: + void SnapCenterOnce (WaveTrack *pTrack, bool up); +protected: void StartSnappingFreqSelection (WaveTrack *pTrack); void MoveSnappingFreqSelection (int mouseYCoordinate, int trackTopEdge,