Audacity's noise reduction filter is pretty good. Before I use it, though, I want to know if I'm missing out on any fundamentally different approaches that may work better.

I have some recordings of my brother singing and playing piano. It's pretty good as-is, but there's noticeable white noise. There's also a 60Hz signal that's audible (but not really objectionable) during quieter portions of the recording. Audacity does a pretty good job of getting rid of them. So I'll almost certainly just use that, esp. since very recent audacity changes apparently have improved the noise-reduction filter. (or maybe just the config UI? I didn't look at the diffs).

The comments at the start of the file describes the design pretty well, and what the settings sliders mean (esp. the frequency smoothing was a mystery until I thought to check the source, and found it had a great comment describing the design.)

It gets a profile of the kind of noise you want to remove from a clip of only noise. For the main pass, it FFTs the input, and silences every frequency bin that is below a threshold. So it's a bandpass filter that adapts to only let through frequencies with signals above the noise level for that bin. (Thresholds established from the noise profile.)

So my question is, are there other designs for noise filters that work any better? Mostly out of curiosity, since audacity works very well for my application. (noise energy distributed over a wide frequency range, signal I want to keep made up of fairly narrow frequencies.)


After a bit of searching, I found an article surveying some of the commercial software noise reduction options. For hiss/hum type noise removal (as opposed to crackles and pops), no approach other than noise-gates in multiple frequency bands was mentioned. The differences between implementations are in the default settings, the control knobs available, and things like that. (and whether the a noise sample is used to get a profile. Apparently there are faster implementations that do well without needing a noise sample to build a tailored profile of the noise to remove.)

So AFAICT, Audacity's noise reduction plugin works the same way as commercial software implementations.

(For pops and crackles, Audacity allows making rectangular selections on the spectrum plot. It might not have as sophisticated algorithms for filling in deleted glitches with similar-sounding audio from nearby, compared to some commercial software. IDK, I haven't tried that.)

The other thing I was interested in was what's up with recent development activity in Audacity's Noise Reduction filter:

Following the svn history of NoiseReduction.cpp, there are really only changes to the GUI for setting parameters, from it's appearance in SVN r13591 (Nov 10, 2014) up to latest change in r13895 (Jan 24, 2015).

It replaces the over-optimistically-titled NoiseRemoval.cpp. It appears to be a rewrite of the same basic design. The intro comment describing the design is only slightly changed, and some of the same comments are kicking around in the code. However, almost every line of code is different, and it's 1.9k lines of code instead of 870.

So it's probably not critical to get a pre-release build of Audacity 2.1 for noise removal. If you get chimes / dropouts where you don't want them, or otherwise have problems, then go for a new version. It looks at more data to decide if something is noise or not, as detailed below.

One critical part of the new filter now has several methods to choose from. (OLD_METHOD_AVAILABLE is not enabled by default. And DM_DEFAULT_METHOD = DM_SECOND_GREATEST)

(The code is well-commented. I mostly just read the comments, on the assumption that the code matches well enough.)

//***** NoiseReduction.cpp:1079
// Return true iff the given band of the "center" window looks like noise.
// Examine the band in a few neighboring windows to decide.
bool EffectNoiseReduction::Worker::Classify(const Statistics &statistics, int band)
   switch (mMethod) {
   case DM_OLD_METHOD:
         float min = mQueue[0]->mSpectrums[band];
         for (int ii = 1; ii < mNWindowsToExamine; ++ii)
            min = std::min(min, mQueue[ii]->mSpectrums[band]);
         return min <= mOldSensitivityFactor * statistics.mNoiseThreshold[band];
   // New methods suppose an exponential distribution of power values
   // in the noise; new sensitivity is meant to be log of probability
   // that noise strays above the threshold.  Call that probability
   // 1 - F.  The quantile function of an exponential distribution is
   // log (1 - F) * mean.  Thus simply multiply mean by sensitivity
   // to get the threshold.
   case DM_MEDIAN:
      // This method examines the window and all windows
      // that partly overlap it, and takes a median, to
      // avoid being fooled by up and down excursions into
      // either the mistake of classifying noise as not noise
      // (leaving a musical noise chime), or the opposite
      // (distorting the signal with a drop out). 
      if (mNWindowsToExamine == 3)
         // No different from second greatest.
         goto secondGreatest;
      else if (mNWindowsToExamine == 5)
         float greatest = 0.0, second = 0.0, third = 0.0;
         for (int ii = 0; ii < mNWindowsToExamine; ++ii) {
            const float power = mQueue[ii]->mSpectrums[band];
            if (power >= greatest)
               third = second, second = greatest, greatest = power;
            else if (power >= second)
               third = second, second = power;
            else if (power >= third)
               third = power;
         return third <= mNewSensitivity * statistics.mMeans[band];
      else {
         return true;
         // This method just throws out the high outlier.  It
         // should be less prone to distortions and more prone to
         // chimes.
         float greatest = 0.0, second = 0.0;
         for (int ii = 0; ii < mNWindowsToExamine; ++ii) {
            const float power = mQueue[ii]->mSpectrums[band];
            if (power >= greatest)
               second = greatest, greatest = power;
            else if (power >= second)
               second = power;
         return second <= mNewSensitivity * statistics.mMeans[band];
      return true;

(why isn't syntax highlighting working? I put <!-- language: lang-cpp --> before the code block :/)

I'm probably going to build audacity from this SVN checkout I already have, but I'm not planning to compare noise reduction between the latest dev build and the stable 2.0.6 release.


I am the author of the code you are reading. It appears you were an alpha user of Audacity 2.1.0 in advance of its release, which was only days ago. You have a version of the noise reduction effect with many experimental optional controls exposed to the user that are not in the release version.

You may be interested in what I wrote here about the inadequacies of the previous version of the effect that I tried to remedy with this rewrite. But the overall procedure remains unchanged.


  • Thanks for that link, some of the discussion sheds some light on significantly different ways of doing noise reduction (i.e. not just different ways for choosing which FFT bins to pass/reject), as well as good info on how audacity's filter chooses which frequency bins to gate. And the effect of choosing a good windowing function. Lots of neat stuff. :) Apr 17 '15 at 1:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.