1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-15 23:59:37 +02:00

Noise removal updates from Marco Diego Aurélio

This commit is contained in:
james.k.crook 2010-07-04 11:34:51 +00:00
parent fc0dadf93c
commit 4d244e93ae
2 changed files with 103 additions and 10 deletions

View File

@ -60,6 +60,8 @@
#include <wx/bitmap.h>
#include <wx/brush.h>
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/radiobut.h>
#include <wx/dcmemory.h>
#include <wx/image.h>
#include <wx/intl.h>
@ -69,6 +71,7 @@
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include "../AudacityApp.h"
#include "../PlatformCompatibility.h"
@ -77,12 +80,18 @@ EffectNoiseRemoval::EffectNoiseRemoval()
mWindowSize = 2048;
mSpectrumSize = 1 + mWindowSize / 2;
gPrefs->Read(wxT("/CsPresets/NoiseSensitivity"),
&mSensitivity, 0.0);
gPrefs->Read(wxT("/CsPresets/NoiseGain"),
&mNoiseGain, -24.0);
gPrefs->Read(wxT("/CsPresets/NoiseFreqSmoothing"),
&mFreqSmoothingHz, 150.0);
gPrefs->Read(wxT("/CsPresets/NoiseAttackDecayTime"),
&mAttackDecayTime, 0.15);
gPrefs->Read(wxT("/CsPresets/NoiseLeaveNoise"),
&mbLeaveNoise, false);
// mbLeaveNoise = false;
mMinSignalTime = 0.05f;
mHasProfile = false;
@ -213,9 +222,13 @@ bool EffectNoiseRemoval::CheckWhetherSkipEffect()
bool EffectNoiseRemoval::PromptUser()
{
NoiseRemovalDialog dlog(this, mParent);
dlog.mSensitivity = mSensitivity;
dlog.mGain = -mNoiseGain;
dlog.mFreq = mFreqSmoothingHz;
dlog.mTime = mAttackDecayTime;
dlog.mbLeaveNoise = mbLeaveNoise;
dlog.mKeepSignal->SetValue(!mbLeaveNoise);
dlog.mKeepNoise->SetValue(mbLeaveNoise);
if( !mHasProfile )
{
@ -238,6 +251,7 @@ bool EffectNoiseRemoval::PromptUser()
}
dlog.TransferDataToWindow();
dlog.mKeepNoise->SetValue(dlog.mbLeaveNoise);
dlog.CentreOnParent();
dlog.ShowModal();
@ -245,12 +259,16 @@ bool EffectNoiseRemoval::PromptUser()
return false;
}
mSensitivity = dlog.mSensitivity;
mNoiseGain = -dlog.mGain;
mFreqSmoothingHz = dlog.mFreq;
mAttackDecayTime = dlog.mTime;
mbLeaveNoise = dlog.mbLeaveNoise;
gPrefs->Write(wxT("/CsPresets/NoiseSensitivity"), mSensitivity);
gPrefs->Write(wxT("/CsPresets/NoiseGain"), mNoiseGain);
gPrefs->Write(wxT("/CsPresets/NoiseFreqSmoothing"), mFreqSmoothingHz);
gPrefs->Write(wxT("/CsPresets/NoiseAttackDecayTime"), mAttackDecayTime);
gPrefs->Write(wxT("/CsPresets/NoiseLeaveNoise"), mbLeaveNoise);
mDoProfile = (dlog.GetReturnCode() == 1);
return true;
@ -350,7 +368,8 @@ void EffectNoiseRemoval::Initialize()
mAttackDecayBlocks = 1 +
(int)(mAttackDecayTime * mSampleRate / (mWindowSize / 2));
mNoiseAttenFactor = pow(10.0, mNoiseGain/20.0);
mOneBlockAttackDecay = (int)(mNoiseGain / (mAttackDecayBlocks - 1));
mOneBlockAttackDecay = pow(10.0, (mNoiseGain / (10.0 * mAttackDecayBlocks)));
mSensitivityFactor = pow(10.0, mSensitivity/10.0);
mMinSignalBlocks =
(int)(mMinSignalTime * mSampleRate / (mWindowSize / 2));
if( mMinSignalBlocks < 1 )
@ -571,13 +590,17 @@ void EffectNoiseRemoval::RemoveNoise()
if (mSpectrums[i][j] < min)
min = mSpectrums[i][j];
}
if (min > mNoiseThreshold[j] && mGains[center][j] < 1.0)
mGains[center][j] = 1.0;
if (min > mSensitivityFactor * mNoiseThreshold[j] && mGains[center][j] < 1.0) {
if (mbLeaveNoise) mGains[center][j] = 0.0;
else mGains[center][j] = 1.0;
} else {
if (mbLeaveNoise) mGains[center][j] = 1.0;
}
}
// Decay the gain in both directions;
// note that mOneBlockAttackDecay is less than 1.0
// dB of attenuation per block
// of linear attenuation per block
for (j = 0; j < mSpectrumSize; j++) {
for (i = center + 1; i < mHistoryLen; i++) {
if (mGains[i][j] < mGains[i - 1][j] * mOneBlockAttackDecay)
@ -593,6 +616,7 @@ void EffectNoiseRemoval::RemoveNoise()
}
}
// Apply frequency smoothing to output gain
int out = mHistoryLen - 1; // end of the queue
@ -704,14 +728,22 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
enum {
ID_BUTTON_GETPROFILE = 10001,
ID_BUTTON_LEAVENOISE,
ID_RADIOBUTTON_KEEPSIGNAL,
ID_RADIOBUTTON_KEEPNOISE,
ID_SENSIVITY_SLIDER,
ID_GAIN_SLIDER,
ID_FREQ_SLIDER,
ID_TIME_SLIDER,
ID_SENSIVITY_TEXT,
ID_GAIN_TEXT,
ID_FREQ_TEXT,
ID_TIME_TEXT,
};
#define SENSIVITY_MIN 0 // Corresponds to -20 dB
#define SENSIVITY_MAX 4000 // Corresponds to 20 dB
#define GAIN_MIN 0
#define GAIN_MAX 48 // Corresponds to -48 dB
@ -719,7 +751,7 @@ enum {
#define FREQ_MAX 100 // Corresponds to 1000 Hz
#define TIME_MIN 0
#define TIME_MAX 100 // Corresponds to 1.00 seconds
#define TIME_MAX 1000 // Corresponds to 1.000 seconds
BEGIN_EVENT_TABLE(NoiseRemovalDialog,wxDialog)
@ -727,9 +759,13 @@ BEGIN_EVENT_TABLE(NoiseRemovalDialog,wxDialog)
EVT_BUTTON(wxID_CANCEL, NoiseRemovalDialog::OnCancel)
EVT_BUTTON(ID_EFFECT_PREVIEW, NoiseRemovalDialog::OnPreview)
EVT_BUTTON(ID_BUTTON_GETPROFILE, NoiseRemovalDialog::OnGetProfile)
EVT_RADIOBUTTON(ID_RADIOBUTTON_KEEPNOISE, NoiseRemovalDialog::OnKeepNoise)
EVT_RADIOBUTTON(ID_RADIOBUTTON_KEEPSIGNAL, NoiseRemovalDialog::OnKeepNoise)
EVT_SLIDER(ID_SENSIVITY_SLIDER, NoiseRemovalDialog::OnSensitivitySlider)
EVT_SLIDER(ID_GAIN_SLIDER, NoiseRemovalDialog::OnGainSlider)
EVT_SLIDER(ID_FREQ_SLIDER, NoiseRemovalDialog::OnFreqSlider)
EVT_SLIDER(ID_TIME_SLIDER, NoiseRemovalDialog::OnTimeSlider)
EVT_TEXT(ID_SENSIVITY_TEXT, NoiseRemovalDialog::OnSensitivityText)
EVT_TEXT(ID_GAIN_TEXT, NoiseRemovalDialog::OnGainText)
EVT_TEXT(ID_FREQ_TEXT, NoiseRemovalDialog::OnFreqText)
EVT_TEXT(ID_TIME_TEXT, NoiseRemovalDialog::OnTimeText)
@ -759,10 +795,17 @@ void NoiseRemovalDialog::OnGetProfile( wxCommandEvent &event )
EndModal(1);
}
void NoiseRemovalDialog::OnKeepNoise( wxCommandEvent &event )
{
mbLeaveNoise = mKeepNoise->GetValue();
}
void NoiseRemovalDialog::OnPreview(wxCommandEvent &event)
{
// Save & restore parameters around Preview, because we didn't do OK.
bool oldDoProfile = m_pEffect->mDoProfile;
bool oldLeaveNoise = m_pEffect->mbLeaveNoise;
double oldSensitivity = m_pEffect->mSensitivity;
double oldGain = m_pEffect->mNoiseGain;
double oldFreq = m_pEffect->mFreqSmoothingHz;
double oldTime = m_pEffect->mAttackDecayTime;
@ -770,20 +813,25 @@ void NoiseRemovalDialog::OnPreview(wxCommandEvent &event)
TransferDataFromWindow();
m_pEffect->mDoProfile = false;
m_pEffect->mbLeaveNoise = mbLeaveNoise;
m_pEffect->mSensitivity = mSensitivity;
m_pEffect->mNoiseGain = -mGain;
m_pEffect->mFreqSmoothingHz = mFreq;
m_pEffect->mAttackDecayTime = mTime;
m_pEffect->Preview();
m_pEffect->mSensitivity = oldSensitivity;
m_pEffect->mNoiseGain = oldGain;
m_pEffect->mFreqSmoothingHz = oldFreq;
m_pEffect->mAttackDecayTime = oldTime;
m_pEffect->mbLeaveNoise = oldLeaveNoise;
m_pEffect->mDoProfile = oldDoProfile;
}
void NoiseRemovalDialog::OnRemoveNoise( wxCommandEvent &event )
{
mbLeaveNoise = mKeepNoise->GetValue();
EndModal(2);
}
@ -862,6 +910,15 @@ void NoiseRemovalDialog::PopulateOrExchange(ShuttleGui & S)
mGainS->SetRange(GAIN_MIN, GAIN_MAX);
mGainS->SetSizeHints(150, -1);
mSensitivityT = S.Id(ID_SENSIVITY_TEXT).AddTextBox(_("Sensitivity (dB):"),
wxT(""),
0);
S.SetStyle(wxSL_HORIZONTAL);
mSensitivityS = S.Id(ID_SENSIVITY_SLIDER).AddSlider(wxT(""), 0, SENSIVITY_MAX);
mSensitivityS->SetName(_("Sensitivity"));
mSensitivityS->SetRange(SENSIVITY_MIN, SENSIVITY_MAX);
mSensitivityS->SetSizeHints(150, -1);
mFreqT = S.Id(ID_FREQ_TEXT).AddTextBox(_("Frequency smoothing (Hz):"),
wxT(""),
0);
@ -876,9 +933,15 @@ void NoiseRemovalDialog::PopulateOrExchange(ShuttleGui & S)
0);
S.SetStyle(wxSL_HORIZONTAL);
mTimeS = S.Id(ID_TIME_SLIDER).AddSlider(wxT(""), 0, TIME_MAX);
mTimeS->SetName(_("Attach/decay time"));
mTimeS->SetName(_("Attack/decay time"));
mTimeS->SetRange(TIME_MIN, TIME_MAX);
mTimeS->SetSizeHints(150, -1);
S.AddPrompt(_("Noise:"));
mKeepSignal = S.Id(ID_RADIOBUTTON_KEEPSIGNAL)
.AddRadioButtonToGroup(_("Remove"));
mKeepNoise = S.Id(ID_RADIOBUTTON_KEEPNOISE)
.AddRadioButtonToGroup(_("Isolate"));
}
S.EndMultiColumn();
}
@ -887,13 +950,17 @@ void NoiseRemovalDialog::PopulateOrExchange(ShuttleGui & S)
bool NoiseRemovalDialog::TransferDataToWindow()
{
mSensitivityT->SetValue(wxString::Format(wxT("%.2f"), mSensitivity));
mGainT->SetValue(wxString::Format(wxT("%d"), (int)mGain));
mFreqT->SetValue(wxString::Format(wxT("%d"), (int)mFreq));
mTimeT->SetValue(wxString::Format(wxT("%.2f"), mTime));
mKeepNoise->SetValue(mbLeaveNoise);
mKeepSignal->SetValue(!mbLeaveNoise);
mSensitivityS->SetValue(TrapLong(mSensitivity*100.0 + 2000.0, SENSIVITY_MIN, SENSIVITY_MAX));
mGainS->SetValue(TrapLong(mGain, GAIN_MIN, GAIN_MAX));
mFreqS->SetValue(TrapLong(mFreq / 10, FREQ_MIN, FREQ_MAX));
mTimeS->SetValue(TrapLong(mTime / 0.01, TIME_MIN, TIME_MAX));
mTimeS->SetValue(TrapLong(mTime * 1000, TIME_MIN, TIME_MAX));
return true;
}
@ -904,6 +971,12 @@ bool NoiseRemovalDialog::TransferDataFromWindow()
return true;
}
void NoiseRemovalDialog::OnSensitivityText(wxCommandEvent & event)
{
mSensitivityT->GetValue().ToDouble(&mSensitivity);
mSensitivityS->SetValue(TrapLong(mSensitivity*100.0 + 2000.0, SENSIVITY_MIN, SENSIVITY_MAX));
}
void NoiseRemovalDialog::OnGainText(wxCommandEvent & event)
{
mGainT->GetValue().ToDouble(&mGain);
@ -919,7 +992,13 @@ void NoiseRemovalDialog::OnFreqText(wxCommandEvent & event)
void NoiseRemovalDialog::OnTimeText(wxCommandEvent & event)
{
mTimeT->GetValue().ToDouble(&mTime);
mTimeS->SetValue(TrapLong(mTime / 0.01, TIME_MIN, TIME_MAX));
mTimeS->SetValue(TrapLong(mTime * 1000, TIME_MIN, TIME_MAX));
}
void NoiseRemovalDialog::OnSensitivitySlider(wxCommandEvent & event)
{
mSensitivity = mSensitivityS->GetValue()/100.0 - 20.0;
mSensitivityT->SetValue(wxString::Format(wxT("%.2f"), mSensitivity));
}
void NoiseRemovalDialog::OnGainSlider(wxCommandEvent & event)
@ -936,7 +1015,7 @@ void NoiseRemovalDialog::OnFreqSlider(wxCommandEvent & event)
void NoiseRemovalDialog::OnTimeSlider(wxCommandEvent & event)
{
mTime = mTimeS->GetValue() * 0.01;
mTime = mTimeS->GetValue() / 1000.0;
mTimeT->SetValue(wxString::Format(wxT("%.2f"), mTime));
}

View File

@ -81,9 +81,11 @@ private:
// Parameters that affect the noise removal, regardless of how the
// noise profile was extracted
double mSensitivity;
double mFreqSmoothingHz;
double mNoiseGain; // in dB, should be negative
double mAttackDecayTime; // in secs
bool mbLeaveNoise;
bool ProcessOne(int count, WaveTrack * track,
sampleCount start, sampleCount len);
@ -113,6 +115,7 @@ private:
int mAttackDecayBlocks;
float mOneBlockAttackDecay;
float mNoiseAttenFactor;
float mSensitivityFactor;
int mMinSignalBlocks;
int mHistoryLen;
float *mInWaveBuffer; // mWindowSize
@ -151,13 +154,16 @@ public:
private:
// handlers
void OnGetProfile( wxCommandEvent &event );
void OnKeepNoise( wxCommandEvent &event );
void OnPreview(wxCommandEvent &event);
void OnRemoveNoise( wxCommandEvent &event );
void OnCancel( wxCommandEvent &event );
void OnSensitivityText(wxCommandEvent & event);
void OnGainText(wxCommandEvent & event);
void OnFreqText(wxCommandEvent & event);
void OnTimeText(wxCommandEvent & event);
void OnSensitivitySlider(wxCommandEvent & event);
void OnGainSlider(wxCommandEvent & event);
void OnFreqSlider(wxCommandEvent & event);
void OnTimeSlider(wxCommandEvent & event);
@ -170,18 +176,26 @@ private:
wxButton * m_pButton_Preview;
wxButton * m_pButton_RemoveNoise;
wxRadioButton *mKeepSignal;
wxRadioButton *mKeepNoise;
wxSlider *mSensitivityS;
wxSlider *mGainS;
wxSlider *mFreqS;
wxSlider *mTimeS;
wxTextCtrl *mSensitivityT;
wxTextCtrl *mGainT;
wxTextCtrl *mFreqT;
wxTextCtrl *mTimeT;
double mSensitivity;
double mGain;
double mFreq;
double mTime;
bool mbLeaveNoise;
private:
DECLARE_EVENT_TABLE()