David Van Brink, 2000 October, A bit of recreational computing.

An Experiment In Noise Reduction

To recover some old music of my band "Science", to post on MP3.com, I had to digitize off my only copy of the music. This, unfortunately, was on a 15 year old TDK D-30 cassette. The quality wasn't all that great. There was a lot of tape hiss. It was pretty hard to listen to.

Since I'd written the sequencing software ("Synthestra") all those years ago, it seemed only fitting that now, 15 years later, I should have to write some more software to preserve these sonic relics of my past, so I tried my hand at writing some noise-reduction software.

The results of four evening's work were quite satisfying! Using some Fourier transform code I'd had lying around (written from scratch, of course), and some online info about AIFF files, I cobbled something together that seemed to reduce the audible tape hiss by about half.

Example 1: Voice and Fan Noise

Input File
Noise File
Output File

Example 2: Test Tone and Hum

Input File
Noise File
Output File

Examples with controllers embedded in page


Here's a little about how that was done.

Two files are used, the "input" file, and the "noise" file, which characterizes the sort of noise you want to remove.

The technique is fairly simple. The noise file is run through a series of fft windows. The amplitudes of each frequency component is averaged across the entire input file.

Then, the input file is run through a series of fft windows, and the amplitudes of each frequency component is reduced by the amount found in the noise file.

Note that you cannot do this with linear filters! Linear filters will multiply each frequency component by some amount, whereas this technique subtracts some amount from each component.

If the noise is actually present throughout the input file, the subtraction will always yield a nonnegative result. The algorithm does not assume that however, and pins the value to zero, should it go negative after the subtraction.

That all sounds good -- but it turns out that to stitch the windows together again without clicks, you need to overlap quite a bit.

So, before applying an FFT to each 512 sample window, I apply a trapezoid window to it, tapering from 0 to full across 16 samples. This removes some of the end-stitching high frequencies.

Then I apply the FFT, and subtract out the noise.

Then, I apply a triangle window centered over the middle 128 bytes, going from 0 at sample number 192, to full at 256, and back to 0 at 320.

The window slides across the input file in increments of just 64 samples.

Another advantage of altering a file in this manner is that no phase-change is introduced during the manipulation.

I don't believe this technique is unique, by any means. But I'm strictly barnstorming this method, playing, ah, by ear, as it were.


The code runs on MacOS, and is compiled for PowerPC only. It runs just a little bit below realtime, well, within a factor of two, anyway, on a 300 MHz 604e (Power Macintosh 8600/300).

Download Application

Download Source Code for CodeWarrior on Mac

The code would probably be straightforward to port for someone "skilled in the craft." It doesn't have any user interface to speak of, but does do things like call "NewPtr()" instead of "malloc()".


Feel free to email me with any comments or questions! -- dvb 2000, poly@omino.com