Fix some assert error in EQ curves

Selected EQ curves in Draw mode should now retain their name
when they are selected.
This commit is contained in:
Steve Daulton 2016-03-08 21:38:13 +00:00
parent a856d1e3b0
commit 7d5e54e364
2 changed files with 146 additions and 68 deletions

View File

@ -517,6 +517,14 @@ bool EffectEqualization::Init()
}
mHiFreq = rate / 2.0;
// Unlikely, but better than crashing.
if (mHiFreq <= loFreqI) {
wxMessageBox( _("Track sample rate is too low for this effect."),
_("Effect Unavailable"),
wxOK | wxCENTRE);
return(false);
}
mLoFreq = loFreqI;
mBandsInUse = 0;
@ -1654,84 +1662,146 @@ void EffectEqualization::SaveCurves(const wxString &fileName)
void EffectEqualization::setCurve(int currentCurve)
{
// Set current choice
Select( currentCurve );
Select(currentCurve);
wxASSERT( currentCurve < (int) mCurves.GetCount() );
bool changed = false;
if( mLin ) // linear freq mode?
{
Envelope *env = mLinEnvelope;
env->Flatten(0.);
env->SetTrackLen(1.0);
Envelope *env;
int numPoints = (int) mCurves[currentCurve].points.GetCount();
if( mCurves[currentCurve].points.GetCount() )
{
double when, value;
int i;
int nCurvePoints = mCurves[currentCurve].points.GetCount();
for(i=0;i<nCurvePoints;i++)
{
when = mCurves[currentCurve].points[i].Freq / mHiFreq;
value = mCurves[currentCurve].points[i].dB;
if(when <= 1)
env->Insert(when, value);
else
break;
}
if ( i != nCurvePoints) // there are more points at higher freqs
{
when = 1.; // set the RH end to the next highest point
value = mCurves[currentCurve].points[nCurvePoints-1].dB;
env->Insert(when, value);
changed = true;
}
}
if (mLin) { // linear freq mode
env = mLinEnvelope;
}
else
{
Envelope *env = mLogEnvelope;
env->Flatten(0.);
env->SetTrackLen(1.0);
else { // log freq mode
env = mLogEnvelope;
}
env->Flatten(0.);
env->SetTrackLen(1.0);
if( mCurves[currentCurve].points.GetCount() )
{
double when, value;
double loLog = log10(20.);
// Handle special case of no points.
if (numPoints == 0) {
ForceRecalc();
return;
}
double when, value;
// Handle special case 1 point.
if (numPoints == 1) {
// only one point, so ensure it is in range then return.
when = mCurves[currentCurve].points[0].Freq;
if (mLin) {
when = when / mHiFreq;
}
else { // log scale
// We don't go below loFreqI (20 Hz) in log view.
double loLog = log10((double)loFreqI);
double hiLog = log10(mHiFreq);
double denom = hiLog - loLog;
int i;
int nCurvePoints = mCurves[currentCurve].points.GetCount();
when = (log10(std::max((double) loFreqI, when)) - loLog)/denom;
}
value = mCurves[currentCurve].points[0].dB;
env->Insert(std::min(1.0, std::max(0.0, when)), value);
ForceRecalc();
return;
}
for(i=0;i<nCurvePoints;i++)
{
double flog = log10(mCurves[currentCurve].points[i].Freq);
if( flog >= loLog )
{
when = (flog - loLog)/denom;
value = mCurves[currentCurve].points[i].dB;
if(when <= 1.)
env->Insert(when, value);
else
{ // we have a point beyond fs/2. Insert it so that env code can use it.
// but just this one, we have no use for the rest
env->SetTrackLen(when); // can't Insert if the envelope isn't long enough
env->Insert(when, value);
break;
}
}
else
{ //get the first point as close as we can to the last point requested
changed = true;
//double f = mCurves[currentCurve].points[i].Freq;
//double v = mCurves[currentCurve].points[i].dB;
mLogEnvelope->Insert(0., mCurves[currentCurve].points[i].dB);
}
// We have at least two points, so ensure they are in frequency order.
mCurves[currentCurve].points.Sort(SortCurvePoints);
if (mCurves[currentCurve].points[0].Freq < 0) {
// Corrupt or invalid curve, so bail.
ForceRecalc();
return;
}
if(mLin) { // linear Hz scale
for(int pointCount = 0; pointCount < numPoints; pointCount++) {
when = mCurves[currentCurve].points[pointCount].Freq / mHiFreq;
value = mCurves[currentCurve].points[pointCount].dB;
if(when <= 1) {
env->Insert(when, value);
}
else {
// There are more points at higher freqs, so interpolate next one then stop.
when = 1.0;
double lastF = mCurves[currentCurve].points[pointCount-1].Freq;
double nextF = mCurves[currentCurve].points[pointCount].Freq;
double lastDB = mCurves[currentCurve].points[pointCount-1].dB;
double nextDB = mCurves[currentCurve].points[pointCount].dB;
value = lastDB + ((nextDB - lastDB) * ((mHiFreq - lastF) / (nextF - lastF)));
env->Insert(when, value);
break;
}
}
}
else { // log Hz scale
double loLog = log10((double) loFreqI);
double hiLog = log10(mHiFreq);
double denom = hiLog - loLog;
int firstAbove20Hz;
// log scale EQ starts at 20 Hz (threshold of hearing).
// so find the first point (if any) above 20 Hz.
for (firstAbove20Hz = 0; firstAbove20Hz < numPoints; firstAbove20Hz++) {
if (mCurves[currentCurve].points[firstAbove20Hz].Freq > loFreqI)
break;
}
if (firstAbove20Hz == numPoints) {
// All points below 20 Hz, so just use final point.
when = 0.0;
value = mCurves[currentCurve].points[numPoints-1].dB;
env->Insert(when, value);
ForceRecalc();
return;
}
if (firstAbove20Hz > 0) {
// At least one point is before 20 Hz and there are more
// beyond 20 Hz, so interpolate the first
double prevF = mCurves[currentCurve].points[firstAbove20Hz-1].Freq;
prevF = log10(std::max(1.0, prevF)); // log zero is bad.
double prevDB = mCurves[currentCurve].points[firstAbove20Hz-1].dB;
double nextF = log10(mCurves[currentCurve].points[firstAbove20Hz].Freq);
double nextDB = mCurves[currentCurve].points[firstAbove20Hz].dB;
when = 0.0;
value = nextDB - ((nextDB - prevDB) * ((nextF - loLog) / (nextF - prevF)));
env->Insert(when, value);
}
// Now get the rest.
for(int pointCount = firstAbove20Hz; pointCount < numPoints; pointCount++)
{
double flog = log10(mCurves[currentCurve].points[pointCount].Freq);
wxASSERT(mCurves[currentCurve].points[pointCount].Freq >= loFreqI);
when = (flog - loLog)/denom;
value = mCurves[currentCurve].points[pointCount].dB;
if(when <= 1.0) {
env->Insert(when, value);
}
else {
// This looks weird when adjusting curve in Draw mode if
// there is a point off-screen.
/*
// we have a point beyond fs/2. Insert it so that env code can use it.
// but just this one, we have no use for the rest
env->SetTrackLen(when); // can't Insert if the envelope isn't long enough
env->Insert(when, value);
break;
*/
// interpolate the final point instead
when = 1.0;
double logLastF = log10(mCurves[currentCurve].points[pointCount-1].Freq);
double lastDB = mCurves[currentCurve].points[pointCount-1].dB;
value = lastDB + ((value - lastDB) * ((log10(mHiFreq) - logLastF) / (flog - logLastF)));
env->Insert(when, value);
break;
}
}
}
if(changed) // not all points were loaded so switch to unnamed
EnvelopeUpdated();
ForceRecalc();
}
@ -2272,7 +2342,10 @@ void EffectEqualization::EnvLinToLog(void)
{
if( when[i]*mHiFreq >= 20 )
{
mLogEnvelope->Insert((log10(when[i]*mHiFreq)-loLog)/denom , value[i]);
// Caution: on Linux, when when == 20, the log calulation rounds
// to just under zero, which causes an assert error.
double flog = (log10(when[i]*mHiFreq)-loLog)/denom;
mLogEnvelope->Insert(std::max(0.0, flog) , value[i]);
}
else
{ //get the first point as close as we can to the last point requested

View File

@ -266,6 +266,11 @@ private:
return (*first)->Name.CmpNoCase((*second)->Name);
}
static int wxCMPFUNC_CONV SortCurvePoints (EQPoint **p0, EQPoint **p1)
{
return (*p0)->Freq > (*p1)->Freq;
}
#ifdef EXPERIMENTAL_EQ_SSE_THREADED
wxRadioButton *mMathProcessingType[5]; // default, sse, sse threaded, AVX, AVX threaded (note AVX is not implemented yet
wxBoxSizer *szrM;