Better way to mute fundamental baseband frequency?

I'm working on a project to monitor the fluctuations and harmonics present on standard 120VAC mains power. I built an adapter that drops the voltage from 120VAC to 12V and then down to 0.5-0.6 VAC nominal and feeds that into sound card input to convert it to digital form where I can analyze it with gnuradio.

The dominant frequency that is present of course is the fundamental mains power frequency (60Hz here in the US). I want to mute this frequency so I Can study all the other attributes of the signal.

I came up with a way to mute the fundamental 60Hz signal but I don't think it's the best way. My method is simple - it takes the current signal and adds the inverse of the same point on the signal to it. Picture a sine wave and a cosine wave plotted together and when added, they always add up to 0.

The problem is that I suspect this method may be adding artifacts to the output. I suspect so because I created another flow graph with sound card input and output sink and performed the same "add signal to its delayed inverse self" method I mentioned above. What I hear is a very distorted version of the actual input which includes an echo of the input signal.

Aside from the artifacts it does an amazing job of muting the 60Hz fundamental. So maybe it is the best way, but I want to crowd-source this challenge and ask the community for ideas on how to mute the 60Hz fundamental while adding little or no artifacts to the output signal.

Fig. 1: Flow graph and "zoomed out" scope focused on the current signal (blue) and the inverse delayed signal (green): Fig. 2: Zoomed in scope showing the calculated output (red line). Note that it does appear to show the precise fluctuations of the input signals while muting the fundamental as expected, I'm just suspicious that it's also a somewhat unrealistic representation due to my method of calculation. EDIT 1: Thank you @dan-boschen for the notch filter suggestion. To get a notch filter in my gnuradio flow graph, I used a FIR filter with a band_reject taps function (firdes.band_reject(1,samp_rate,56,64,2)). Playing with the start/stop/transition parameters doesn't change much. The fundamental is significantly attenuated but is still present and much stronger than the very minute signal deviations that are present, and can be heard using the other method (both methods are compared in the video through left and right audio channels) I just uploaded this video to illustrate the gnuradio flow graph, and left and right speaker channel comparison between FIR notch filter along, and FIR filter plus the "add to inverse last cycle" method I came up with.

I suspect the band_reject notch filter is tuned as best it can be. Perhaps there is another level of filtering I can apply. Maybe a series of band_reject filters? Looking for any ideas.

Use a notch filter such as the one shown in the figure below, where $\omega_n =2\pi 60/f_s$, where $f_s$ is your sampling rate, and $\alpha$ is chosen based on the bandwidth of the notch and how long you can allow for settling in the time domain; the tighter the filter bandwidth the longer it will take to settle; you can use a first order approximation of 10%/90% rise time = $\frac{0.35}{BW}$ where the BW is in Hz (and the amount of precision you can allow in the filter is an important factor---insufficient precision and $\alpha$ to close to 1 can lead to instability).  See this post for details: Transfer function of second order notch filter

Note the diagram below to facilitate implementation, mapping the coefficients to the transfer function as commonly referenced in Matlab and Octave. Do note that the signal flow below is going from right to left, which is opposite the diagram above (this was because my slide was showing how the implementation came from transposing the Direct Form II implementation). To be clear, the resulting coefficients are:

$b_0 = 1$

$b_1 = -2cos(\omega_n)$

$b_2 = 1$

$a_1 = -2\alpha cos(\omega_n)$

$a_2 = -\alpha^2$

A normalizing gain of $(1+\alpha)/2$ is added to the whole filter. Since $\alpha$ is typically close to 1, this can reasonably be omitted in most cases. • This works quite nicely, thank you. I found the necessary block in gnuradio (FIR filter with band reject taps: firdes.band_reject(1,samp_rate,56,64,2)). The fundamental is still present above the harmonics, so now I'm experimenting with it, to try and further minimize the fundamental. May 12 '17 at 15:13
• The above can work a lot better than a FIR for purpose of rejecting a single frequency. When you said "this works nicely" does that mean you actually implemented it? If you do I am sure others would be seeing the before and after and details of your actual implementation. May 12 '17 at 15:15
• Note that an IIR notch filter is a narrow frequency resonator that attempts to create a matching sinusoid to the input, and then subtracts that from the input. Same as the OPs original method, except with a low-order polynomial sinusoidal parameter estimator. Other estimators may do better in some situations. May 12 '17 at 17:30
• @hotpaw2 Interesting perspective on describing the placement of the IIR poles and zeros which is how this was derived. There was no attempt to create a matching sinusoid based on observation of the signal itself other than the parameters that were based on the center frequency of the null which was set apriori --which I could see described this way as a cancellation of course (as in any frequency rejection), but what you describe makes me think you are considering adaptive techniques which would also be interesting - What other estimators and what situations? May 12 '17 at 19:53
• The frequency "matching" is due to a stable IIR having a non-zero bandwidth, thus a slightly "pull-able" resonance frequency. May 12 '17 at 19:55