I have an acoustic signal of a test and I want to remove the "thin"
peaks, because they don't really affect the structure that I'm
studying. For that I've thought of a Low pass filter in order to
retain only frequencies below 300 Hz.
If this is accurate, that is, you have an acoustic signal that exists from baseband to 300 Hz, then yes, what you want to do is a digital low-pass filtering operation to retain all energy below 300 Hz, and discard energies above that.
My aim is to count the peaks of the filtered signal above 3 sigma
(Standard Deviation). I'm programming in C# and I don't know if there
is a direct (and simpler way) of doing this but what I'm doing now is
Your intuition is correct - you want to remove frequencies below 300 Hz, so naturally you think to transform your signal into the Fourier domain, clobber unwanted frequencies, and then transform back. There are some issues with this method:
- Firstly, this method is taboo in the DSP community, (and for decent reasons), although there are cases where you can get away with it, depending on your application. Some background: Nulling out unwanted co-efficients in a transform domain and inverse transforming back into the original domain is used in denoising especially in wavelets, and it also makes intuitive sense, (and correctly so). The problem with doing this in the Fourier domain is that the basis function of the DFT are global, and not local like they are in wavelets. In other words, you can clobber our wavelet co-efficients and affect only local areas in your signal (ie, small parts of your signal) - but doing so in the Fourier domain affects all your signal.
- Expanding on the above background, when you "boxcar" your frequency domain, (ie, mask it with 1s and 0s that either allow or disallow certain frequencies), this is the same as convolving your time-domain signal with a sinc function, that carries on forever. This is why simply culling out unwanted frequencies - while acceptable in some applications - will introduce 'ringing/smearing' in the time domain.
- Instead what is usually done, is that people create filters (masks in the frequency domain that are not sharp 1s and 0s, but more graceful), such that their equivalent transform back into the time-domain does not have the effective infinite extent of sinc function, (that is, the decay of the sidelobes is much faster than that of a sinc). This then provides a nice trade-off between removing unwanted frequencies, and not having to pay the price of extreme ringing/smearing in the time domain.
Armed with this task at hand, what you need to do is the following:
- Create a digital low pass filter in some other software such as MATLAB or Python. You can create a simple FIR filter for your purposes. (Do not use an IIR because you are working with an audio application and default IIR filters will warp your phase, but thats another story). When you make your filter, you will simply have a vector of numbers, of a length you chose. The larger the length of the filter, the sharper the transitions in the frequency domain, but also the larger the delay, so this is a trade-off you can experiment with. At the end of the say though, you will $1$ by $N$ vector of numbers. This is your filter. Let us call it $h[n]$
- You have your audio signal, let us call that $s[n]$. The planets are not aligned, so most likely your audio signal is of a different length than your filter, and let us say it is of length $M$. So your signal $s[n]$ is simply a $1$ by $M$ vector of numbers.
- Your objective is to filter $s[n]$ by $h[n]$. There are a number of ways to do this. Since you already seem to have access to the FFT in C#, we will use the FFT method. In the FFT method, you want to multiply the Fourier transform of your filter, (call it $H(f)$), with the Fourier Transform of your signal, (call it $S(f)$).
- We doing a linear convolution, (as opposed to a circular one), but in the frequency domain, so we have to take extra care when it comes to FFT sizes. If you did the linear convolution in the time domain, the resulting filtered signal would be of length $N + M -1$. This is then the FFT size you need to use.
- You are almost done. All you need to do now is take the $N+M-1$ length FFT of your filter, $h[n]$. Take the $N+M-1$ length FFT of your signal, $s[n]$. Multiply them together. Then take the $N+M-1$ length IFFT of this element-by-element product, and viola, you have filtered your signal.
Hope this helped.