mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-17 16:40:07 +02:00
Fix for bug 930.
Calculate with doubles rather than float. Simplify calculation of max/min peak. Slight hack to work around limitation in FloatingPointValidator. Allow 'close equality' in CheckClip(). Tested on Debian 8 and Release build on Ubuntu 14.10.
This commit is contained in:
parent
9568f97054
commit
4d0c7cd97b
@ -30,12 +30,15 @@
|
|||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/valtext.h>
|
#include <wx/valtext.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
|
||||||
#include "../WaveTrack.h"
|
#include "../WaveTrack.h"
|
||||||
#include "../widgets/valnum.h"
|
#include "../widgets/valnum.h"
|
||||||
|
|
||||||
#include "Amplify.h"
|
#include "Amplify.h"
|
||||||
|
|
||||||
|
#define EPSILON 0.000000000001 // allow for imprecise equality comparisons.
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ID_Amp = 10000,
|
ID_Amp = 10000,
|
||||||
@ -63,9 +66,9 @@ END_EVENT_TABLE()
|
|||||||
EffectAmplify::EffectAmplify()
|
EffectAmplify::EffectAmplify()
|
||||||
{
|
{
|
||||||
mAmp = DEF_Amp;
|
mAmp = DEF_Amp;
|
||||||
mRatio = powf(10.0f, mAmp / 20.0f);
|
mRatio = pow(10.0, mAmp / 20.0);
|
||||||
mCanClip = false;
|
mCanClip = false;
|
||||||
mPeak = 0.0f;
|
mPeak = 0.0;
|
||||||
|
|
||||||
SetLinearEffectFlag(true);
|
SetLinearEffectFlag(true);
|
||||||
}
|
}
|
||||||
@ -136,7 +139,7 @@ bool EffectAmplify::SetAutomationParameters(EffectAutomationParameters & parms)
|
|||||||
|
|
||||||
bool EffectAmplify::Init()
|
bool EffectAmplify::Init()
|
||||||
{
|
{
|
||||||
mPeak = 0.0f;
|
mPeak = 0.0;
|
||||||
|
|
||||||
SelectedTrackListOfKindIterator iter(Track::Wave, mTracks);
|
SelectedTrackListOfKindIterator iter(Track::Wave, mTracks);
|
||||||
|
|
||||||
@ -157,8 +160,8 @@ bool EffectAmplify::Init()
|
|||||||
|
|
||||||
void EffectAmplify::Preview(bool dryOnly)
|
void EffectAmplify::Preview(bool dryOnly)
|
||||||
{
|
{
|
||||||
float ratio = mRatio;
|
double ratio = mRatio;
|
||||||
float peak = mPeak;
|
double peak = mPeak;
|
||||||
|
|
||||||
Effect::Preview(dryOnly);
|
Effect::Preview(dryOnly);
|
||||||
|
|
||||||
@ -170,13 +173,13 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S)
|
|||||||
{
|
{
|
||||||
if (IsBatchProcessing())
|
if (IsBatchProcessing())
|
||||||
{
|
{
|
||||||
mPeak = 1.0f;
|
mPeak = 1.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mPeak > 0.0)
|
if (mPeak > 0.0)
|
||||||
{
|
{
|
||||||
mRatio = 1.0f / mPeak;
|
mRatio = 1.0 / mPeak;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -191,7 +194,7 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S)
|
|||||||
// Amplitude
|
// Amplitude
|
||||||
S.StartMultiColumn(2, wxCENTER);
|
S.StartMultiColumn(2, wxCENTER);
|
||||||
{
|
{
|
||||||
FloatingPointValidator<float> vldAmp(1, &mAmp);
|
FloatingPointValidator<double> vldAmp(2, &mAmp);
|
||||||
vldAmp.SetRange(MIN_Amp, MAX_Amp);
|
vldAmp.SetRange(MIN_Amp, MAX_Amp);
|
||||||
mAmpT = S.Id(ID_Amp).AddTextBox(_("Amplification (dB):"), wxT(""), 12);
|
mAmpT = S.Id(ID_Amp).AddTextBox(_("Amplification (dB):"), wxT(""), 12);
|
||||||
mAmpT->SetValidator(vldAmp);
|
mAmpT->SetValidator(vldAmp);
|
||||||
@ -207,12 +210,19 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S)
|
|||||||
}
|
}
|
||||||
S.EndHorizontalLay();
|
S.EndHorizontalLay();
|
||||||
|
|
||||||
// Peek
|
// Peak
|
||||||
S.StartMultiColumn(2, wxCENTER);
|
S.StartMultiColumn(2, wxCENTER);
|
||||||
{
|
{
|
||||||
FloatingPointValidator<float> vldNewPeak(1, &mNewPeak);
|
FloatingPointValidator<double> vldNewPeak(2, &mNewPeak);
|
||||||
vldNewPeak.SetRange(20.0f * log10f(powf(10.0f, MIN_Amp / 20.0f) * mPeak),
|
double minAmp = MIN_Amp + (20.0 * log10(mPeak));
|
||||||
20.0f * log10f(powf(10.0f, MAX_Amp / 20.0f) * mPeak));
|
double maxAmp = MAX_Amp + (20.0 * log10(mPeak));
|
||||||
|
// TODO: This is a hack that should be fixed in the validator:
|
||||||
|
// If MAX_Amp is negative, then the truncated text value will be greater
|
||||||
|
// than the actual float value.
|
||||||
|
// Add 0.05 to the max value, equivalent to rounding the right way.
|
||||||
|
if (maxAmp < 0)
|
||||||
|
maxAmp += 0.005;
|
||||||
|
vldNewPeak.SetRange(minAmp, maxAmp);
|
||||||
mNewPeakT = S.Id(ID_Peak).AddTextBox(_("New Peak Amplitude (dB):"), wxT(""), 12);
|
mNewPeakT = S.Id(ID_Peak).AddTextBox(_("New Peak Amplitude (dB):"), wxT(""), 12);
|
||||||
mNewPeakT->SetValidator(vldNewPeak);
|
mNewPeakT->SetValidator(vldNewPeak);
|
||||||
}
|
}
|
||||||
@ -238,17 +248,17 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S)
|
|||||||
bool EffectAmplify::TransferDataToWindow()
|
bool EffectAmplify::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
// limit range of gain
|
// limit range of gain
|
||||||
float dBInit = 20.0f*log10f(mRatio);
|
double dBInit = 20.0*log10(mRatio);
|
||||||
float dB = TrapFloat(dBInit, MIN_Amp, MAX_Amp);
|
double dB = TrapDouble(dBInit, MIN_Amp, MAX_Amp);
|
||||||
if (dB != dBInit)
|
if (dB != dBInit)
|
||||||
mRatio = powf(10.0f, dB / 20.0f);
|
mRatio = pow(10.0, dB / 20.0);
|
||||||
|
|
||||||
mAmp = 20.0f * log10f(mRatio);
|
mAmp = 20.0 * log10(mRatio);
|
||||||
mAmpT->GetValidator()->TransferToWindow();
|
mAmpT->GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
mAmpS->SetValue((int) (mAmp * SCL_Amp + 0.5f));
|
mAmpS->SetValue((int) (mAmp * SCL_Amp + 0.5f));
|
||||||
|
|
||||||
mNewPeak = 20.0f * log10f(mRatio * mPeak);
|
mNewPeak = 20.0 * log10(mRatio * mPeak);
|
||||||
mNewPeakT->GetValidator()->TransferToWindow();
|
mNewPeakT->GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
mClip->SetValue(mCanClip);
|
mClip->SetValue(mCanClip);
|
||||||
@ -265,13 +275,13 @@ bool EffectAmplify::TransferDataFromWindow()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRatio = powf(10.0f, TrapFloat(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / (20.0f * SCL_Amp));
|
mRatio = pow(10.0, TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / (20.0 * SCL_Amp));
|
||||||
|
|
||||||
mCanClip = mClip->GetValue();
|
mCanClip = mClip->GetValue();
|
||||||
|
|
||||||
if (!mCanClip && mRatio * mPeak > 1.0f)
|
if (!mCanClip && mRatio * mPeak > 1.0)
|
||||||
{
|
{
|
||||||
mRatio = 1.0f / mPeak;
|
mRatio = 1.0 / mPeak;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -281,12 +291,7 @@ bool EffectAmplify::TransferDataFromWindow()
|
|||||||
|
|
||||||
void EffectAmplify::CheckClip()
|
void EffectAmplify::CheckClip()
|
||||||
{
|
{
|
||||||
// On Linux (not tested other platforms), 1.0f/mPeak is calculated at higher precision
|
EnableApply(mClip->GetValue() || (mPeak > 0.0 && mRatio <= 1.0/mPeak + EPSILON));
|
||||||
// than the (float) value of mRatio, that is, the value is rounded in mRatio = 1/mPeak,
|
|
||||||
// so there is no guarantee that mRatio == 1/mPeak. To test for equality, assign the value
|
|
||||||
// of 1/mPeak to a float rather than directly comparing mRatio <= 1.0f/mPeak
|
|
||||||
float peakInv = 1.0f/mPeak;
|
|
||||||
EnableApply(mClip->GetValue() || (mPeak > 0.0f && mRatio <= peakInv));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectAmplify::OnAmpText(wxCommandEvent & WXUNUSED(evt))
|
void EffectAmplify::OnAmpText(wxCommandEvent & WXUNUSED(evt))
|
||||||
@ -297,11 +302,11 @@ void EffectAmplify::OnAmpText(wxCommandEvent & WXUNUSED(evt))
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRatio = powf(10.0f, TrapFloat(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / (20.0f * SCL_Amp));
|
mRatio = pow(10.0, TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / (20.0 * SCL_Amp));
|
||||||
|
|
||||||
mAmpS->SetValue((int) (20.0f * log10f(mRatio) * SCL_Amp + 0.5f));
|
mAmpS->SetValue((int) (20.0 * log10(mRatio) * SCL_Amp + 0.5));
|
||||||
|
|
||||||
mNewPeak = 20.0f * log10f(mRatio * mPeak);
|
mNewPeak = 20.0 * log10(mRatio * mPeak);
|
||||||
mNewPeakT->GetValidator()->TransferToWindow();
|
mNewPeakT->GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
CheckClip();
|
CheckClip();
|
||||||
@ -315,12 +320,12 @@ void EffectAmplify::OnPeakText(wxCommandEvent & WXUNUSED(evt))
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRatio = powf(10.0f, mNewPeak / 20.0f) / mPeak;
|
mRatio = pow(10.0, mNewPeak / 20.0) / mPeak;
|
||||||
|
|
||||||
float ampInit = 20.0f * log10f(mRatio);
|
double ampInit = 20.0 * log10(mRatio);
|
||||||
mAmp = TrapFloat(ampInit, MIN_Amp, MAX_Amp);
|
mAmp = TrapDouble(ampInit, MIN_Amp, MAX_Amp);
|
||||||
if (mAmp != ampInit)
|
if (mAmp != ampInit)
|
||||||
mRatio = powf(10.0f, mAmp / 20.0f);
|
mRatio = pow(10.0, mAmp / 20.0);
|
||||||
|
|
||||||
mAmpT->GetValidator()->TransferToWindow();
|
mAmpT->GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
@ -331,21 +336,21 @@ void EffectAmplify::OnPeakText(wxCommandEvent & WXUNUSED(evt))
|
|||||||
|
|
||||||
void EffectAmplify::OnAmpSlider(wxCommandEvent & evt)
|
void EffectAmplify::OnAmpSlider(wxCommandEvent & evt)
|
||||||
{
|
{
|
||||||
float dB = evt.GetInt() / SCL_Amp;
|
double dB = evt.GetInt() / SCL_Amp;
|
||||||
mRatio = powf(10.0f, TrapFloat(dB, MIN_Amp, MAX_Amp) / 20.0f);
|
mRatio = pow(10.0, TrapDouble(dB, MIN_Amp, MAX_Amp) / 20.0);
|
||||||
|
|
||||||
float dB2 = (evt.GetInt() - 1) / SCL_Amp;
|
double dB2 = (evt.GetInt() - 1) / SCL_Amp;
|
||||||
float ratio2 = powf(10.0f, TrapFloat(dB2, MIN_Amp, MAX_Amp) / 20.0f);
|
double ratio2 = pow(10.0, TrapDouble(dB2, MIN_Amp, MAX_Amp) / 20.0);
|
||||||
|
|
||||||
if (!mClip->GetValue() && mRatio * mPeak > 1.0f && ratio2 * mPeak < 1.0f)
|
if (!mClip->GetValue() && mRatio * mPeak > 1.0 && ratio2 * mPeak < 1.0)
|
||||||
{
|
{
|
||||||
mRatio = 1.0 / mPeak;
|
mRatio = 1.0 / mPeak;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAmp = 20.0f * log10f(mRatio);
|
mAmp = 20.0 * log10(mRatio);
|
||||||
mAmpT->GetValidator()->TransferToWindow();
|
mAmpT->GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
mNewPeak = 20.0f * log10f(mRatio * mPeak);
|
mNewPeak = 20.0 * log10(mRatio * mPeak);
|
||||||
mNewPeakT->GetValidator()->TransferToWindow();
|
mNewPeakT->GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
CheckClip();
|
CheckClip();
|
||||||
|
@ -68,11 +68,11 @@ private:
|
|||||||
void CheckClip();
|
void CheckClip();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mPeak;
|
double mPeak;
|
||||||
|
|
||||||
float mRatio;
|
double mRatio;
|
||||||
float mAmp;
|
double mAmp;
|
||||||
float mNewPeak;
|
double mNewPeak;
|
||||||
bool mCanClip;
|
bool mCanClip;
|
||||||
|
|
||||||
wxSlider *mAmpS;
|
wxSlider *mAmpS;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user