NoiseRemoval.cpp

I have read more, and now I also blame 9298 for changing the geometric averaging of gain factors in frequency smoothing (which I think makes more sense) to arithmetic.

It seems a lot of intermediate results stored as dB were changed by somebody to ratios, BUT not all the changes necessary for consistency happened. This changed the frequency smoothing and the attack/decay in bad ways, and the fixes to that seem not yet complete.

Tortoise showed fewer revisions in the Revision Graph than in the “Show Log” dialog, before I discovered the “Show all revisions” button, so I may not have identified the exact revisions that introduced bugs. Still there is a story here of some things getting messed up and only partly restored. It was 9290 that introduced much of the badness.

Comments for rev 9290:

“Change NoiseRemoval processing to use new RealFFTf function for improved performance
also change variable definitions from exp(log(a)+log(b)) to a*b for improved performance”

The change did remove some calls to log10 and pow, but made what must have been unintended changes to the results!

I just tried this simple experiment:

Take some speech including pauses. Duplicate. Apply Noise Removal. Invert the original. Mix and render the two tracks.

The result is a whispery thing indicating the difference of tracks. Perhaps not what “Isolate” was meant to do, which is pass the noise through with a gain of 1, instead of the difference of original and reduced noise. But still a better indication of how much the effect is changing my sound inside words.

The resulting wave often looks “furry” and zooming in shows it zigzagging with each sample – in other words, some Nyquist frequency stuff superimposed on the other differences – the result of that mistaken zeroing out of that frequency before the inverse FFT.

Still, the aural impression of this difference is MUCH quieter than what the confused Isolate button feature is doing. Try isolate with a long attack and a low noise reduction factor – you hear way too much non-noise passed through, and it often “swells” in loudness before pauses, then drops down again, all of which I know how to explain from what the code is doing.

So I assume you now mean r9290, right? Google Code Archive - Long-term storage for Google Code Project Hosting. .

Can you give steps to reproduce the bug in attack/decay and handling DC?


Gale

Neither effect would be obvious I think. They are differences in calculated results more than roundoff, introduced by what was supposed to be a performance improvement only according to the comments in svn.

Gale, I tried this extreme example:

Make a track, generate 1 s of sine wave at 11025 Hz (that’s 44100/4), amplitude .99. Make that your noise profile.

Make a new track, generate some silence, select it all, go to Nyquist prompt, type:

(hzosc 22050.0 *table* 90)

The result is a big triangular wave with exactly two samples period.

Do we agree that noise removal should do nothing to that wave, because the spectrum is completely unlike that of the noise?

But try it, you get silence.

Try this formula instead to get a sound that is all DC:

(snd-offset (s-rest 1) 0.5)

Not a nice sound, but can we agree Noise removal “should not” affect it? But it is also silenced.

I must think more about how to demonstrate that attack and release are not right, and that frequency smoothing is no longer as Dominic Mazzoni intended.

Will you test a few-lines change if I write it for you?

I have identified a few different problems, all in one source file, but I might not persuade you to take all of my changes.

Try this, to demonstrate that attack times are only half as long as they are supposed to be. (The particular numbers are not very important, we just need tone significantly louder than noise.)

New project. Generate 2 s of white noise, amplitude .5. View it in Waveform dB. Do Noise removal, Get Noise Profile.

Hit right arrow, generate tone, 440 Hz Sine wave amplitude .99, 2 seconds. Ctrl-f, ctrl-j, ctrl-a: Now tone follows noise in a single clip all of which is selected.

Now do noise removal with 48 dB reduction and 1 s attack/decay.

The envelope of the noise should drop from -6 to -54, and does nicely. It should rise in anticipation of the tone – that is attack time. The rise in the envelope should be exponential, meaning a straight line in dB view, and that appears roughly so.

But the duration of this rise is about .5 seconds, not 1 second.

I have posted at Nabble too. http://audacity.238276.n2.nabble.com/bugs-in-Noise-Removal-effect-td7562446.html

For comparison, Noise Removal in 1.3.3 reduced the bulk of the waveform to -20.6 dB and 1.2.6 kept most of the waveform at the same level but with the amplitude sharply reduced for about 1/10th of a second in numerous places.

So what is the reason in the code for the current behaviour? What makes Audacity see the audio not in its profile as something to be removed? Are there any cases in real world audio where that behaviour would be beneficial?


Steve discovered a while ago that

The overlapping FFT windows each remove the DC offset over the period of each window. That just leaves the final window that does not have the offset completely removed.

Apart from the final glitch, the DC removal is arguably better than in Normalize if the whole track does not have offset.

Are there disbenefits from removing offset as well as noise?


Gale

These changes were simply mistakes introduced in version 9290 which was supposed to be for performance only.

In my opinion, Normalizer should be made a better Normalizer. It is not the purpose of this effect to normalize.

I have also written a fix for the frequency smoothing which accidentally became arithmetic when it should be geometric. Though it may be hard to make the strong case for it, showing why arithmetic averaging is wrong, but it is restoring Dominic’s original intent.

Steve discovered a while ago that

The overlapping FFT windows each remove the DC offset over the period of each window. That just leaves the final window that does not have the offset completely removed.

Apart from the final glitch, the DC removal is arguably better than in Normalize if the whole track does not have offset.

Where did Steve say that?

I see there is something weird going on at start and end. In my examples, in fact the last 1024 samples of DC or Nyquist frequency are not silenced but fade in with a half a Hann window.

When I attempt a fix, now the beginning of the sound has such a fade in.

Something else seems off and I didn’t catch that by reading.

Um, are you having problems compiling Audacity? What platform are you on?

At the moment, after having tested in 1.3.3 as above I am only getting a reduction of noise to -24 dB whatever noise reduction level I select. And the attack/decay is not changing with setting. I will have to reboot later (I’m on Windows 8 at the moment).


Gale

Off the public forums.


Gale

It is not always clear which mean one gets, especially when dB are involved, thus mistakes happen easily enough:

;; Linear magnitudes
(setf li '(1.0 0.3 0.6 0.8))
;; A-mean in dB
(print (linear-to-db (* (/ 1.0 (length li)) (apply '+ li))))
;; G-mean in dB
(print (linear-to-db (expt  (apply '* li) (/ 1.0 (length li)) )))
;; G-mean equals A-mean over dB-values
(print (* (/ 1.0 (length li)) (apply '+ (mapcar 'linear-to-db li))))

“G-mean equals A-mean over dB-values.” Yes, the ApplyFreqSmoothing function has always done arithmetic averaging. But whereas originally it did that to dB values, version 9290 caused it to be done to gain factors.

I think in this case it makes sense to have “A-mean over dB-values” or the equivalent computation of G-mean over gain factors.

Windows, and I am not having problems, but surely somebody else has to test my proposed patches.

Version 9290 broke the attack and decay, and 10512 changed it to its present state, which still has that factor of 2 error. I don’t know which version was in Audacity 1.3.3. Was it 5586? The attack and decay feature does not yet exist in that version.

It came up in a discussion about voltage bias on audio signals, about 18 months / 2 years ago. Gale has an excellent memory :wink:

I don’t agree that it is “silenced”, because DC is already silent.
DC is not valid audio, so it shouldn’t be present in audio signals in the first place. In audio hardware it is standard practice to decouple DC.

Considering that Noise Removal is intended to be an audio effect (rather than a “scientific transformation”), what is the practical benefit for retaining DC offset?

Maybe there is something below 43 Hz that is not really DC but excites that lowest band of the FFT variably?

There’s a similar issue with your other example.
From Wikipedia Nyquist–Shannon sampling theorem - Wikipedia

Modern statements of the theorem are sometimes careful to explicitly state that x(t) must contain no sinusoidal component at exactly frequency B, or that B must be strictly less than ½ the sample rate


Discussion about low frequency performance is not quite the same issue as discussion about DC performance.
IF we accept (and I’m not saying that we should) that the Noise Removal effect discards DC, then low frequency response depends on the FFT size. With an extremely large FFT size very low frequencies are supported, but with a small FFT size low frequencies will be considerably attenuated. However, we probably don’t want to use an “extremely” large FFT size. Although I’ve found that for some material, better noise reduction can be achieved by doubling the size, I expect that unwanted effects will occur if the size is too great (I’ve not tested). It therefore seems that there is a reasonable argument for supporting DC - not because we really want to retain DC, but simply that we don’t want to roll-off low frequency audio prematurely.