diff --git a/src/NumberScale.h b/src/NumberScale.h index 653977354..e8529d3e2 100644 --- a/src/NumberScale.h +++ b/src/NumberScale.h @@ -22,7 +22,7 @@ enum NumberScaleType { nstMel, nstBark, nstErb, - nstUndertone, + nstPeriod, nstNumScaleTypes, }; @@ -31,6 +31,10 @@ enum NumberScaleType { class NumberScale { public: + NumberScale() + : mType(nstLinear), mValue0(0), mValue1(1), mUnit(1) + {} + NumberScale(NumberScaleType type, float value0, float value1, float unit) : mType(type) @@ -71,10 +75,10 @@ public: mUnit = unit; } break; - case nstUndertone: + case nstPeriod: { - mValue0 = hzToUndertone(value0); - mValue1 = hzToUndertone(value1); + mValue0 = hzToPeriod(value0); + mValue1 = hzToPeriod(value1); mUnit = unit; } break; @@ -144,12 +148,12 @@ public: return 676170.4 / (47.06538 - exp(0.08950404 * erb)) - 14678.49; } - static inline float hzToUndertone(float hz) + static inline float hzToPeriod(float hz) { return -1.0 / std::max (1.0f, hz); } - static inline float undertoneToHz(float u) + static inline float periodToHz(float u) { return -1.0 / u; } @@ -170,8 +174,8 @@ public: return barkToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; case nstErb: return erbToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; - case nstUndertone: - return undertoneToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; + case nstPeriod: + return periodToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; } } @@ -199,8 +203,8 @@ public: return barkToHz(mValue) / mUnit; case nstErb: return erbToHz(mValue) / mUnit; - case nstUndertone: - return undertoneToHz(mValue) / mUnit; + case nstPeriod: + return periodToHz(mValue) / mUnit; } } @@ -211,7 +215,7 @@ public: case nstMel: case nstBark: case nstErb: - case nstUndertone: + case nstPeriod: mValue += mStep; break; case nstLogarithmic: @@ -239,7 +243,7 @@ public: case nstMel: case nstBark: case nstErb: - case nstUndertone: + case nstPeriod: return Iterator (mType, nPositions == 1 ? 0 : (mValue1 - mValue0) / (nPositions - 1), @@ -268,13 +272,13 @@ public: return ((hzToBark(val * mUnit) - mValue0) / (mValue1 - mValue0)); case nstErb: return ((hzToErb(val * mUnit) - mValue0) / (mValue1 - mValue0)); - case nstUndertone: - return ((hzToUndertone(val * mUnit) - mValue0) / (mValue1 - mValue0)); + case nstPeriod: + return ((hzToPeriod(val * mUnit) - mValue0) / (mValue1 - mValue0)); } } private: - const NumberScaleType mType; + NumberScaleType mType; float mValue0; float mValue1; float mUnit; diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index f42040e51..3b994ea1d 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -831,6 +831,10 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect) } else { wxASSERT(display == WaveTrack::Spectrum); + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + float minFreq, maxFreq; + wt->GetSpectrumBounds(&minFreq, &maxFreq); + switch (wt->GetSpectrogramSettings().scaleType) { default: wxASSERT(false); @@ -841,11 +845,6 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect) 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); - /* draw the ruler we will use Hz if maxFreq is < 2000, otherwise we represent kHz, @@ -872,18 +871,13 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect) case SpectrogramSettings::stMel: case SpectrogramSettings::stBark: case SpectrogramSettings::stErb: - case SpectrogramSettings::stUndertone: + case SpectrogramSettings::stPeriod: { // SpectrumLog 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); - /* draw the ruler we will use Hz if maxFreq is < 2000, otherwise we represent kHz, @@ -897,7 +891,8 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect) vruler->SetUnits(wxT("")); vruler->SetLog(true); NumberScale scale - (wt->GetSpectrogramSettings().GetScale(wt->GetRate(), false).Reversal()); + (wt->GetSpectrogramSettings().GetScale + (minFreq, maxFreq, wt->GetRate(), false).Reversal()); vruler->SetNumberScale(&scale); } break; @@ -2183,16 +2178,12 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, t0, pps); } - // 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 minFreq, maxFreq; + track->GetSpectrumBounds(&minFreq, &maxFreq); - const NumberScale numberScale(settings.GetScale(rate, true)); + const SpectrogramSettings::ScaleType scaleType = settings.scaleType; + + const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, true)); #ifdef EXPERIMENTAL_FFT_Y_GRID const float diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index a99042d38..e07469ce0 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1037,7 +1037,7 @@ AudacityProject * TrackPanel::GetProject() const } /// AS: This gets called on our wx timer events. -void TrackPanel::OnTimer(wxTimerEvent& event) +void TrackPanel::OnTimer(wxTimerEvent& ) { mTimeCount++; // AS: If the user is dragging the mouse and there is a track that @@ -3467,7 +3467,9 @@ double TrackPanel::PositionToFrequency(const WaveTrack *wt, return -1; const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); - const NumberScale numberScale(settings.GetScale(rate, false)); + float minFreq, maxFreq; + wt->GetSpectrumBounds(&minFreq, &maxFreq); + const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, false)); const double p = double(mouseYCoordinate - trackTopEdge) / trackHeight; return numberScale.PositionToValue(1.0 - p); } @@ -3481,7 +3483,9 @@ wxInt64 TrackPanel::FrequencyToPosition(const WaveTrack *wt, const double rate = wt->GetRate(); const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); - const NumberScale numberScale(settings.GetScale(rate, false)); + float minFreq, maxFreq; + wt->GetSpectrumBounds(&minFreq, &maxFreq); + const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, false)); const float p = numberScale.ValueToPosition(frequency); return trackTopEdge + wxInt64((1.0 - p) * trackHeight); } @@ -4612,20 +4616,14 @@ void TrackPanel::HandleWaveTrackVZoom const double rate = track->GetRate(); const float halfrate = rate / 2; const SpectrogramSettings &settings = track->GetSpectrogramSettings(); - NumberScale scale(track->GetSpectrogramSettings().GetScale(rate, false)); + NumberScale scale; const bool spectral = (track->GetDisplay() == WaveTrack::Spectrum); const bool spectrumLinear = spectral && (track->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLinear); if (spectral) { - if (spectrumLinear) { - min = settings.GetMinFreq(rate); - max = settings.GetMaxFreq(rate); - } - else { - min = settings.GetLogMinFreq(rate); - max = settings.GetLogMaxFreq(rate); - } + track->GetSpectrumBounds(&min, &max); + scale = (settings.GetScale(min, max, rate, false)); const int fftLength = settings.GetFFTLength(); const float binSize = rate / fftLength; const int minBins = @@ -4797,28 +4795,9 @@ void TrackPanel::HandleWaveTrackVZoom } if (spectral) { - if (spectrumLinear) { - SpectrogramSettings &settings = track->GetSpectrogramSettings(); - settings.SetMinFreq(min); - settings.SetMaxFreq(max); - if (partner) { - // To do: share memory with reference counting? - SpectrogramSettings &settings = partner->GetSpectrogramSettings(); - settings.SetMinFreq(min); - settings.SetMaxFreq(max); - } - } - else { - SpectrogramSettings &settings = track->GetSpectrogramSettings(); - settings.SetLogMinFreq(min); - settings.SetLogMaxFreq(max); - if (partner) { - // To do: share memory with reference counting? - SpectrogramSettings &settings = partner->GetSpectrogramSettings(); - settings.SetLogMinFreq(min); - settings.SetLogMaxFreq(max); - } - } + track->SetSpectrumBounds(min, max); + if (partner) + partner->SetSpectrumBounds(min, max); } else { track->SetDisplayBounds(min, max); @@ -6287,36 +6266,23 @@ void TrackPanel::HandleWheelRotationInVRuler const float delta = steps * movement / height; SpectrogramSettings &settings = wt->GetIndependentSpectrogramSettings(); const bool isLinear = settings.scaleType == SpectrogramSettings::stLinear; + float bottom, top; + wt->GetSpectrumBounds(&bottom, &top); const double rate = wt->GetRate(); - const float maxFreq = float(rate) / 2.0f; - const NumberScale numberScale(settings.GetScale(rate, false)); + const float bound = rate / 2; + const NumberScale numberScale(settings.GetScale(bottom, top, rate, false)); float newTop = - std::min(maxFreq, numberScale.PositionToValue(1.0f + delta)); + std::min(bound, numberScale.PositionToValue(1.0f + delta)); const float newBottom = std::max((isLinear ? 0.0f : 1.0f), numberScale.PositionToValue(numberScale.ValueToPosition(newTop) - 1.0f)); newTop = - std::min(maxFreq, + std::min(bound, numberScale.PositionToValue(numberScale.ValueToPosition(newBottom) + 1.0f)); - if (isLinear) { - settings.SetMinFreq(newBottom); - settings.SetMaxFreq(newTop); - } - else { - settings.SetLogMinFreq(newBottom); - settings.SetLogMaxFreq(newTop); - } - if (partner) { - SpectrogramSettings &partnerSettings = partner->GetIndependentSpectrogramSettings(); - if (isLinear) { - partnerSettings.SetMinFreq(newBottom); - partnerSettings.SetMaxFreq(newTop); - } - else { - partnerSettings.SetLogMinFreq(newBottom); - partnerSettings.SetLogMaxFreq(newTop); - } - } + + wt->SetSpectrumBounds(newBottom, newTop); + if (partner) + partner->SetSpectrumBounds(newBottom, newTop); } else { float topLimit = 2.0; diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 421800378..62bfc2cc4 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -107,6 +107,7 @@ WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rat SetName(GetDefaultName()); mDisplayMin = -1.0; mDisplayMax = 1.0; + mSpectrumMin = mSpectrumMax = -1; // so values will default to settings mDisplayNumLocations = 0; mDisplayLocations = NULL; mDisplayNumLocationsAllocated = 0; @@ -147,6 +148,8 @@ void WaveTrack::Init(const WaveTrack &orig) mDisplay = orig.mDisplay; mDisplayMin = orig.mDisplayMin; mDisplayMax = orig.mDisplayMax; + mSpectrumMin = orig.mSpectrumMin; + mSpectrumMax = orig.mSpectrumMax; mDisplayNumLocations = 0; mDisplayLocations = NULL; mDisplayNumLocationsAllocated = 0; @@ -297,7 +300,7 @@ void WaveTrack::SetLastdBRange() mLastdBRange = GetWaveformSettings().dBRange; } -void WaveTrack::GetDisplayBounds(float *min, float *max) +void WaveTrack::GetDisplayBounds(float *min, float *max) const { *min = mDisplayMin; *max = mDisplayMax; @@ -309,6 +312,56 @@ void WaveTrack::SetDisplayBounds(float min, float max) mDisplayMax = max; } +void WaveTrack::GetSpectrumBounds(float *min, float *max) const +{ + const double rate = GetRate(); + + const SpectrogramSettings &settings = GetSpectrogramSettings(); + const SpectrogramSettings::ScaleType type = settings.scaleType; + + const float top = (rate / 2.); + + float bottom; + if (type == SpectrogramSettings::stLinear) + bottom = 0.0f; + else if (type == SpectrogramSettings::stPeriod) { + // special case + const int half = settings.GetFFTLength() / 2; + // EAC returns no data for below this frequency: + const float bin2 = rate / half; + bottom = bin2; + } + else + // logarithmic, etc. + bottom = 1.0f; + + { + float spectrumMax = mSpectrumMax; + if (spectrumMax < 0) + spectrumMax = settings.maxFreq; + if (spectrumMax < 0) + *max = top; + else + *max = std::max(bottom, std::min(top, spectrumMax)); + } + + { + float spectrumMin = mSpectrumMin; + if (spectrumMin < 0) + spectrumMin = settings.minFreq; + if (spectrumMin < 0) + *min = std::max(bottom, top / 1000.0f); + else + *min = std::max(bottom, std::min(top, spectrumMin)); + } +} + +void WaveTrack::SetSpectrumBounds(float min, float max) +{ + mSpectrumMin = min; + mSpectrumMax = max; +} + Track *WaveTrack::Duplicate() { return new WaveTrack(*this); diff --git a/src/WaveTrack.h b/src/WaveTrack.h index b545c48c2..b8197cff8 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -441,8 +441,10 @@ class AUDACITY_DLL_API WaveTrack : public Track { WaveTrackDisplay GetDisplay() const { return mDisplay; } void SetDisplay(WaveTrackDisplay display) { mDisplay = display; } - void GetDisplayBounds(float *min, float *max); + void GetDisplayBounds(float *min, float *max) const; void SetDisplayBounds(float min, float max); + void GetSpectrumBounds(float *min, float *max) const; + void SetSpectrumBounds(float min, float max); protected: @@ -464,6 +466,9 @@ class AUDACITY_DLL_API WaveTrack : public Track { // float mDisplayMin; float mDisplayMax; + float mSpectrumMin; + float mSpectrumMax; + WaveTrackDisplay mDisplay; int mLastScaleType; // last scale type choice int mLastdBRange; diff --git a/src/prefs/SpectrogramSettings.cpp b/src/prefs/SpectrogramSettings.cpp index eb729a687..13f3e04ce 100644 --- a/src/prefs/SpectrogramSettings.cpp +++ b/src/prefs/SpectrogramSettings.cpp @@ -68,8 +68,6 @@ SpectrogramSettings::SpectrogramSettings() SpectrogramSettings::SpectrogramSettings(const SpectrogramSettings &other) : minFreq(other.minFreq) , maxFreq(other.maxFreq) - , logMinFreq(other.logMinFreq) - , logMaxFreq(other.logMaxFreq) , range(other.range) , gain(other.gain) , frequencyGain(other.frequencyGain) @@ -107,8 +105,6 @@ SpectrogramSettings &SpectrogramSettings::operator= (const SpectrogramSettings & if (this != &other) { minFreq = other.minFreq; maxFreq = other.maxFreq; - logMinFreq = other.logMinFreq; - logMaxFreq = other.logMaxFreq; range = other.range; gain = other.gain; frequencyGain = other.frequencyGain; @@ -298,20 +294,6 @@ void SpectrogramSettings::LoadPrefs() // 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(); } @@ -501,59 +483,6 @@ void SpectrogramSettings::ConvertToActualWindowSizes() #endif } -int SpectrogramSettings::GetMinFreq(double rate) const -{ - const int top = lrint(rate / 2.); - return std::max(0, std::min(top, minFreq)); -} - -int SpectrogramSettings::GetMaxFreq(double rate) const -{ - const int top = lrint(rate / 2.); - if (maxFreq < 0) - return top; - else - return std::max(0, std::min(top, maxFreq)); -} - -int SpectrogramSettings::GetLogMinFreq(double rate) const -{ - const int top = lrint(rate / 2.); - if (logMinFreq < 0) - return top / 1000.0; - else - return std::max(1, std::min(top, logMinFreq)); -} - -int SpectrogramSettings::GetLogMaxFreq(double rate) const -{ - const int top = lrint(rate / 2.); - if (logMaxFreq < 0) - return top; - else - return std::max(1, std::min(top, logMaxFreq)); -} - -void SpectrogramSettings::SetMinFreq(int freq) -{ - minFreq = freq; -} - -void SpectrogramSettings::SetMaxFreq(int freq) -{ - maxFreq = freq; -} - -void SpectrogramSettings::SetLogMinFreq(int freq) -{ - logMinFreq = freq; -} - -void SpectrogramSettings::SetLogMaxFreq(int freq) -{ - logMaxFreq = freq; -} - int SpectrogramSettings::GetFFTLength() const { return windowSize @@ -564,9 +493,8 @@ int SpectrogramSettings::GetFFTLength() const } NumberScale SpectrogramSettings::GetScale -(double rate, bool bins) const +(float minFreq, float maxFreq, double rate, bool bins) const { - int minFreq, maxFreq; NumberScaleType type = nstLinear; const int half = GetFFTLength() / 2; @@ -585,31 +513,8 @@ NumberScale SpectrogramSettings::GetScale type = nstBark; break; case stErb: type = nstErb; break; - case stUndertone: - type = nstUndertone; break; - } - - switch (scaleType) { - default: - wxASSERT(false); - case stLinear: - minFreq = GetMinFreq(rate); - maxFreq = GetMaxFreq(rate); - break; - case stLogarithmic: - case stMel: - case stBark: - case stErb: - minFreq = GetLogMinFreq(rate); - maxFreq = GetLogMaxFreq(rate); - break; - case stUndertone: - { - const float bin2 = rate / half; - minFreq = std::max(int(0.5 + bin2), GetLogMinFreq(rate)); - maxFreq = GetLogMaxFreq(rate); - } - break; + case stPeriod: + type = nstPeriod; break; } return NumberScale(type, minFreq, maxFreq, diff --git a/src/prefs/SpectrogramSettings.h b/src/prefs/SpectrogramSettings.h index cdc13329b..d5a66eaf0 100644 --- a/src/prefs/SpectrogramSettings.h +++ b/src/prefs/SpectrogramSettings.h @@ -57,7 +57,7 @@ public: stMel, stBark, stErb, - stUndertone, + stPeriod, stNumScaleTypes, }; @@ -87,24 +87,12 @@ public: // If "bins" is false, units are Hz NumberScale GetScale - (double rate, bool bins) const; + (float minFreq, float maxFreq, double rate, bool bins) const; -private: int minFreq; int maxFreq; - int logMinFreq; - int logMaxFreq; -public: - int GetMinFreq(double rate) const; - 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); - void SetLogMinFreq(int freq); - void SetLogMaxFreq(int freq); + bool SpectralSelectionEnabled() const; public: int range; diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index b6a4683b4..0b0273d9c 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -376,8 +376,12 @@ bool SpectrumPrefs::Apply() if (mWt) { if (mDefaulted) { mWt->SetSpectrogramSettings(NULL); - if (partner) + // ... and so that the vertical scale also defaults: + mWt->SetSpectrumBounds(-1, -1); + if (partner) { partner->SetSpectrogramSettings(NULL); + partner->SetSpectrumBounds(-1, -1); + } } else { SpectrogramSettings *pSettings =