mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-16 08:34:10 +02:00
Frequency-selection aware noise reduction, plus small adjustments to toolbar and effect. (patch from Paul Licameli)
1. Change in project.cpp fixes misbehavior of spectral selection toolbar, when you try to enter numbers in the low or high frequency boxes and one of the frequencies was undefined. 2. Changes in NoiseReduction.cpp now take the spectral selection into account in step 2, so that noise is reduced (or isolated) only in the selected range of frequencies. No effect on statistics gathered in step 1. 3. Other noise reduction changes: avoid an assertion in case of certain incompatible settings, and end all messages in message boxes consistently with a period.
This commit is contained in:
parent
e76c17d384
commit
703fafacb2
@ -1263,8 +1263,10 @@ void AudacityProject::SSBL_ModifySpectralSelection(double &bottom, double &top,
|
||||
{
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
double nyq = mRate / 2.0;
|
||||
bottom = std::max(1.0, std::min(nyq, bottom));
|
||||
top = std::max(0.0, std::min(nyq, top));
|
||||
if (bottom >= 0.0)
|
||||
bottom = std::min(nyq, bottom);
|
||||
if (top >= 0.0)
|
||||
top = std::min(nyq, top);
|
||||
mViewInfo.selectedRegion.setFrequencies(bottom, top);
|
||||
mTrackPanel->Refresh(false);
|
||||
if (done) {
|
||||
|
@ -37,6 +37,7 @@
|
||||
*/
|
||||
|
||||
#include "../Audacity.h"
|
||||
#include "../Experimental.h"
|
||||
#include "NoiseReduction.h"
|
||||
|
||||
#include "../Prefs.h"
|
||||
@ -229,7 +230,11 @@ public:
|
||||
typedef EffectNoiseReduction::Settings Settings;
|
||||
typedef EffectNoiseReduction::Statistics Statistics;
|
||||
|
||||
Worker(const Settings &settings, double sampleRate);
|
||||
Worker(const Settings &settings, double sampleRate
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
, double f0, double f1
|
||||
#endif
|
||||
);
|
||||
~Worker();
|
||||
|
||||
bool Process(EffectNoiseReduction &effect,
|
||||
@ -274,6 +279,9 @@ private:
|
||||
const int mSpectrumSize;
|
||||
FloatVector mFreqSmoothingScratch;
|
||||
const int mFreqSmoothingBins;
|
||||
// When spectral selection limits the affected band:
|
||||
int mBinLow; // inclusive lower bound
|
||||
int mBinHigh; // exclusive upper bound
|
||||
|
||||
const int mNoiseReductionChoice;
|
||||
const int mStepsPerWindow;
|
||||
@ -545,12 +553,17 @@ bool EffectNoiseReduction::Settings::PrefsIO(bool read)
|
||||
bool EffectNoiseReduction::Settings::Validate() const
|
||||
{
|
||||
if (StepsPerWindow() < windowTypesInfo[mWindowTypes].minSteps) {
|
||||
::wxMessageBox(_("Steps per block are too few for the window types"));
|
||||
::wxMessageBox(_("Steps per block are too few for the window types."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StepsPerWindow() > WindowSize()) {
|
||||
::wxMessageBox(_("Steps per block cannot exceed the window size"));
|
||||
::wxMessageBox(_("Steps per block cannot exceed the window size."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mMethod == DM_MEDIAN && StepsPerWindow() > 4) {
|
||||
::wxMessageBox(_("Median method is not implemented for more than four steps per window."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -589,10 +602,14 @@ bool EffectNoiseReduction::Process()
|
||||
}
|
||||
else if (mStatistics->mWindowTypes != mSettings->mWindowTypes) {
|
||||
// A warning only
|
||||
::wxMessageBox(_("Warning: window types are not the same as for profiling"));
|
||||
::wxMessageBox(_("Warning: window types are not the same as for profiling."));
|
||||
}
|
||||
|
||||
Worker worker(*mSettings, mStatistics->mRate);
|
||||
Worker worker(*mSettings, mStatistics->mRate
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
, mF0, mF1
|
||||
#endif
|
||||
);
|
||||
bool bGoodResult = worker.Process(*this, *mStatistics, *mFactory, iter, mT0, mT1);
|
||||
if (mSettings->mDoProfile) {
|
||||
if (bGoodResult)
|
||||
@ -646,7 +663,7 @@ bool EffectNoiseReduction::Worker::Process
|
||||
|
||||
if (mDoProfile) {
|
||||
if (statistics.mTotalWindows == 0) {
|
||||
::wxMessageBox(_("Selected noise profile is too short"));
|
||||
::wxMessageBox(_("Selected noise profile is too short."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -685,7 +702,11 @@ void EffectNoiseReduction::Worker::ApplyFreqSmoothing(FloatVector &gains)
|
||||
}
|
||||
|
||||
EffectNoiseReduction::Worker::Worker
|
||||
(const Settings &settings, double sampleRate)
|
||||
(const Settings &settings, double sampleRate
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
, double f0, double f1
|
||||
#endif
|
||||
)
|
||||
: mDoProfile(settings.mDoProfile)
|
||||
|
||||
, mSampleRate(sampleRate)
|
||||
@ -701,6 +722,8 @@ EffectNoiseReduction::Worker::Worker
|
||||
, mSpectrumSize(1 + mWindowSize / 2)
|
||||
, mFreqSmoothingScratch(mSpectrumSize)
|
||||
, mFreqSmoothingBins((int)(settings.mFreqSmoothingHz * mWindowSize / mSampleRate))
|
||||
, mBinLow(0)
|
||||
, mBinHigh(mSpectrumSize)
|
||||
|
||||
, mNoiseReductionChoice(settings.mNoiseReductionChoice)
|
||||
, mStepsPerWindow(settings.StepsPerWindow())
|
||||
@ -714,6 +737,16 @@ EffectNoiseReduction::Worker::Worker
|
||||
, mOutStepCount(0)
|
||||
, mInWavePos(0)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
{
|
||||
const double bin = mSampleRate / mWindowSize;
|
||||
if (f0 >= 0.0 )
|
||||
mBinLow = floor(f0 / bin);
|
||||
if (f1 >= 0.0)
|
||||
mBinHigh = ceil(f1 / bin);
|
||||
}
|
||||
#endif
|
||||
|
||||
const double noiseGain = -settings.mNoiseGain;
|
||||
const int nAttackBlocks = 1 + (int)(settings.mAttackTime * sampleRate / mStepSize);
|
||||
const int nReleaseBlocks = 1 + (int)(settings.mReleaseTime * sampleRate / mStepSize);
|
||||
@ -1074,13 +1107,21 @@ void EffectNoiseReduction::Worker::ReduceNoise
|
||||
{
|
||||
float *pGain = &mQueue[mCenter]->mGains[0];
|
||||
if (mNoiseReductionChoice == NRC_ISOLATE_NOISE) {
|
||||
for (int jj = 0; jj < mSpectrumSize; ++jj) {
|
||||
const bool isNoise = Classify(statistics, jj);
|
||||
// All above or below the selected frequency range is non-noise
|
||||
std::fill(pGain, pGain + mBinLow, 0.0f);
|
||||
std::fill(pGain + mBinHigh, pGain + mSpectrumSize, 0.0f);
|
||||
pGain += mBinLow;
|
||||
for (int jj = mBinLow; jj < mBinHigh; ++jj) {
|
||||
const bool isNoise = Classify(statistics, jj);
|
||||
*pGain++ = isNoise ? 1.0 : 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int jj = 0; jj < mSpectrumSize; ++jj) {
|
||||
// All above or below the selected frequency range is non-noise
|
||||
std::fill(pGain, pGain + mBinLow, 1.0f);
|
||||
std::fill(pGain + mBinHigh, pGain + mSpectrumSize, 1.0f);
|
||||
pGain += mBinLow;
|
||||
for (int jj = mBinLow; jj < mBinHigh; ++jj) {
|
||||
const bool isNoise = Classify(statistics, jj);
|
||||
if (!isNoise)
|
||||
*pGain = 1.0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user