If I understand the very old versions of NoiseRemoval.cpp correctly, it really was meant for removal. There was no reduction control, and instead there was a “level” that was more like Sensitivity now. It seems sensitivity contol under watever name got removed and later restored.
Sensitivity and the noise profile together determine what is noise (“discrimination”), and the other controls determine how it is treated.
So maybe the Sensitivity slider should be above the other sliders and just under the profile button.
As far as Preferences and Chains…
Internally, I think “NoiseRemoval” will need to remain as such but “Noise Removal” could be changed to “Noise Reduction”.
To preserve Preferences all of the:
gPrefs->Write(wxT(“/Effects/NoiseRemoval/…
and
gPrefs->Read(wxT(”/Effects/NoiseRemoval/…
which rely on NoiseRemoval need to be honored unless we write a lot of conditional code to look for both NoiseRemoval and NoiseReduction (which may already be happening with other preferences).
The really ugly place we would need to retain NoiseRemoval is in NoiseRemoval.h:
As you know I disagree with you all on that. Practical considerations aside, if the effect is called Noise Reduction, then the “Remove” button is misnamed.
We choose here to be verbose in the dialogue so we could explain that removing noise creates distortion.
The Isolate button is already misnamed, it seems. Of course if it is called “Isolate” it should do the opposite of “Remove”. What other expectation would one have?
-1 to that.
It may be more useful to address the many Manual P1’s and to test the code we already have for the many lib-src changes that were made after 2.0.5 release.
I assume we could do string replacement as we have done before when we changed Chain command names, but I still think the rename is misguided.
IMO, the fundamental reason for arguing that Noise Removal should be called Noise Reduction is that Noise Removal is still inferior to Noise Removal/Reduction in other apps.
As Gale mentioned, that is easy (though not pretty) to work around and has been done before.
If I have a bag containing 10 apples and I “remove” 4 apples, I have “reduced” the number of apples in the bag.
There is no linguistic problem if we say we are “removing” noise and specifying “how much” we are removing. The effect of “removing” some of the noise is that we have “reduced” the amount of noise. To say that we have “removed” the noise is misleading because it implies that we have removed all of the noise, which as we all know causes unwanted side effects that can be worse than the problem that we started with.
Some applications have significantly more effective noise reduction, in that they can often reduce the same amount of noise with subjectively better sound quality. Examples include: Gnome Wave Cleaner “Denoise”, Adobe Audition “Noise Reduction/Restoration > Noise Reduction”, Sony SoundForge “Noise Reduction”, Reaper “ReaFIR”.
+1 for changing the name.
-1 for changing it before 2.0.6 (and I would not expect the release manager to agree to the change).
Gale has mentioned before that some users may see the change from “Noise Removal” to “Noise Reduction” as an indication that the effect has been watered down and is less effective than before. I think it is a reasonable point that some users might think that, though why we might purposefully make an effect worse is a mystery.
I’d be happier if the name change occurred at the same time as replacing “Noise Removal” with a “Noise Reduction” effect that is demonstrably better. Personally I would even be happy about the new effect being incompatible with existing Chains if the new effect was better (a very small price to pay).
Dare I hope that I might be discovering improvements?
I have identified some places where errors were introduced by others that did not respect Dominic Mazzoni’s intentions. It is a matter of logic to prove that.
But now I think I know some variations on Dominic’s algorithms that are worth trying. Whether these should be adopted will be a matter of opinion and not mine alone.
If anyone is interested in testing it after 2.0.6 let me know.
If I take some speech and try extreme settings of 48 dB reduction and the minimal attack/decay and frequency smoothing, and sensitivity 0, I get many obvious artifacts IN THE WORDS.
I have a variation I wrote just this morning that eliminates almost all of these. But effective noise reduction in the pauses is perhaps 6-7 dB less and more subtle tinkles are heard in the PAUSES – if you apply extreme amplification to pauses with the pan control.
That was as I anticipated, but I believe (haven’t tried yet) that increasing the sensitivity may remedy that.
I suppose I could have this variation of the algorithm controlled by a hidden preference so you could edit the config to try it.
The dialogue refers twice to “filtering”. I doubt naive users know what that might mean but I assume it means remove, and the action choice is “Remove” (or “Isolate”).
It is clearly confusing for the name of the effect to be called something other than the action choice.
We can add Goldwave and CoolEdit to Steve’s list of apps that have better noise reduction (better also in that they give better results at default settings).
My objection to the rename is not that we may seem to be saying we’ve watered it down but we are admitting it is not as good as it should be. If Audacity Noise Removal was better there would be much less demand for a name change (though “Noise Reduction” would have been a better choice to begin with).
I agree with Steve that any rename should be deferred until there is a substantial change in the effect (and probably therefore also GUI changes).
Thanks for your perusal of the code and your interest, Paul.
I am sure the current algorithm can be further tweaked but I am not sure to what extent that tweaking it will solve the basic problem.
My impression is that we should be looking at spectral subtraction or noise coring as the future of Noise Removal (or whatever it’s called) and/or present choice of algorithm as the main parameter to change when removing noise rather than users spending hours fiddling with combinations of different parameters of the same algorithm.
We always want to offer detailed control of parameters for advanced users but for more basic users they need simpler choices like “algorithm 1, 2, or 3” and “Weak, medium or strong reduction”.
Rather than having the options “Remove” and “Isolate”, we could have 3 options:
Remove: Removes some of the profiled noise so as to reduce the noise level.
Residual: Inverse of “Remove”. Returns the sound that would be removed if we used “Remove”. (Original sound - noise reduced sound).
Isolate: Removes some of the “non-noise” so as to reduce the non-noise level. Isolates the profiled “noise”.
There may be a better name than “Residual”. Perhaps “Inverse” or something else, but important to distinguish it from “Isolate” (which is very different for low settings).
So seeing this go on for 8 pages made me want to see what’s going on. I walked through the code and to me it seems to allocate the right number of buffers and do the attack decay over the correct number of windows. 1s = 87. I do see that the isolate function does not invert/shift the attack decay function so it has the opposite effect on the floating gains. Just to test this case added the inverted case for isolation at line 489.
// Decay the gain in both directions;
// note that mOneBlockAttackDecay is less than 1.0
// of linear attenuation per block
// A.C.H inverted the funuction for isolate
if (mbLeaveNoise) {
for (j = 0; j < mSpectrumSize; j++) {
for (i = mHistoryLen-2; i > center; i--) {
if (mGains[i][j] < mGains[i + 1][j] * mOneBlockAttackDecay)
mGains[i][j] = mGains[i + 1][j] * mOneBlockAttackDecay;
if (mGains[i][j] < mNoiseAttenFactor)
mGains[i][j] = mNoiseAttenFactor;
}
for (i = 1; i <= center; i++) {
if (mGains[i][j] < mGains[i - 1][j] * mOneBlockAttackDecay)
mGains[i][j] = mGains[i - 1][j] * mOneBlockAttackDecay;
if (mGains[i][j] < mNoiseAttenFactor)
mGains[i][j] = mNoiseAttenFactor;
}
}
} else {
for (j = 0; j < mSpectrumSize; j++) {
for (i = center + 1; i < mHistoryLen; i++) {
if (mGains[i][j] < mGains[i - 1][j] * mOneBlockAttackDecay)
mGains[i][j] = mGains[i - 1][j] * mOneBlockAttackDecay;
if (mGains[i][j] < mNoiseAttenFactor)
mGains[i][j] = mNoiseAttenFactor;
}
for (i = center - 1; i >= 0; i--) {
if (mGains[i][j] < mGains[i + 1][j] * mOneBlockAttackDecay)
mGains[i][j] = mGains[i + 1][j] * mOneBlockAttackDecay;
if (mGains[i][j] < mNoiseAttenFactor)
mGains[i][j] = mNoiseAttenFactor;
}
}
}
Sorry for the resolution and resize. (I’m at 4k)
The other big thing I can see is places where data is unavailable are not being handled correctly. (I.e. Beginning and Ending) There should probably be some replication of the first sample into the null space to handle this.
Realize I’ve only poked around at this for a few hrs. It seems to be nothing more than a floating auto level; very useful, but only designed to do so much.
Imo, the window size should be at least twice (rule of thumb, 1024 for voice, 4096 for music).
Has anyone tested at different sample rates?
Modern approaches use multi-rate FFT’s anyway, mostly following human perception.
The smoothing could thus be linear under 1000 Hz and logarithmic above it.
Windowing should be two-fold, on the analyse and synthesize side and something that is adapted to the smoothing mechanism.
The profile should perhaps rather be made outlayers-free (median or something else non-linear).
I am not sure I understand multi rate FFT or twofold windowing.
You mention medians. I was just about to suggest to steve, in the other recent thread about this, that the right thing to do with the profile is find a certain quantile of the power for each bin.
I suspect that the time and frequency smoothings and the sensitivity setting might be complications just to compensate for thresholds being set too low by the analysis now done on the profile. So fluctuations above the theshold in the noise cause tinklebells in the silences. Dominic added frequency smoothing while Marco Aureliano later added Sensitivity so you can raise the thresholds.
Should we figure out how to make noise removal work well in most cases even when smoothing and sensitivity are all set to zero?