NoiseRemoval.cpp
Posted: Fri Jul 25, 2014 7:46 pm
Who can help me understand this file? I see no names in it besides Dominic Mazzoni. A couple things puzzle me.
Code: Select all
mOutSampleCount += mWindowSize / 2; // what is this for? Not used when we are getting the profile?
Code: Select all
// Apply gain to FFT
for (j = 0; j < (mSpectrumSize-1); j++) {
mFFTBuffer[j*2 ] = mRealFFTs[out][j] * mGains[out][j];
mFFTBuffer[j*2+1] = mImagFFTs[out][j] * mGains[out][j];
}
// The Fs/2 component is stored as the imaginary part of the DC component
mFFTBuffer[1] = mRealFFTs[out][mSpectrumSize-1] * mGains[out][mSpectrumSize-1];But the effect is not in fact to compute the difference between what would be returned with Remove, and the original signal. Maybe that is proper, because with phase shifts of passed frequencies, the aural impression would not be correct. But perhaps the better way to compute this would be to compute all gain factors as if for noise removal, then apply one minus gain to the frequencies just before the inverse FFT?Select this option to leave just the noise - useful if you want to hear exactly what the Noise Removal effect is removing.
What happens if you change it from 10 to 20?Paul L wrote:2) I understand why there is division by 20 calculating mNoiseAttenFactor. I understand why division is by 10 not 20 when computing mSensitivityFactor because it is used in comparison of squared amplitudes. I do not understand why division is by 10 not 20 when computing mOneBlockAttackDecay which affects decay of gain factors that are not squared.
What happens if you change it?Paul L wrote:3) Would it make more sense to take geometric means, not arithmetic means, in ApplyFreqSmoothing, since these are multiplicative factors that are being averaged?
You're correct, but in NoiseRemoval.h it has a contradictory comment:Paul L wrote:4) In this line:Isn't the simple answer, "to make processSamples progress toward termination" ?Code: Select all
mOutSampleCount += mWindowSize / 2; // what is this for? Not used when we are getting the profile?
Code: Select all
// Variables that only exist during processing
WaveTrack *mOutputTrack;
sampleCount mInSampleCount;
sampleCount mOutSampleCount;
Does that work better?Paul L wrote:But perhaps the better way to compute this would be to compute all gain factors as if for noise removal, then apply one minus gain to the frequencies just before the inverse FFT?
Regarding the FFT window size, a larger window size can give (subjectively) better noise reduction with some material, so yes there is a case for making that an advanced control. On the other hand, many users already find this effect intimidating / too difficult and additional "advanced controls" would make that worse.Paul L wrote:7) There are two hidden magic numbers in the code, the FFT window size of 2048 and the 50 millisecond minimum signal time that influences the exact noise detection criterion. Might these make sense as advanced controls?
The real part holds DC and Nyquist respectively, it's the imaginary part (sine) that is always 0.5) In these lines:
Code: Select all
// Apply gain to FFT for (j = 0; j < (mSpectrumSize-1); j++) { mFFTBuffer[j*2 ] = mRealFFTs[out][j] * mGains[out][j]; mFFTBuffer[j*2+1] = mImagFFTs[out][j] * mGains[out][j]; } // The Fs/2 component is stored as the imaginary part of the DC component mFFTBuffer[1] = mRealFFTs[out][mSpectrumSize-1] * mGains[out][mSpectrumSize-1];
I believe the result is that mFFTBuffer[0] and mFFTBuffer[1] always become 0 because the corresponding entries of mRealFFTs are always 0. The squares of the untransformed coefficients are in the first and last entries of mSpectrums[out] and were never copied into mRealFFTs. We have lost the signs of ths coefficients by now.
It's correctly handled, as far as I can see.steve wrote:If I recall (I've not checked the code), the DC component is discarded.
Code: Select all
for(i = 1; i < (mSpectrumSize-1); i++) {
mRealFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i] ];
mImagFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i]+1];
mSpectrums[0][i] = mRealFFTs[0][i]*mRealFFTs[0][i] + mImagFFTs[0][i]*mImagFFTs[0][i];
mGains[0][i] = mNoiseAttenFactor;
}
// DC and Fs/2 bins need to be handled specially
mSpectrums[0][0] = mFFTBuffer[0]*mFFTBuffer[0];
mSpectrums[0][mSpectrumSize-1] = mFFTBuffer[1]*mFFTBuffer[1];