mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-31 16:09:28 +02:00
Other spectrogram scales, easily defined!! -- and include bug fixes 1038, 1039
This commit is contained in:
parent
9b9ceab6ab
commit
846c5d454e
@ -19,6 +19,10 @@ Paul Licameli
|
||||
enum NumberScaleType {
|
||||
nstLinear,
|
||||
nstLogarithmic,
|
||||
nstMel,
|
||||
nstBark,
|
||||
nstErb,
|
||||
nstUndertone,
|
||||
|
||||
nstNumScaleTypes,
|
||||
};
|
||||
@ -46,6 +50,34 @@ public:
|
||||
mUnit = 1.0;
|
||||
}
|
||||
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 nstUndertone:
|
||||
{
|
||||
mValue0 = hzToUndertone(value0);
|
||||
mValue1 = hzToUndertone(value1);
|
||||
mUnit = unit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
wxASSERT(false);
|
||||
}
|
||||
@ -71,6 +103,57 @@ public:
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
static inline float hzToMel(float hz)
|
||||
{
|
||||
return 1127 * log(1 + hz / 700);
|
||||
}
|
||||
|
||||
static inline float melToHz(float mel)
|
||||
{
|
||||
return 700 * (exp(mel / 1127) - 1);
|
||||
}
|
||||
|
||||
static inline float hzToBark(float hz)
|
||||
{
|
||||
// Traunmueller's formula
|
||||
const float z1 = 26.81 * hz / (1960 + hz) - 0.53;
|
||||
if (z1 < 2.0)
|
||||
return z1 + 0.15 * (2.0 - z1);
|
||||
else if (z1 > 20.1)
|
||||
return z1 + 0.22 * (z1 - 20.1);
|
||||
else
|
||||
return z1;
|
||||
}
|
||||
|
||||
static inline float barkToHz(float z1)
|
||||
{
|
||||
if (z1 < 2.0)
|
||||
z1 = 2.0 + (z1 - 2.0) / 0.85;
|
||||
else if (z1 > 20.1)
|
||||
z1 = 20.1 + (z1 - 20.1) / 1.22;
|
||||
return 1960 * (z1 + 0.53) / (26.28 - z1);
|
||||
}
|
||||
|
||||
static inline float hzToErb(float hz)
|
||||
{
|
||||
return 11.17268 * log(1 + (46.06538 * hz) / (hz + 14678.49));
|
||||
}
|
||||
|
||||
static inline float erbToHz(float erb)
|
||||
{
|
||||
return 676170.4 / (47.06538 - exp(0.08950404 * erb)) - 14678.49;
|
||||
}
|
||||
|
||||
static inline float hzToUndertone(float hz)
|
||||
{
|
||||
return -1.0 / std::max (1.0f, hz);
|
||||
}
|
||||
|
||||
static inline float undertoneToHz(float u)
|
||||
{
|
||||
return -1.0 / u;
|
||||
}
|
||||
|
||||
// Random access
|
||||
float PositionToValue(float pp) const
|
||||
{
|
||||
@ -81,6 +164,14 @@ public:
|
||||
return mValue0 + pp * (mValue1 - mValue0);
|
||||
case nstLogarithmic:
|
||||
return exp(mValue0 + pp * (mValue1 - mValue0));
|
||||
case nstMel:
|
||||
return melToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit;
|
||||
case nstBark:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +193,14 @@ public:
|
||||
case nstLinear:
|
||||
case nstLogarithmic:
|
||||
return mValue;
|
||||
case nstMel:
|
||||
return melToHz(mValue) / mUnit;
|
||||
case nstBark:
|
||||
return barkToHz(mValue) / mUnit;
|
||||
case nstErb:
|
||||
return erbToHz(mValue) / mUnit;
|
||||
case nstUndertone:
|
||||
return undertoneToHz(mValue) / mUnit;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +208,10 @@ public:
|
||||
{
|
||||
switch (mType) {
|
||||
case nstLinear:
|
||||
case nstMel:
|
||||
case nstBark:
|
||||
case nstErb:
|
||||
case nstUndertone:
|
||||
mValue += mStep;
|
||||
break;
|
||||
case nstLogarithmic:
|
||||
@ -133,6 +236,10 @@ public:
|
||||
default:
|
||||
wxASSERT(false);
|
||||
case nstLinear:
|
||||
case nstMel:
|
||||
case nstBark:
|
||||
case nstErb:
|
||||
case nstUndertone:
|
||||
return Iterator
|
||||
(mType, (mValue1 - mValue0) / nPositions, mValue0, mUnit);
|
||||
case nstLogarithmic:
|
||||
@ -151,6 +258,14 @@ public:
|
||||
return ((val - mValue0) / (mValue1 - mValue0));
|
||||
case nstLogarithmic:
|
||||
return ((log(val) - mValue0) / (mValue1 - mValue0));
|
||||
case nstMel:
|
||||
return ((hzToMel(val * mUnit) - mValue0) / (mValue1 - mValue0));
|
||||
case nstBark:
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,6 +830,10 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect)
|
||||
}
|
||||
break;
|
||||
case SpectrogramSettings::stLogarithmic:
|
||||
case SpectrogramSettings::stMel:
|
||||
case SpectrogramSettings::stBark:
|
||||
case SpectrogramSettings::stErb:
|
||||
case SpectrogramSettings::stUndertone:
|
||||
{
|
||||
// SpectrumLog
|
||||
|
||||
|
@ -161,6 +161,10 @@ const wxArrayString &SpectrogramSettings::GetScaleNames()
|
||||
// Keep in correspondence with enum SpectrogramSettings::ScaleType:
|
||||
theArray.Add(_("Linear"));
|
||||
theArray.Add(_("Logarithmic"));
|
||||
theArray.Add(_("Mel"));
|
||||
theArray.Add(_("Bark"));
|
||||
theArray.Add(_("Erb"));
|
||||
theArray.Add(_("Undertone"));
|
||||
}
|
||||
|
||||
return theArray;
|
||||
@ -529,6 +533,7 @@ NumberScale SpectrogramSettings::GetScale
|
||||
{
|
||||
int minFreq, maxFreq;
|
||||
NumberScaleType type = nstLinear;
|
||||
const int half = GetFFTLength(autocorrelation) / 2;
|
||||
|
||||
// Don't assume the correspondence of the enums will remain direct in the future.
|
||||
// Do this switch.
|
||||
@ -539,6 +544,14 @@ NumberScale SpectrogramSettings::GetScale
|
||||
type = nstLinear; break;
|
||||
case stLogarithmic:
|
||||
type = nstLogarithmic; break;
|
||||
case stMel:
|
||||
type = nstMel; break;
|
||||
case stBark:
|
||||
type = nstBark; break;
|
||||
case stErb:
|
||||
type = nstErb; break;
|
||||
case stUndertone:
|
||||
type = nstUndertone; break;
|
||||
}
|
||||
|
||||
switch (scaleType) {
|
||||
@ -549,12 +562,20 @@ NumberScale SpectrogramSettings::GetScale
|
||||
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;
|
||||
}
|
||||
|
||||
const int half = GetFFTLength(autocorrelation) / 2;
|
||||
|
||||
return NumberScale(type, minFreq, maxFreq,
|
||||
bins ? rate / (2 * half) : 1.0f);
|
||||
|
@ -54,6 +54,10 @@ public:
|
||||
enum ScaleType {
|
||||
stLinear,
|
||||
stLogarithmic,
|
||||
stMel,
|
||||
stBark,
|
||||
stErb,
|
||||
stUndertone,
|
||||
|
||||
stNumScaleTypes,
|
||||
};
|
||||
|
@ -1192,7 +1192,7 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
|
||||
: NumberScale(nstLogarithmic, mMin, mMax, 1.0f)
|
||||
);
|
||||
|
||||
mDigits=2; //TODO: implement dynamic digit computation
|
||||
mDigits=2; //TODO: implement dynamic digit computation
|
||||
double loLog = log10(mMin);
|
||||
double hiLog = log10(mMax);
|
||||
int loDecade = (int) floor(loLog);
|
||||
@ -1208,7 +1208,7 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
|
||||
for(i=0; i<=steps; i++)
|
||||
{ // if(i!=0)
|
||||
{ val = decade;
|
||||
if(val > rMin && val < rMax) {
|
||||
if(val >= rMin && val < rMax) {
|
||||
const int pos(0.5 + mLength * numberScale.ValueToPosition(val));
|
||||
Tick(pos, val, true, false);
|
||||
}
|
||||
@ -1244,13 +1244,16 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
|
||||
{ start=100; end= 10; mstep=-1;
|
||||
}
|
||||
steps++;
|
||||
for(i=0; i<=steps; i++) {
|
||||
for(int f=start; f!=int(end); f+=mstep) {
|
||||
if (int(f/10)!=f/10.0f) {
|
||||
val = decade * f/10;
|
||||
if(val >= rMin && val < rMax) {
|
||||
const int pos(0.5 + mLength * numberScale.ValueToPosition(val));
|
||||
Tick(pos, val, false, false);
|
||||
for (i = 0; i <= steps; i++) {
|
||||
// PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2"
|
||||
if (!(mFormat == IntFormat && decade < 10.0)) {
|
||||
for (int f = start; f != int(end); f += mstep) {
|
||||
if (int(f / 10) != f / 10.0f) {
|
||||
val = decade * f / 10;
|
||||
if (val >= rMin && val < rMax) {
|
||||
const int pos(0.5 + mLength * numberScale.ValueToPosition(val));
|
||||
Tick(pos, val, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user