Humming noise detection¶
Humming noise¶
Low frequency hums are typically caused by poor electrical isolation on the recording/copying equipment. Usually, they correspond to the frequency of the powerline (50 or 60Hz).
Creating synthetic hums¶
To simulate this phenomenon, we will add a synthetic 50Hz sinusoid plus some harmonics to a clean audio signal:
from IPython.display import Audio
from essentia import Pool, db2amp
from essentia.standard import (
Windowing,
Spectrum,
FrameGenerator,
MonoLoader,
Clipper,
HumDetector
)
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (12, 9)
EPS = np.finfo(np.float32).eps
def spectrogram(audio, frame_size=2048, hop_size=512):
"""
Auxiliary function to compute spectrograms.
"""
window = Windowing(size=frame_size)
spectrum = Spectrum(size=frame_size)
pool = Pool()
for frame in FrameGenerator(audio,
frameSize=frame_size,
hopSize=hop_size):
pool.add("logspectrogram", spectrum(window(frame)))
return 10 * np.log10(pool["logspectrogram"].T + EPS)
audio_file = "../../../test/audio/recorded/Vivaldi_Sonata_5_II_Allegro.wav"
audio = MonoLoader(filename=audio_file)()
sr = 44100
# Generate a 50Hz tone.
time = np.arange(len(audio)) / sr
freq = 50
hum = np.sin(2 * np.pi * freq * time).astype(np.float32)
# Add odd harmonics via clipping.
hum = Clipper(min=-0.5, max=0.5)(hum)
# Attenuate the hum 30 dB.
hum *= db2amp(-30)
audio_with_hum = audio + hum
Now we can plot the spectrograms of the clean and altered versions and visualize the difference. We will plot only the 50 first bins of the spectrum to focus on the frequencies around the hum:
# Plot the first 50 FFT bins only.
max_bin = 50
spectrum_bin_freq = max_bin / 1025
f, ax = plt.subplots(2)
for i, (a, t) in enumerate([(audio, "Clean audio"),
(audio_with_hum, "Audio with a 50Hz hum and harmonics")]):
ax[i].matshow(
spectrogram(a)[:max_bin, :],
aspect="auto",
origin="lower",
extent=[0, time[-1], 0, spectrum_bin_freq * sr / 2]
)
ax[i].set_xlabel("(s)")
ax[i].set_ylabel("(Hz)")
ax[i].set_title(t)
ax[i].xaxis.set_ticks_position("bottom")
f.tight_layout(pad=2.0)
Now we can listen to the original audio:
Audio(audio, rate=sr)