How do you remove a specific frequency from a signal?

I have a signal which is basically a sine wave at 20hz with some randomness added to it. After the real fft I can clearly identify the peak in the 20th bin, but when zeroing this bin and those sorrounding it and converting back to time domain the whole signal is gone for good, where I would expect to see the "random" part of the signal more or less intact.


Below is a picture that has:

  • Top graph has the noiseless 20Hz sine wave sampled at 100Hz (blue) and the noisy sine wave (red).

  • Bottom graph has the actual noise signal added (red) and the noisy signal filtered with an IIR notch filter with a notch centred at 20Hz (blue).

Apart from the group delay between the original noise and the output of the notch filter, the two are very similar.

R code to implement this is below the graph.

enter image description here

The frequency response of the notch filter is as below.

enter image description here

R Code


f <- 20
fs <- 100
phi <- 2*pi*0.12987892374

T <- 100
t <- 0:(T-1)

signal <- sin(2*pi*f/fs*t+phi)
noise <-  rnorm(T,0,1)
noisy_signal <- signal + noise

alpha <- 0.9

num <- c(1, -2*cos(2*pi*f/fs), 1)
den <- c(1, -2*alpha*cos(2*pi*f/fs), alpha*alpha)

filtered <- signal::filter(num,den,noisy_signal)

plot(noisy_signal, type="l", col="red",  lwd=10)
lines(signal, type="l", col="blue", lwd = 3)
title("Noiseless signal (blue) and noisy signal (red)")

plot(filtered, col="blue", lwd = 4)
lines(noise, col="red",  lwd=3)
title("Filtered signal (blue) and original noise signal (red)")
  • 1
    $\begingroup$ Thanks peter. Now the challenge for me is designing such filter usin scipy.signal. Great answer anyway :) $\endgroup$ – cyberguijarro Nov 4 '15 at 15:53
  • $\begingroup$ No worries. Sorry, I'm forcing myself to answer DSP.SE questions in R so that I learn the language. For python, try scipy.signal.lfilter and set b = [1, -2*cos(2*pi*f/fs),1] and a = [1, -2*alpha*cos(2*pi*f/fs), alpha*alpha]. $\endgroup$ – Peter K. Nov 4 '15 at 15:56
  • $\begingroup$ Kind of a stupid question here, but right now I'm beginning to doubt everything: the filter has to be applied in the frequency domain (to the FT transform), right? Also, I'm using real FT, so the output is actually half of the input data... does this affect parameters in any way? $\endgroup$ – cyberguijarro Nov 4 '15 at 16:37
  • $\begingroup$ The code above does not apply the filter in the frequency domain, though the implementation of signal::filter may do so. If you put $N$ points in, your filter output should also be $N$ points. $\endgroup$ – Peter K. Nov 4 '15 at 17:01
  • 1
    $\begingroup$ @Travasaurus Yes, f is the frequency in Hz, fs is the sampling frequency, and alpha is... sort of how wide the notch is. The closer alpha is to 1, the narrower the notch; the further away from 1 it is, the wider it is. $\endgroup$ – Peter K. Nov 23 '20 at 23:38

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.