mirror of
https://github.com/cookiengineer/audacity
synced 2025-09-23 15:41:09 +02:00
Disable experimental loudness normalizing
This commit is contained in:
parent
4ec1393c27
commit
e1ae057806
@ -251,4 +251,7 @@
|
||||
// PRL 31 July 2018
|
||||
#define EXPERIMENTAL_DRAGGABLE_PLAY_HEAD
|
||||
|
||||
// mmm-1 22 Aug 2018
|
||||
//#define EXPERIMENTAL_R128_NORM
|
||||
|
||||
#endif
|
||||
|
@ -34,11 +34,13 @@
|
||||
//
|
||||
// Name Type Key Def Min Max Scale
|
||||
Param( PeakLevel, double, wxT("PeakLevel"), -1.0, -145.0, 0.0, 1 );
|
||||
Param( LUFSLevel, double, wxT("LUFSLevel"), -23.0, -145.0, 0.0, 1 );
|
||||
Param( RemoveDC, bool, wxT("RemoveDcOffset"), true, false, true, 1 );
|
||||
Param( ApplyGain, bool, wxT("ApplyGain"), true, false, true, 1 );
|
||||
Param( StereoInd, bool, wxT("StereoIndependent"), false, false, true, 1 );
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
Param( LUFSLevel, double, wxT("LUFSLevel"), -23.0, -145.0, 0.0, 1 );
|
||||
Param( UseLoudness, bool, wxT("UseLoudness"), false, false, true, 1 );
|
||||
#endif
|
||||
|
||||
BEGIN_EVENT_TABLE(EffectNormalize, wxEvtHandler)
|
||||
EVT_CHECKBOX(wxID_ANY, EffectNormalize::OnUpdateUI)
|
||||
@ -48,11 +50,13 @@ END_EVENT_TABLE()
|
||||
EffectNormalize::EffectNormalize()
|
||||
{
|
||||
mPeakLevel = DEF_PeakLevel;
|
||||
mLUFSLevel = DEF_LUFSLevel;
|
||||
mDC = DEF_RemoveDC;
|
||||
mGain = DEF_ApplyGain;
|
||||
mStereoInd = DEF_StereoInd;
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
mLUFSLevel = DEF_LUFSLevel;
|
||||
mUseLoudness = DEF_UseLoudness;
|
||||
#endif
|
||||
|
||||
SetLinearEffectFlag(false);
|
||||
}
|
||||
@ -70,7 +74,11 @@ IdentInterfaceSymbol EffectNormalize::GetSymbol()
|
||||
|
||||
wxString EffectNormalize::GetDescription()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
return _("Sets the peak amplitude or loudness of one or more tracks");
|
||||
#else
|
||||
return _("Sets the peak amplitude of one or more tracks");
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString EffectNormalize::ManualPage()
|
||||
@ -88,22 +96,26 @@ EffectType EffectNormalize::GetType()
|
||||
// EffectClientInterface implementation
|
||||
bool EffectNormalize::DefineParams( ShuttleParams & S ){
|
||||
S.SHUTTLE_PARAM( mPeakLevel, PeakLevel );
|
||||
S.SHUTTLE_PARAM( mLUFSLevel, LUFSLevel );
|
||||
S.SHUTTLE_PARAM( mGain, ApplyGain );
|
||||
S.SHUTTLE_PARAM( mDC, RemoveDC );
|
||||
S.SHUTTLE_PARAM( mStereoInd, StereoInd );
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
S.SHUTTLE_PARAM( mLUFSLevel, LUFSLevel );
|
||||
S.SHUTTLE_PARAM( mUseLoudness, UseLoudness );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EffectNormalize::GetAutomationParameters(CommandParameters & parms)
|
||||
{
|
||||
parms.Write(KEY_PeakLevel, mPeakLevel);
|
||||
parms.Write(KEY_LUFSLevel, mLUFSLevel);
|
||||
parms.Write(KEY_ApplyGain, mGain);
|
||||
parms.Write(KEY_RemoveDC, mDC);
|
||||
parms.Write(KEY_StereoInd, mStereoInd);
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
parms.Write(KEY_LUFSLevel, mLUFSLevel);
|
||||
parms.Write(KEY_UseLoudness, mUseLoudness);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -111,18 +123,22 @@ bool EffectNormalize::GetAutomationParameters(CommandParameters & parms)
|
||||
bool EffectNormalize::SetAutomationParameters(CommandParameters & parms)
|
||||
{
|
||||
ReadAndVerifyDouble(PeakLevel);
|
||||
ReadAndVerifyDouble(LUFSLevel);
|
||||
ReadAndVerifyBool(ApplyGain);
|
||||
ReadAndVerifyBool(RemoveDC);
|
||||
ReadAndVerifyBool(StereoInd);
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
ReadAndVerifyDouble(LUFSLevel);
|
||||
ReadAndVerifyBool(UseLoudness);
|
||||
#endif
|
||||
|
||||
mPeakLevel = PeakLevel;
|
||||
mLUFSLevel = LUFSLevel;
|
||||
mGain = ApplyGain;
|
||||
mDC = RemoveDC;
|
||||
mStereoInd = StereoInd;
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
mLUFSLevel = LUFSLevel;
|
||||
mUseLoudness = UseLoudness;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -158,8 +174,10 @@ bool EffectNormalize::Startup()
|
||||
mPeakLevel = -mPeakLevel;
|
||||
boolProxy = gPrefs->Read(base + wxT("StereoIndependent"), 0L);
|
||||
mStereoInd = (boolProxy == 1);
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
mUseLoudness = false;
|
||||
mLUFSLevel = DEF_LUFSLevel;
|
||||
#endif
|
||||
|
||||
SaveUserPreset(GetCurrentSettingsGroup());
|
||||
|
||||
@ -179,16 +197,24 @@ bool EffectNormalize::Process()
|
||||
float ratio;
|
||||
if( mGain )
|
||||
{
|
||||
if(mUseLoudness)
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
if(mUseLoudness) {
|
||||
// LU use 10*log10(...) instead of 20*log10(...)
|
||||
// so multiply level by 2 and use standard DB_TO_LINEAR macro.
|
||||
ratio = DB_TO_LINEAR(TrapDouble(mLUFSLevel*2, MIN_LUFSLevel, MAX_LUFSLevel));
|
||||
else
|
||||
}
|
||||
else {
|
||||
// same value used for all tracks
|
||||
ratio = DB_TO_LINEAR(TrapDouble(mPeakLevel, MIN_PeakLevel, MAX_PeakLevel));
|
||||
}
|
||||
#else
|
||||
// same value used for all tracks
|
||||
ratio = DB_TO_LINEAR(TrapDouble(mPeakLevel, MIN_PeakLevel, MAX_PeakLevel));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
else {
|
||||
ratio = 1.0;
|
||||
}
|
||||
|
||||
//Iterate over each track
|
||||
this->CopyInputTracks(); // Set up mOutputTracks.
|
||||
@ -238,19 +264,21 @@ bool EffectNormalize::Process()
|
||||
if( (extent > 0) && mGain )
|
||||
{
|
||||
mMult = ratio / extent;
|
||||
if(mUseLoudness)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
if(mUseLoudness) {
|
||||
// LUFS is defined as -0.691 dB + 10*log10(sum(channels))
|
||||
mMult /= 0.8529037031;
|
||||
// LUFS are related to square values so the multiplier must be the root.
|
||||
mMult = sqrt(ratio / extent);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
mMult = 1.0;
|
||||
|
||||
msg =
|
||||
topMsg + wxString::Format( _("Processing: %s"), trackName );
|
||||
|
||||
if(track->GetLinked() || prevTrack->GetLinked()) // only get here if there is a linked track but we are processing independently
|
||||
msg =
|
||||
topMsg + wxString::Format( _("Processing stereo channels independently: %s"), trackName );
|
||||
@ -261,8 +289,7 @@ bool EffectNormalize::Process()
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// we have a linked stereo track
|
||||
// so we need to find it's min, max and offset
|
||||
// as they are needed to calc the multiplier for both tracks
|
||||
@ -276,30 +303,40 @@ bool EffectNormalize::Process()
|
||||
if ( !bGoodResult )
|
||||
break;
|
||||
|
||||
if (mUseLoudness)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
if (mUseLoudness) {
|
||||
// Loudness: use sum of both tracks.
|
||||
// As a result, stereo tracks appear about 3 LUFS louder, as specified.
|
||||
extent = extent + extent2;
|
||||
// LUFS is defined as -0.691 dB + 10*log10(sum(channels))
|
||||
extent *= 0.8529037031;
|
||||
}
|
||||
else
|
||||
else {
|
||||
// Peak: use maximum of both tracks.
|
||||
extent = fmax(extent, extent2);
|
||||
}
|
||||
#else
|
||||
// Peak: use maximum of both tracks.
|
||||
extent = fmax(extent, extent2);
|
||||
#endif
|
||||
|
||||
if( (extent > 0) && mGain )
|
||||
{
|
||||
mMult = ratio / extent; // we need to use this for both linked tracks
|
||||
if(mUseLoudness)
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
if(mUseLoudness) {
|
||||
// LUFS are related to square values so the multiplier must be the root.
|
||||
mMult = sqrt(mMult);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
mMult = 1.0;
|
||||
|
||||
track = (WaveTrack *) iter.Prev(); // go back to the first linked one
|
||||
msg =
|
||||
topMsg + wxString::Format( _("Processing first track of stereo pair: %s"), trackName );
|
||||
|
||||
if (!ProcessOne(track, msg, progress, offset))
|
||||
{
|
||||
bGoodResult = false;
|
||||
@ -308,6 +345,7 @@ bool EffectNormalize::Process()
|
||||
track = (WaveTrack *) iter.Next(); // go to the second linked one
|
||||
msg =
|
||||
topMsg + wxString::Format( _("Processing second track of stereo pair: %s"), trackName );
|
||||
|
||||
if (!ProcessOne(track, msg, progress, offset2))
|
||||
{
|
||||
bGoodResult = false;
|
||||
@ -345,9 +383,12 @@ void EffectNormalize::PopulateOrExchange(ShuttleGui & S)
|
||||
// which that is will depend on translation. So decide that here.
|
||||
// (strictly we should count pixels, not characters).
|
||||
wxString prompt1 = _("Normalize peak amplitude to");
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
wxString prompt2 = _("Normalize loudness to");
|
||||
wxString longerPrompt = ((prompt1.Length() > prompt2.Length()) ? prompt1 : prompt2) + " ";
|
||||
|
||||
#else
|
||||
wxString longerPrompt = prompt1 + " ";
|
||||
#endif
|
||||
// Now make the checkbox.
|
||||
mGainCheckBox = S.AddCheckBox(longerPrompt,
|
||||
mGain ? wxT("true") : wxT("false"));
|
||||
@ -367,11 +408,11 @@ void EffectNormalize::PopulateOrExchange(ShuttleGui & S)
|
||||
wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
mUseLoudnessCheckBox = S.AddCheckBox(_("Use loudness instead of peak amplitude"),
|
||||
mUseLoudness ? wxT("true") : wxT("false"));
|
||||
mUseLoudnessCheckBox->SetValidator(wxGenericValidator(&mGUIUseLoudness));
|
||||
|
||||
#endif
|
||||
mStereoIndCheckBox = S.AddCheckBox(_("Normalize stereo channels independently"),
|
||||
mStereoInd ? wxT("true") : wxT("false"));
|
||||
mStereoIndCheckBox->SetValidator(wxGenericValidator(&mStereoInd));
|
||||
@ -381,8 +422,10 @@ void EffectNormalize::PopulateOrExchange(ShuttleGui & S)
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
// To ensure that the UpdateUI on creation sets the prompts correctly.
|
||||
mUseLoudness = !mGUIUseLoudness;
|
||||
#endif
|
||||
mCreating = false;
|
||||
}
|
||||
|
||||
@ -418,6 +461,7 @@ bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
|
||||
|
||||
if(mGain)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
if(mUseLoudness)
|
||||
{
|
||||
CalcEBUR128HPF(track->GetRate());
|
||||
@ -437,6 +481,7 @@ bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
// Since we need complete summary data, we need to block until the OD tasks are done for this track
|
||||
// This is needed for track->GetMinMax
|
||||
// TODO: should we restrict the flags to just the relevant block files (for selections)
|
||||
@ -458,7 +503,9 @@ bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
|
||||
min += offset;
|
||||
max += offset;
|
||||
}
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(mDC)
|
||||
{
|
||||
@ -469,12 +516,15 @@ bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG("Analysing Track when nothing to do!");
|
||||
min = -1.0, max = 1.0; // sensible defaults?
|
||||
offset = 0.0;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
if(!mUseLoudness)
|
||||
#endif
|
||||
extent = fmax(fabs(min), fabs(max));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -499,8 +549,10 @@ bool EffectNormalize::AnalyseTrackData(const WaveTrack * track, const wxString &
|
||||
Floats buffer{ track->GetMaxBlockSize() };
|
||||
|
||||
mSum = 0.0; // dc offset inits
|
||||
mSqSum = 0.0; // rms init
|
||||
mCount = 0;
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
mSqSum = 0.0; // rms init
|
||||
#endif
|
||||
|
||||
sampleCount blockSamples;
|
||||
sampleCount totalSamples = 0;
|
||||
@ -523,10 +575,12 @@ bool EffectNormalize::AnalyseTrackData(const WaveTrack * track, const wxString &
|
||||
//Process the buffer.
|
||||
if(op == ANALYSE_DC)
|
||||
AnalyseDataDC(buffer.get(), block);
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
else if(op == ANALYSE_LOUDNESS)
|
||||
AnalyseDataLoudness(buffer.get(), block);
|
||||
else if(op == ANALYSE_LOUDNESS_DC)
|
||||
AnalyseDataLoudnessDC(buffer.get(), block);
|
||||
#endif
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += block;
|
||||
@ -614,6 +668,7 @@ void EffectNormalize::AnalyseDataDC(float *buffer, size_t len)
|
||||
mCount += len;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
/// @see AnalyseDataLoudnessDC
|
||||
void EffectNormalize::AnalyseDataLoudness(float *buffer, size_t len)
|
||||
{
|
||||
@ -645,6 +700,7 @@ void EffectNormalize::AnalyseDataLoudnessDC(float *buffer, size_t len)
|
||||
}
|
||||
mCount += len;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EffectNormalize::ProcessData(float *buffer, size_t len, float offset)
|
||||
{
|
||||
@ -654,6 +710,7 @@ void EffectNormalize::ProcessData(float *buffer, size_t len, float offset)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
// EBU R128 parameter sampling rate adaption after
|
||||
// Mansbridge, Stuart, Saoirse Finn, and Joshua D. Reiss.
|
||||
// "Implementation and Evaluation of Autonomous Multi-track Fader Control."
|
||||
@ -701,6 +758,7 @@ void EffectNormalize::CalcEBUR128HSF(float fs)
|
||||
mR128HSF.fDenomCoeffs[Biquad::A1] = 2.0 * (K * K - 1.0) / a0;
|
||||
mR128HSF.fDenomCoeffs[Biquad::A2] = (1.0 - K / Q + K * K) / a0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EffectNormalize::OnUpdateUI(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
@ -718,6 +776,7 @@ void EffectNormalize::UpdateUI()
|
||||
}
|
||||
mWarning->SetLabel(wxT(""));
|
||||
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
// Changing the prompts causes an unwanted UpdateUI event.
|
||||
// This 'guard' stops that becoming an infinite recursion.
|
||||
if (mUseLoudness != mGUIUseLoudness)
|
||||
@ -744,12 +803,15 @@ void EffectNormalize::UpdateUI()
|
||||
mGainCheckBox->SetLabelText(_("Normalize peak amplitude to"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Disallow level stuff if not normalizing
|
||||
mLevelTextCtrl->Enable(mGain);
|
||||
mLeveldB->Enable(mGain);
|
||||
mStereoIndCheckBox->Enable(mGain);
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
mUseLoudnessCheckBox->Enable(mGain);
|
||||
#endif
|
||||
|
||||
// Disallow OK/Preview if doing nothing
|
||||
EnableApply(mGain || mDC);
|
||||
|
@ -72,30 +72,38 @@ private:
|
||||
bool AnalyseTrackData(const WaveTrack * track, const wxString &msg, double &progress,
|
||||
AnalyseOperation op, float &offset);
|
||||
void AnalyseDataDC(float *buffer, size_t len);
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
void AnalyseDataLoudness(float *buffer, size_t len);
|
||||
void AnalyseDataLoudnessDC(float *buffer, size_t len);
|
||||
#endif
|
||||
void ProcessData(float *buffer, size_t len, float offset);
|
||||
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
void CalcEBUR128HPF(float fs);
|
||||
void CalcEBUR128HSF(float fs);
|
||||
#endif
|
||||
|
||||
void OnUpdateUI(wxCommandEvent & evt);
|
||||
void UpdateUI();
|
||||
|
||||
private:
|
||||
double mPeakLevel;
|
||||
double mLUFSLevel;
|
||||
bool mGain;
|
||||
bool mDC;
|
||||
bool mStereoInd;
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
double mLUFSLevel;
|
||||
bool mUseLoudness;
|
||||
bool mGUIUseLoudness;
|
||||
#endif
|
||||
|
||||
double mCurT0;
|
||||
double mCurT1;
|
||||
float mMult;
|
||||
double mSum;
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
double mSqSum;
|
||||
#endif
|
||||
sampleCount mCount;
|
||||
|
||||
wxCheckBox *mGainCheckBox;
|
||||
@ -103,12 +111,15 @@ private:
|
||||
wxTextCtrl *mLevelTextCtrl;
|
||||
wxStaticText *mLeveldB;
|
||||
wxStaticText *mWarning;
|
||||
wxCheckBox *mUseLoudnessCheckBox;
|
||||
wxCheckBox *mStereoIndCheckBox;
|
||||
#ifdef EXPERIMENTAL_R128_NORM
|
||||
wxCheckBox *mUseLoudnessCheckBox;
|
||||
|
||||
bool mCreating;
|
||||
Biquad mR128HSF;
|
||||
Biquad mR128HPF;
|
||||
#endif
|
||||
bool mCreating;
|
||||
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user