How to de-noise raw sound data

What techniques/algorithms can I use to remove noise from a raw recording of sound (voice)?

The purpose is to get a smoother graph (removing the "jaggedness"). What I have tried was to average-out small deviations by using the surrounding two values to either side, but ended up with distorted sound. What better way is there to "smooth-out" the graph?

migrated from stackoverflow.comAug 18 '12 at 14:26

This question came from our site for professional and enthusiast programmers.

• So is your goal in all this to simply produce a graphic representation of the sound, or do you have some other purpose in mind? – Daniel R Hicks Aug 19 '12 at 14:10
• @DanielRHicks: ambitious goal is to isolate phonetic-sounds for home-grown voice-recognition exercise ... – slashmais Aug 19 '12 at 17:07
• In that case going directly to an FFT may be the simplest approach. You can then just ignore FFT bands outside of your range of interest. – Daniel R Hicks Aug 19 '12 at 23:55

For what you intend to do, a low-pass filter is the way to go. Your statement about filtering frequencies vs filtering amplitudes is incorrect. Your signal contains many components at many frequencies, the amplitude of which varies in time, and the high frequency components are those causing the "jaggedness" and you want to get rid of them. Not sure why you say your signal is "constant frequency" - maybe you are getting confused by the sample rate?

What you have tried (averaging) is indeed a special case of low-pass filtering, but one with a frequency response far from being ideal. You should try a properly designed IIR or FIR filter. In particular, the FIR filter is not very different from what you tried - this is just a weighted combination of the samples neighboring each sample. But the choice of the coefficients is important and ensures that only unwanted components are eliminated. Note that an FFT is not the way to go. This question crops up here quite frequently under different forms, but in short - FFT, messing with coefficients, IFFT - is a bad idea.

By design, the output of a moving average filter (what you implemented) has less energy than the input. It is thus impossible for a moving average filter to cause distortion. If the input signal is in the [-1, 1] range, there is no way for an averaging filter to yield values outside this range. The "distorted sound" you observed was probably due to an implementation error on your side (overflow / clipping of integer values, signed values treated as unsigned value, or maybe incorrect in-place processing)...

EDIT: one thing worth mentioning is that there are situations in which a speech signal actually has high frequency components (appears "jagged", is noisy) - for example during a sss or shhh ; and removing those with a low-pass filter will affect its brilliance. Ideally, you'll want your low-pass filter to be active only when you detect that your speech signal is voiced - and inhibit it when you detect an unvoiced, noisy consonant.

• What filter bandwidth would you use for American English in the presence of AWGN, with no consonant detection? – Jim Clay Aug 18 '12 at 17:20
• Also, a wide averaging filter (i.e. low cut-off frequency) would distort the sound. Doesn't have to be clipping. – Jim Clay Aug 18 '12 at 17:21
• Using the phone bandwidth (cutoff at 4kHz) would be a good start if intelligibility is the sole goal. I wouldn't use 4kHz to clean up recordings of vocals on a studio production though :) From the original post, it's not clear what is the application. – pichenettes Aug 18 '12 at 17:34
• I take distortion in the sense: the input is a sine wave but the output is not (added harmonics), not in the sense "output signal will sound unintelligible". The only way for a digital filter to exhibit this behavior would be if it has gain for some input frequencies, causing the signal to clip. – pichenettes Aug 18 '12 at 17:39
• @JimClay I think it depends on what the definition if distortion is. :-) Personally I am not clear in this, there seems to be a colloquial meaning (ANY change in intelligibility) VS a more rigorous definition (non-linear operations that give rise to additional frequencies). – Spacey Aug 19 '12 at 15:32

Another interesting audio denoising technique exploits the fact that many sound recordings contain silent time intervals that contain only noise. Such sections can be chopped out of the recording to obtain a noise spectrum and then spectral gating can be applied to suppress noise. Take a look at the following links for detailed discussion on this technique:

Noise gate: http://en.wikipedia.org/wiki/Noise_gate

Noise removal in Audacity (an open source audio editing tool): http://wiki.audacityteam.org/wiki/Noise_Removal

Of course, this method rests on the assumption that the same noise source'' persists throughout the duration of the audio.

You should apply a low-pass filter on your signal. Look for such an algorithm. Hope this helps... Voice is low frequencies and usually noise is high frequencies.

• The recording I work with is just an array of byte-values, effectively constant frequency, just amplitude differences, where low-pass filters works with differences in the frequencies. – slashmais Aug 18 '12 at 10:08
• @slashmais - an array of values still contains many frequencies. just because the samples are regular in time doesn't mean that the signal as a whole cannot have many frequencies. even what you tried - averaging with values either side - can be thought of as a (rather poor) low pass filter. – andrew cooke Aug 18 '12 at 12:55
• @slashmais : if your data are discrete values, then you should probably do a FFT in order to apply a low-pass filter. Interesting math ahead ;-) but I would bet you can find some already well written/tested libs out there. – Sun Wukong Aug 18 '12 at 13:32
• you don't need to do an fft. a simple finite impulse response filter is simpler. for example here en.wikipedia.org/wiki/… is the average of three points as the op tried (if i understood right). – andrew cooke Aug 18 '12 at 13:56