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

View File

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