de-click via differentiation then limiting then integration

I had an idea for click-reduction via differentiation then limiting then integration.

  1. differentiate the waveform …
(multichan-expand #'slope s)

this produces a waveform with big spikes where there were clicks.

  1. Then use a limiter to reduce these big spikes,
    then integrate …
(multichan-expand #'integrate s)

to get back to the original waveform but now clicks reduced.

[ Normalization will be required after both differentiation and integration, after steps 1 & 2 ]

Here’s a before-after. IMO the “after” does sound less like a Geiger-counter

NB: this procedure only de-clicks , not de-hiss, ( it actually increases hiss slightly :cry: )

It’s putting thumps in the show. After has “fist smacking a pillow” sounds that Before does not have.

Do you have a killer sound system or good headphones?

Koz

Earbuds. Pressing them in my ear’oles for a better bass I can now hear the thumps.
I was concentrating on the bit from 1-to-3 seconds on the “before” and the corresponding bit on the “after”,
where the music is quietest and consequently the clicks/crackles are most obvious.

If I use a higher threshold for limiting it will cause less damage to the music …

I now need a limiter which rides the RMS envelope of the differentiated waveform, only chopping off the click spikes , leaving the show alone …

Interesting idea.
In effect it is acting as an amplitude dependent low pass filter.
I’m not sure of the maths, but for a given input amplitude, the slope increases rapidly with frequency so it makes the crackles stand out more.
Does this work any better than using a high-shelf filter with positive gain, then compressing the peaks, then applying a high-shelf filter with an equal amount of negative gain?

The problem with differentiation is that each sample relies on that one before, when reconstructing via integration.
A sample sequence:
(0 0 1 0.75 0 0.2 0 0)
After differentiation we’ll get:
(0 0 1 -0.25 -0.75 0.2 -0.2 0)
We now hard-clip at 0.5:
(0 0 0.5 -0.25 -0.5 0.2 -0.2 0)
…and integrate again:
(0 0 0.5 0.25 -0.25 -0.05 -0.25 -0.25)

That’s a coarse example, a limiter would rather distribute the first peak over the look ahead time.
I only want to emphase that a slight numerical error will cause the signal to drift out of balance, i.e. you’ll get a temporary DC-offset.
One could treat the positive and negative bands separately, cut off the numbers that cross the zero line and put it all together again.
You can also use the slope as a control signal too manipulate the original sound directly, where a steep slope is detected, an attenuation will be applied accordingly.
By the way, slope and integrate may not be ideal because they include the sample rate into their calculations. Slope will for instance have a value of 88200 for a jump from -1 to 1.
Here are some replacement functions and the sample from above as code (click “Debug” in the Nyquist prompt):

(defun integrator (s-in)
(biquad   s-in 1 0 0 1 1 0))
(defun differentiator (s-in)
  (biquad s-in  1 -1 0  1 0 0))
(setf sig (snd-from-array 0 44100 #(0 0 1 0.75 0 0.2 0 0)))
(snd-display sig) (terpri)
(snd-display (differentiator sig)) (terpri)
(snd-display (clip (differentiator sig) 0.5)) (terpri)
(snd-display (integrator (clip (differentiator sig) 0.5)))

There’s of course still a peak of 2 possible for the differentiator.

The noises this technique removes seem to include the entire sound spectrum, rather than a specific frequency range,
see the third take of the flac below which is the original crackly record minus the de-clicked version, (i.e. the noise-removed, isolated via destructive interference).

The limiter used to chop the spikes off the differentiated waveform had a 2 millisecond sustain, (much faster than a bog-standard compressor) , so any sounds occurring during the click and two-milliseconds immediately after were attenuated, no matter their frequency.

Yes you’re right Robert, I should have mentioned that when I said “normalize after differentiation and integration” that included removing DC offset.
The integrated waveforms do drift off within a few seconds and on longer sections would end up going off the scale.

Well done Trebor,
this seems to do a good job. Do you want to implement this in a single plug-in?
It is astonishing how many sorts of degradation one can encounter.
Here’s another corrupted file that you can try to clean:

I’ve used a non-linear filter to clean up the second part, namely a median filter with a 5 sample window.
This filter does not work as good as your method (with your file, I mean). A window of about 17 samples is necessary to get a similar result. Which leads to the conclusion that one should always take the right tool for the task at hand. Therefore, it would be nice to let the program recognize what kind of corruption has to be corrected.
The built-in filters (click-removal, clip-fix) couldn’t correct the above file perfectly.
However, the clip-fix tool does it reasonable (threshold 20) and the clicks will disappear after two passes; the bass suffers though.

That’s miraculous , where can I get a median filter ?

I tried cleaning your example with my technique, there was some improvement but nothing in comparison to your “after”.
As your frequent click noises are often less than 2 milliseconds apart, then a limiter isn’t going to respond quickly enough.

My technique of modifying the differentiated waveform does work with defects which are tens of milliseconds in duration ,
e.g. the two hit noises on this horn …

My median filter is actually only suited for this specific kind of impulse-noise.
You will maybe never encounter it in real life.
It’s absolutely unsuitable for high hiss–You’ll end up with white noise.
Nevertheless, it is a common filter for data, where edges should be preserved (image processing for instance).
Many click-removal employ the median filter, but not in this direct fashion, rather to evaluate detection features.
The plug-in below let’s you currently choose the window size, i.e from how many samples the median is taken. The higher, the more extreme values will be left out.
There’s also a setting for the percentile. This expands the plug-in to a minimum, maximum or whatever filter.
This choices do not make much sense for audio though (perhaps if positive and negative values were processed separately).
rjh-median.ny (1.44 KB)

Thanks for that

I’ve occasionally come across corrupted digital files which had noise like that.

Audacity logo median filtered.gif

You may be losing less signal than you think. If you subtract the original from the modified signal, there may be phase shifts in retained frequencies, giving the false impression that you are subtracting some of the real sound. If original is a sine wave and modified is shifted half a cycle, for instance, the difference is even louder than either.

Or in other words the power spectrum of the difference is not the difference of power spectra.

Is there a better way to calculate the perceptual difference of sounds?

If you use Nyquist’s slope and then integrate the result, the sound is not unchanged, but it loses the last signal and is offset to begin with a zero sample. This is not phase shifted, but perhaps the other steps introduced shifts.

Also the slope function seems always to assign a zero start time, contrary to the documentation, which might matter in other programs, but not in the sound returned to Audacity, which ignores the sound’s start anyway and only uses the sample sequence.

The destructive interference was just to get an approximate idea of the frequency content of what was being removed.

Superimposing the spectrograms ? …
before-after spectrograms showing the spectral content of noise removed.gif

Are those spectrograms really different?

Tell me how to make such pictures in case I need to demonstrate befores and afters too.

I was wondering if there is a way to present the difference of spectra aurally, better than just subtracting one signal from another.

I can see vertical spikes in the “before” spectrogram which aren’t in the “after”, their timing corresponds with the noises isolated by the destructive-interference method.

I used free photoshop-type software called GIMP to created a simple gif animation : (the fiddly bit was getting the two spectrograms perfectly aligned).

The difference can be detected by having the “before” and the “after” tracks playing simultaneously (and in-sync) and toggling between the recordings.

Of course there is that method, but is there any way to listen to something that approximates the difference of power spectra without that bit of murmur of the original that could only be phase shift?

Audacity’s noise removal for instance has an isolate radio button. I could not get rid of the murmur and naively thought at first that I was losing some signal with the noise. But maybe not.