NoiseRemoval.cpp
Forum rules
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
Re: NoiseRemoval.cpp
How many other effects follow this patter of Fourier transform, change of coefficients, then inverse transform? NoiseRemoval includes most of the work for that. Perhaps the common part should be abstracted into another subclass of Effect.
Thought now it seems NoiseRemoval doesn't get the handling of the first and last 1024 samples quite right.
Thought now it seems NoiseRemoval doesn't get the handling of the first and last 1024 samples quite right.
Re: NoiseRemoval.cpp
More thought and experiment, and I discovered another possible problem with Noise Removal. Here is a test case:
Use the former extreme example of a loud 11025 Hz sine wave for Noise Profile, and white noise as the sound to process. Use 48 dB of noise reduction and ZERO frequency smoothing.
Look at the result using Analyze, Spectrum and use a rectangular window of 2048 (just as Noise Removal does).
Shouldn't we see a very narrow notch, with a width of one bin (43 Hz)? We don't get a notch that narrow.
I think I know the reason:
Look at the sine wave using Spectrogram and 2048 and Rectangular.
See the funny stuff that happens at the edges, where there is the abrupt transition to a padding of zeroes? As the code is written, Noise Removal does not see the first funny boundary when analyzing the sample, but it does see the other one.
Therefore, it attenuates frequencies near 11025 more than it should.
Maybe this test case is unrealistic, but a noise profile with spikes at 60 and 120 Hz ought to be common.
Use the former extreme example of a loud 11025 Hz sine wave for Noise Profile, and white noise as the sound to process. Use 48 dB of noise reduction and ZERO frequency smoothing.
Look at the result using Analyze, Spectrum and use a rectangular window of 2048 (just as Noise Removal does).
Shouldn't we see a very narrow notch, with a width of one bin (43 Hz)? We don't get a notch that narrow.
I think I know the reason:
Look at the sine wave using Spectrogram and 2048 and Rectangular.
See the funny stuff that happens at the edges, where there is the abrupt transition to a padding of zeroes? As the code is written, Noise Removal does not see the first funny boundary when analyzing the sample, but it does see the other one.
Therefore, it attenuates frequencies near 11025 more than it should.
Maybe this test case is unrealistic, but a noise profile with spikes at 60 and 120 Hz ought to be common.
Re: NoiseRemoval.cpp
Summarizing problems:
1) attack/decay times are half as long as they should be. Test case already described. Have fix.
2) Resulting sound always has a 1024 sample fade-in from 0. Could fix.
3) Attenuated sounds sometimes rise again in the last 1024 samples, as seen in test cases for (4). Different explanation. Less sure how to fix it.
4) Highest and lowest frequency bins are always silenced (not merely attenuated). Test cases described. Have fix.
5) Noise profiles with narrow spectrum do not result in a narrow notch effect with frequency smoothing off. Test case described. Could fix.
6) Frequency smoothing uses arithmetic averaging of gain factors instead of geometric. Have fix. Do NOT yet have a convincing test case (because problem 5 interferes with demonstrating it). A subtler problem.
Besides all of these, I could clean up some misleading comments written by confused people and I could make a number of minor performance improvements.
Perhaps I should pick only some of these fixes for near term inclusion in the source tree.
1) attack/decay times are half as long as they should be. Test case already described. Have fix.
2) Resulting sound always has a 1024 sample fade-in from 0. Could fix.
3) Attenuated sounds sometimes rise again in the last 1024 samples, as seen in test cases for (4). Different explanation. Less sure how to fix it.
4) Highest and lowest frequency bins are always silenced (not merely attenuated). Test cases described. Have fix.
5) Noise profiles with narrow spectrum do not result in a narrow notch effect with frequency smoothing off. Test case described. Could fix.
6) Frequency smoothing uses arithmetic averaging of gain factors instead of geometric. Have fix. Do NOT yet have a convincing test case (because problem 5 interferes with demonstrating it). A subtler problem.
Besides all of these, I could clean up some misleading comments written by confused people and I could make a number of minor performance improvements.
Perhaps I should pick only some of these fixes for near term inclusion in the source tree.
Re: NoiseRemoval.cpp
And here's a minor UI nuisance I just found...
7) If you change the attack/decay from the default of 0.15, you can't set it back to that value again exactly. (0.10 gets remembered in preferences.)
7) If you change the attack/decay from the default of 0.15, you can't set it back to that value again exactly. (0.10 gets remembered in preferences.)
Re: NoiseRemoval.cpp
I don't see that here.Paul L wrote:7) If you change the attack/decay from the default of 0.15, you can't set it back to that value again exactly.
I can either type in 0.15, or use the left right cursor keys to move the slider to 0.15. The setting is correctly saved in audacity.cfg as:
Code: Select all
NoiseAttackDecayTime=0.159/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)
Re: NoiseRemoval.cpp
And I forgot
8) Isolate was just broken from the beginning. Not sure whether to fix it or remove it. Is it supposed to be the difference of NR and original? Why bother when you can easy duplicate & invert? Is it supposed to pass noise with gain of 1? Then what the manual says about its purpose is misleading.
8) Isolate was just broken from the beginning. Not sure whether to fix it or remove it. Is it supposed to be the difference of NR and original? Why bother when you can easy duplicate & invert? Is it supposed to pass noise with gain of 1? Then what the manual says about its purpose is misleading.
Re: NoiseRemoval.cpp
If it is broken it needs fixing.Paul L wrote:Not sure whether to fix it or remove it.
It is supposed to "isolate" (separate out) sound that is like the captured profile.Paul L wrote:Is it supposed to be the difference of NR and original?
You can't do that with "Preview" while the effect window is open.Paul L wrote:Why bother when you can easy duplicate & invert?
Which does a better job of "isolating" a sound? The current "isolate" feature, or using "Remove" then invert and add to the original?
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)
Re: NoiseRemoval.cpp
I read this in the 2.0.5 manual page for the effect:
As for what the code is doing, somebody was trying to pass the noise with gain of 1 and the rest with gain of 0, but didn't think through how this interacts with the attack/release setting, with the weird results I wrote about above. And just try it, and you hear too much of the non-noise.
In fact Isolate gives such a false impression, it used to make me unfairly mistrustful of using the Removal.
But "exactly what the Noise Removal effect is removing" suggests to me the difference of the waveforms. The difference between the original and the reduced noise is not the same thing as passing the noise with a gain of 1.Isolate: Select this option to leave just the noise - useful if you want to hear exactly what the Noise Removal effect is removing.
As for what the code is doing, somebody was trying to pass the noise with gain of 1 and the rest with gain of 0, but didn't think through how this interacts with the attack/release setting, with the weird results I wrote about above. And just try it, and you hear too much of the non-noise.
In fact Isolate gives such a false impression, it used to make me unfairly mistrustful of using the Removal.
Last edited by Paul L on Tue Jul 29, 2014 11:02 pm, edited 1 time in total.
Re: NoiseRemoval.cpp
Regarding the handling of the first 1024 samples, I have written a fix that satisfies me.
I am finding too much to fix, I want someone else expert in this code to review me!
I am finding too much to fix, I want someone else expert in this code to review me!
Re: NoiseRemoval.cpp
Let me summarize what NR does:
Make a queue of windows (width 2048, step of 1024) and a corresponding queue of (arrays of) gains (one for each bin). It covers about twice the attack/decay time and always has an odd number of windows.
Repeatedly:
Shift a window of output from the queue using the final gain factors (if the queue is full; and this is where frequency smoothing happens -- averaging of the gain factor with the factors computed for other nearby frequencies). Shift a window of input into the queue. Assign the noise reduction factor as the gain for all bands of the new window.
Examine the middle of the queue and decide (for each band) if it's noise. If noise, do nothing. If not noise, reassign the gain to be 1. Then, calculate the exponential decay of that gain from 1 to the noise reduction factor over decay time; make the gain for the band not less than that decay curve for later windows. Do similar backwards in time for attack.
So, all gains are the reduction factor by default, UNLESS raised because the window is not noise or is near enough to some not-noise to be affected by the attack/decay setting. Okay?
But what should be the algorithm to isolate noise? This was not well thought out. It is assigning gain of 1 to noise and gain of 0 to not-noise in the middle of the queue. HOWEVER, attack/decay is still calculated. The assigning of 0 to not-noise in the middle cancels the effect of the decay calculation, but the not-noise can still be raised from 0, to values between 1 and the noise reduction, in the attack, resulting in that "swelling" I wrote about somewhere above. So, the less the noise reduction, the LOUDER is the non-noise in the mix made by isolate. AND, the frequency smoothing is still done too. The result is a weird and useless mess.
What is supposed to happen? Was it meant just to assign 0's and 1's without any of the time or frequency smoothing? Will that produce something useful to hear (though not the same as the difference of the original and noise-reduced sound)? Should it be implemented and documented that attack/decay and frequency smoothing and the noise reduction level all have no effect on Isolate?
Make a queue of windows (width 2048, step of 1024) and a corresponding queue of (arrays of) gains (one for each bin). It covers about twice the attack/decay time and always has an odd number of windows.
Repeatedly:
Shift a window of output from the queue using the final gain factors (if the queue is full; and this is where frequency smoothing happens -- averaging of the gain factor with the factors computed for other nearby frequencies). Shift a window of input into the queue. Assign the noise reduction factor as the gain for all bands of the new window.
Examine the middle of the queue and decide (for each band) if it's noise. If noise, do nothing. If not noise, reassign the gain to be 1. Then, calculate the exponential decay of that gain from 1 to the noise reduction factor over decay time; make the gain for the band not less than that decay curve for later windows. Do similar backwards in time for attack.
So, all gains are the reduction factor by default, UNLESS raised because the window is not noise or is near enough to some not-noise to be affected by the attack/decay setting. Okay?
But what should be the algorithm to isolate noise? This was not well thought out. It is assigning gain of 1 to noise and gain of 0 to not-noise in the middle of the queue. HOWEVER, attack/decay is still calculated. The assigning of 0 to not-noise in the middle cancels the effect of the decay calculation, but the not-noise can still be raised from 0, to values between 1 and the noise reduction, in the attack, resulting in that "swelling" I wrote about somewhere above. So, the less the noise reduction, the LOUDER is the non-noise in the mix made by isolate. AND, the frequency smoothing is still done too. The result is a weird and useless mess.
What is supposed to happen? Was it meant just to assign 0's and 1's without any of the time or frequency smoothing? Will that produce something useful to hear (though not the same as the difference of the original and noise-reduced sound)? Should it be implemented and documented that attack/decay and frequency smoothing and the noise reduction level all have no effect on Isolate?