simplify SpectrogramSettings::GetScale; abstract frequency-to-bin...

... this is a preparation for the constant-q feature, if we want it.
This commit is contained in:
Paul Licameli 2017-02-10 13:56:31 -05:00
parent a4a9df5c03
commit d831318132
6 changed files with 57 additions and 55 deletions

View File

@ -32,54 +32,47 @@ class NumberScale
{
public:
NumberScale()
: mType(nstLinear), mValue0(0), mValue1(1), mUnit(1)
: mType(nstLinear), mValue0(0), mValue1(1)
{}
NumberScale(NumberScaleType type,
float value0, float value1, float unit)
NumberScale(NumberScaleType type, float value0, float value1)
: mType(type)
{
switch (mType) {
case nstLinear:
{
mValue0 = value0 / unit;
mValue1 = value1 / unit;
mUnit = 1.0;
mValue0 = value0;
mValue1 = value1;
}
break;
case nstLogarithmic:
{
mValue0 = logf(value0 / unit);
mValue1 = logf(value1 / unit);
mUnit = 1.0;
mValue0 = logf(value0);
mValue1 = logf(value1);
}
break;
case nstMel:
{
mValue0 = hzToMel(value0);
mValue1 = hzToMel(value1);
mUnit = unit;
}
break;
case nstBark:
{
mValue0 = hzToBark(value0);
mValue1 = hzToBark(value1);
mUnit = unit;
}
break;
case nstErb:
{
mValue0 = hzToErb(value0);
mValue1 = hzToErb(value1);
mUnit = unit;
}
break;
case nstPeriod:
{
mValue0 = hzToPeriod(value0);
mValue1 = hzToPeriod(value1);
mUnit = unit;
}
break;
default:
@ -98,8 +91,7 @@ public:
{
return mType == other.mType
&& mValue0 == other.mValue0
&& mValue1 == other.mValue1
&& mUnit == other.mUnit;
&& mValue1 == other.mValue1;
}
bool operator != (const NumberScale &other) const
@ -169,13 +161,13 @@ public:
case nstLogarithmic:
return exp(mValue0 + pp * (mValue1 - mValue0));
case nstMel:
return melToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit;
return melToHz(mValue0 + pp * (mValue1 - mValue0));
case nstBark:
return barkToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit;
return barkToHz(mValue0 + pp * (mValue1 - mValue0));
case nstErb:
return erbToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit;
return erbToHz(mValue0 + pp * (mValue1 - mValue0));
case nstPeriod:
return periodToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit;
return periodToHz(mValue0 + pp * (mValue1 - mValue0));
}
}
@ -184,8 +176,8 @@ public:
class Iterator
{
public:
Iterator(NumberScaleType type, float step, float value, float unit)
: mType(type), mStep(step), mValue(value), mUnit(unit)
Iterator(NumberScaleType type, float step, float value)
: mType(type), mStep(step), mValue(value)
{
}
@ -198,13 +190,13 @@ public:
case nstLogarithmic:
return mValue;
case nstMel:
return melToHz(mValue) / mUnit;
return melToHz(mValue);
case nstBark:
return barkToHz(mValue) / mUnit;
return barkToHz(mValue);
case nstErb:
return erbToHz(mValue) / mUnit;
return erbToHz(mValue);
case nstPeriod:
return periodToHz(mValue) / mUnit;
return periodToHz(mValue);
}
}
@ -231,7 +223,6 @@ public:
const NumberScaleType mType;
const float mStep;
float mValue;
float mUnit;
};
Iterator begin(float nPositions) const
@ -247,12 +238,12 @@ public:
return Iterator
(mType,
nPositions == 1 ? 0 : (mValue1 - mValue0) / (nPositions - 1),
mValue0, mUnit);
mValue0);
case nstLogarithmic:
return Iterator
(mType,
nPositions == 1 ? 1 : exp((mValue1 - mValue0) / (nPositions - 1)),
exp(mValue0), mUnit);
exp(mValue0));
}
}
@ -267,13 +258,13 @@ public:
case nstLogarithmic:
return ((log(val) - mValue0) / (mValue1 - mValue0));
case nstMel:
return ((hzToMel(val * mUnit) - mValue0) / (mValue1 - mValue0));
return ((hzToMel(val) - mValue0) / (mValue1 - mValue0));
case nstBark:
return ((hzToBark(val * mUnit) - mValue0) / (mValue1 - mValue0));
return ((hzToBark(val) - mValue0) / (mValue1 - mValue0));
case nstErb:
return ((hzToErb(val * mUnit) - mValue0) / (mValue1 - mValue0));
return ((hzToErb(val) - mValue0) / (mValue1 - mValue0));
case nstPeriod:
return ((hzToPeriod(val * mUnit) - mValue0) / (mValue1 - mValue0));
return ((hzToPeriod(val) - mValue0) / (mValue1 - mValue0));
}
}
@ -281,7 +272,6 @@ private:
NumberScaleType mType;
float mValue0;
float mValue1;
float mUnit;
};
#endif

View File

@ -893,9 +893,9 @@ void TrackArtist::UpdateVRuler(const Track *t, wxRect & rect)
vruler->SetRange(maxFreq, minFreq);
vruler->SetUnits(wxT(""));
vruler->SetLog(true);
NumberScale scale
(wt->GetSpectrogramSettings().GetScale
(minFreq, maxFreq, wt->GetRate(), false).Reversal());
NumberScale scale(
wt->GetSpectrogramSettings().GetScale( minFreq, maxFreq )
.Reversal() );
vruler->SetNumberScale(&scale);
}
break;
@ -2194,15 +2194,17 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
// the desired fft bin(s) for display on that row
float *bins = (float*)alloca(sizeof(*bins)*(hiddenMid.height + 1));
{
const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, true));
const NumberScale numberScale( settings.GetScale( minFreq, maxFreq ) );
NumberScale::Iterator it = numberScale.begin(mid.height);
float nextBin = std::max(0.0f, std::min(float(half - 1), *it));
float nextBin = std::max( 0.0f, std::min( float(half - 1),
settings.findBin( *it, binUnit ) ) );
int yy;
for (yy = 0; yy < hiddenMid.height; ++yy) {
bins[yy] = nextBin;
nextBin = std::max(0.0f, std::min(float(half - 1), *++it));
nextBin = std::max( 0.0f, std::min( float(half - 1),
settings.findBin( *++it, binUnit ) ) );
}
bins[yy] = nextBin;
}
@ -2407,10 +2409,11 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
} // each xx
} // updating cache
float selBinLo = freqLo / binUnit;
float selBinHi = freqHi / binUnit;
float selBinCenter =
((freqLo < 0 || freqHi < 0) ? -1 : sqrt(freqLo * freqHi)) / binUnit;
float selBinLo = settings.findBin( freqLo, binUnit);
float selBinHi = settings.findBin( freqHi, binUnit);
float selBinCenter = (freqLo < 0 || freqHi < 0)
? -1
: settings.findBin( sqrt(freqLo * freqHi), binUnit );
const bool isSpectral = settings.SpectralSelectionEnabled();
const bool hidden = (ZoomInfo::HIDDEN == zoomInfo.GetFisheyeState());

View File

@ -2988,7 +2988,7 @@ double TrackPanel::PositionToFrequency(const WaveTrack *wt,
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
float minFreq, maxFreq;
wt->GetSpectrumBounds(&minFreq, &maxFreq);
const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, false));
const NumberScale numberScale( settings.GetScale( minFreq, maxFreq ) );
const double p = double(mouseYCoordinate - trackTopEdge) / trackHeight;
return numberScale.PositionToValue(1.0 - p);
}
@ -3004,7 +3004,7 @@ wxInt64 TrackPanel::FrequencyToPosition(const WaveTrack *wt,
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
float minFreq, maxFreq;
wt->GetSpectrumBounds(&minFreq, &maxFreq);
const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, false));
const NumberScale numberScale( settings.GetScale( minFreq, maxFreq ) );
const float p = numberScale.ValueToPosition(frequency);
return trackTopEdge + wxInt64((1.0 - p) * trackHeight);
}
@ -4232,7 +4232,7 @@ void TrackPanel::HandleWaveTrackVZoom
if (spectral) {
track->GetSpectrumBounds(&min, &max);
scale = (settings.GetScale(min, max, rate, false));
scale = settings.GetScale( min, max );
const auto fftLength = settings.GetFFTLength();
const float binSize = rate / fftLength;
@ -5865,7 +5865,7 @@ void TrackPanel::HandleWheelRotationInVRuler
wt->GetSpectrumBounds(&bottom, &top);
const double rate = wt->GetRate();
const float bound = rate / 2;
const NumberScale numberScale(settings.GetScale(bottom, top, rate, false));
const NumberScale numberScale( settings.GetScale( bottom, top ) );
float newTop =
std::min(bound, numberScale.PositionToValue(1.0f + delta));
const float newBottom =

View File

@ -475,6 +475,15 @@ void SpectrogramSettings::ConvertToActualWindowSizes()
#endif
}
float SpectrogramSettings::findBin( float frequency, float binUnit ) const
{
float linearBin = frequency / binUnit;
if (linearBin < 0)
return -1;
else
return linearBin;
}
size_t SpectrogramSettings::GetFFTLength() const
{
return windowSize
@ -484,11 +493,9 @@ size_t SpectrogramSettings::GetFFTLength() const
;
}
NumberScale SpectrogramSettings::GetScale
(float minFreq, float maxFreq, double rate, bool bins) const
NumberScale SpectrogramSettings::GetScale( float minFreq, float maxFreq ) const
{
NumberScaleType type = nstLinear;
const auto half = GetFFTLength() / 2;
// Don't assume the correspondence of the enums will remain direct in the future.
// Do this switch.
@ -509,8 +516,7 @@ NumberScale SpectrogramSettings::GetScale
type = nstPeriod; break;
}
return NumberScale(type, minFreq, maxFreq,
bins ? rate / (2 * half) : 1.0f);
return NumberScale(type, minFreq, maxFreq);
}
bool SpectrogramSettings::SpectralSelectionEnabled() const

View File

@ -85,9 +85,12 @@ public:
void ConvertToEnumeratedWindowSizes();
void ConvertToActualWindowSizes();
// Need to be told what the bin unit is, as this structure does not know
// the rate
float findBin( float frequency, float binUnit ) const;
// If "bins" is false, units are Hz
NumberScale GetScale
(float minFreq, float maxFreq, double rate, bool bins) const;
NumberScale GetScale( float minFreq, float maxFreq ) const;
int minFreq;
int maxFreq;

View File

@ -1183,7 +1183,7 @@ void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpe
NumberScale numberScale(mpNumberScale
? *mpNumberScale
: NumberScale(nstLogarithmic, mMin, mMax, 1.0f)
: NumberScale(nstLogarithmic, mMin, mMax)
);
mDigits=2; //TODO: implement dynamic digit computation