void EffectNoiseRemoval::Cleanup() { int i; EndFFT(hFFT); if (mDoProfile) { ApplyFreqSmoothing(mNoiseThreshold); } for(i = 0; i < mHistoryLen; i++) { delete[] mSpectrums[i]; delete[] mGains[i]; delete[] mRealFFTs[i]; delete[] mImagFFTs[i]; } delete[] mSpectrums; delete[] mGains; delete[] mRealFFTs; delete[] mImagFFTs; delete[] mFFTBuffer; delete[] mInWaveBuffer; delete[] mWindow; delete[] mOutImagBuffer; delete[] mOutOverlapBuffer; }
void EffectNoiseRemoval::RemoveNoise() { int center = mHistoryLen / 2; int start = center - mMinSignalBlocks/2; int finish = start + mMinSignalBlocks; int i, j; // Raise the gain for elements in the center of the sliding history for (j = 0; j < mSpectrumSize; j++) { float min = mSpectrums[start][j]; for (i = start+1; i < finish; i++) { if (mSpectrums[i][j] < min) min = mSpectrums[i][j]; } if (min > mNoiseThreshold[j] && mGains[center][j] < 0.0) mGains[center][j] = 0.0; } // Decay the gain in both directions; // note that mOneBlockAttackDecay is a negative number, like -1.0 // dB of attenuation per block 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] < mNoiseGain) mGains[i][j] = mNoiseGain; } 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] < mNoiseGain) mGains[i][j] = mNoiseGain; } } // Apply frequency smoothing to output gain int out = mHistoryLen - 1; // end of the queue ApplyFreqSmoothing(mGains[out]); // Apply gain to FFT for (j = 0; j < mSpectrumSize; j++) { float mult = pow(10.0, mGains[out][j] / 20.0); mRealFFTs[out][j] *= mult; mImagFFTs[out][j] *= mult; if (j > 0 && j < mSpectrumSize - 1) { mRealFFTs[out][mWindowSize - j] *= mult; mImagFFTs[out][mWindowSize - j] *= mult; } } // Invert the FFT into the output buffer FFT(mWindowSize, true, mRealFFTs[out], mImagFFTs[out], mOutWaveBuffer, mOutImagBuffer); // Hanning window WindowFunc(3, mWindowSize, mOutWaveBuffer); // Overlap-add for(j = 0; j < mWindowSize; j++) mOutOverlapBuffer[j] += mOutWaveBuffer[j]; // Output the first half of the overlap buffer, they're done - // and then shift the next half over. if (mOutSampleCount >= 0) { // ...but not if it's the first half-window mOutputTrack->Append((samplePtr)mOutOverlapBuffer, floatSample, mWindowSize / 2); } mOutSampleCount += mWindowSize / 2; for(j = 0; j < mWindowSize / 2; j++) { mOutOverlapBuffer[j] = mOutOverlapBuffer[j + (mWindowSize / 2)]; mOutOverlapBuffer[j + (mWindowSize / 2)] = 0.0; } }
void EffectNoiseRemoval::RemoveNoise() { int center = mHistoryLen / 2; int start = center - mMinSignalBlocks/2; int finish = start + mMinSignalBlocks; int i, j; // Raise the gain for elements in the center of the sliding history for (j = 0; j < mSpectrumSize; j++) { float min = mSpectrums[start][j]; for (i = start+1; i < finish; i++) { if (mSpectrums[i][j] < min) min = mSpectrums[i][j]; } if (min > mSensitivityFactor * mNoiseThreshold[j] && mGains[center][j] < 1.0) { if (mbLeaveNoise) mGains[center][j] = 0.0; else mGains[center][j] = 1.0; } else { if (mbLeaveNoise) mGains[center][j] = 1.0; } } // Decay the gain in both directions; // note that mOneBlockAttackDecay is less than 1.0 // of linear attenuation per block 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; } } // Apply frequency smoothing to output gain int out = mHistoryLen - 1; // end of the queue ApplyFreqSmoothing(mGains[out]); // 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]; // Invert the FFT into the output buffer InverseRealFFTf(mFFTBuffer, hFFT); // Overlap-add for(j = 0; j < (mSpectrumSize-1); j++) { mOutOverlapBuffer[j*2 ] += mFFTBuffer[hFFT->BitReversed[j] ] * mWindow[j*2 ]; mOutOverlapBuffer[j*2+1] += mFFTBuffer[hFFT->BitReversed[j]+1] * mWindow[j*2+1]; } // Output the first half of the overlap buffer, they're done - // and then shift the next half over. if (mOutSampleCount >= 0) { // ...but not if it's the first half-window mOutputTrack->Append((samplePtr)mOutOverlapBuffer, floatSample, mWindowSize / 2); } mOutSampleCount += mWindowSize / 2; for(j = 0; j < mWindowSize / 2; j++) { mOutOverlapBuffer[j] = mOutOverlapBuffer[j + (mWindowSize / 2)]; mOutOverlapBuffer[j + (mWindowSize / 2)] = 0.0; } }