# How do you remove noise to detect just the human voice?

How do you detect different sound frequencies and cut off parts in an audio file? Among instruments, how do you pick up the human voice?

-
Wasn't this question just posted and migrated to Signal Processing? – s0rce Nov 27 '12 at 3:50
hi user4795. To remove noise from a signal, the normal process it to apply a filter. A low pass filter, since noise typically has high frequency. Since you know the desired frequency range, you can use bandpass filter for this. Many ways to design a bandpass filter. All can be implemented in Mathematica. fyi, there used to be a signal processing add-on for Mathematica, but for some reason, it is no longer offered. Here is the API just fyi to give you an idea what can be done 12000.org/my_notes/faq/mma_notes/… – Nasser Nov 27 '12 at 4:05
@s0rce could you post the URL ? – Vitaliy Kaurov Nov 27 '12 at 4:19
@VitaliyKaurov This was the original question. I migrated it, but the OP deleted it and reasked it here again... – rm -rf Nov 27 '12 at 5:06
These kinds of questions are so typical in the Matlab newsgroup. Many people ask question about how to do this or that in Matlab, where the question is domain specific to some topic which has nothing to do with Matlab the language itself, but since someone wants to use Matlab for the implementation, they ask in that group. You won't believe the type of questions asked there. As Mathematica gets more popular, the same will happen here I am sure. – Nasser Nov 27 '12 at 5:29

A lot depends on your specific data. But if the noise is far from voice in frequency domain there is a simple brute-force trick of cutting off/out "bad" frequencies using wavelets. Let's import some sample recording:

voice = ExampleData[{"Sound", "Apollo11ReturnSafely"}]


WaveletScalogram is great for visualizing voice versus noise features:

cwt = ContinuousWaveletTransform[voice, GaborWavelet[6]];
WaveletScalogram[cwt, ColorFunction -> "AvocadoColors", ColorFunctionScaling -> False]


Voice is more rich and irregular in structure, noise is more monotonic and repetitive. So now based on the visual we can formulate a logical condition to cut out the noisy octaves (numbers on vertical axes):

cwtCUT = WaveletMapIndexed[#1 0.0 &, cwt, {u_ /; u >= 6 && u < 9, _}];
WaveletScalogram[cwtCUT, ColorFunction ->"AvocadoColors", ColorFunctionScaling -> False]


This is pretty brutal, like a surgery that cuts out good stuff too, because in this cases some voice frequencies blend with noise and we lost them. But it roughly works - signal is cleaner. You can hear how many background noises were suppressed (a few still stay though) - use headphones or good speakers. If in your cases noise is even further from voice in frequency domain - it will work much better.

InverseContinuousWaveletTransform[cwtCUT]


-
How did you make the decision on what was and wasn't noise? – rcollyer Nov 27 '12 at 5:44
@rcollyer I gave some explanation under WaveletScalogram image. Voice has rich irregular structure. Noise is monotonic and repetitive. – Vitaliy Kaurov Nov 27 '12 at 5:47
+1 nice. I did not use wavelets before. Stopped at frequency analysis at school ;) but this is useful to know you can do this sort of thing using wavelets. btw, your cwtThresh is not defined any where, so I get an error in that line. But last line works ok. – Nasser Nov 27 '12 at 5:58
@NasserM.Abbasi Thanks! I corrected the code, should work now. – Vitaliy Kaurov Nov 27 '12 at 6:20
Maybe I should have read it ... :P – rcollyer Nov 27 '12 at 6:24

What you need is BandpassFilter, which is new in version 9. Assuming your audio is sampled at 22400 Hz, you can do:

BandpassFilter[data, {60 π, 180 π}, SampleRate -> 22400]


to filter it to between 60-180 Hz.

-
wow, I had no idea that version 9 documentations are online now! – Nasser Nov 27 '12 at 9:10
This works for SampleSoundList, so for voice above, this would be done: Sound[BandpassFilter[voice[[1]], {60 π, 180 π}, SampleRate -> 22400]]. It did not work as well as the wavelet based denoising by @Vitaliy Kaurov – ubpdqn Dec 2 '12 at 10:03
@ubpdqn You'll have to filter the correct band for the sound sample that Vitaliy used. I was addressing OP's question where they wanted to filter their data (not shared) between 60 and 180 Hz. – rm -rf Dec 2 '12 at 15:23
@rm-rf thank you for the clarification – ubpdqn Dec 3 '12 at 8:30
Should that be BandpassFilter[data, {2 π 60, 2 π 180}, SampleRate -> 22400] for radian frequencies? That is, a coefficient of 2 π rather than π. – david Dec 3 '12 at 18:06