.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/audio/signal_to_noise_ratio.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_audio_signal_to_noise_ratio.py: Signal-to-Noise Ratio =============================== Imagine developing a song recognition application. The software's goal is to recognize a song even when it's played in a noisy environment, similar to Shazam. To achieve this, you want to enhance the audio quality by reducing the noise and evaluating the improvement using the Signal-to-Noise Ratio (SNR). In this example, we will demonstrate how to generate a clean signal, add varying levels of noise to simulate the noisy recording, use FFT for noise reduction, and then evaluate the quality of the reconstructed audio using SNR. .. GENERATED FROM PYTHON SOURCE LINES 10-11 Import necessary libraries .. GENERATED FROM PYTHON SOURCE LINES 11-19 .. code-block:: Python :lineno-start: 12 import matplotlib.animation as animation import matplotlib.pyplot as plt import numpy as np import torch from torchmetrics.audio import SignalNoiseRatio .. GENERATED FROM PYTHON SOURCE LINES 20-21 Generate a clean signal (simulating a high-quality recording) .. GENERATED FROM PYTHON SOURCE LINES 21-30 .. code-block:: Python :lineno-start: 23 def generate_clean_signal(length: int = 1000) -> tuple[np.ndarray, np.ndarray]: """Generate a clean signal (sine wave)""" t = np.linspace(0, 1, length) signal = np.sin(2 * np.pi * 10 * t) # 10 Hz sine wave, representing the clean recording return t, signal .. GENERATED FROM PYTHON SOURCE LINES 31-32 Add Gaussian noise to the signal to simulate the noisy environment .. GENERATED FROM PYTHON SOURCE LINES 32-40 .. code-block:: Python :lineno-start: 34 def add_noise(signal: np.ndarray, noise_level: float = 0.5) -> np.ndarray: """Add Gaussian noise to the signal.""" noise = noise_level * np.random.randn(signal.shape[0]) return signal + noise .. GENERATED FROM PYTHON SOURCE LINES 41-42 Apply FFT to filter out the noise .. GENERATED FROM PYTHON SOURCE LINES 42-52 .. code-block:: Python :lineno-start: 44 def fft_denoise(noisy_signal: np.ndarray, threshold: float) -> np.ndarray: """Denoise the signal using FFT.""" freq_domain = np.fft.fft(noisy_signal) # Filter frequencies using FFT magnitude = np.abs(freq_domain) filtered_freq_domain = freq_domain * (magnitude > threshold) return np.fft.ifft(filtered_freq_domain).real # Perform inverse FFT to reconstruct the signal .. GENERATED FROM PYTHON SOURCE LINES 53-54 Generate and plot clean, noisy, and denoised signals to visualize the reconstruction .. GENERATED FROM PYTHON SOURCE LINES 54-70 .. code-block:: Python :lineno-start: 55 length = 1000 t, clean_signal = generate_clean_signal(length) noisy_signal = add_noise(clean_signal, noise_level=0.5) denoised_signal = fft_denoise(noisy_signal, threshold=10) plt.figure(figsize=(12, 4)) plt.plot(t, noisy_signal, label="Noisy environment", color="blue", alpha=0.7) plt.plot(t, denoised_signal, label="Denoised signal", color="green", alpha=0.7) plt.plot(t, clean_signal, label="Clean song", color="red", linewidth=3) plt.xlabel("Time") plt.ylabel("Amplitude") plt.title("Clean Song vs. Noisy Environment vs. Denoised Signal") plt.legend() plt.show() .. image-sg:: /gallery/audio/images/sphx_glr_signal_to_noise_ratio_001.png :alt: Clean Song vs. Noisy Environment vs. Denoised Signal :srcset: /gallery/audio/images/sphx_glr_signal_to_noise_ratio_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 71-72 Convert the signals to PyTorch tensors and calculate the SNR .. GENERATED FROM PYTHON SOURCE LINES 72-82 .. code-block:: Python :lineno-start: 72 clean_signal_tensor = torch.tensor(clean_signal).float() noisy_signal_tensor = torch.tensor(noisy_signal).float() denoised_signal_tensor = torch.tensor(denoised_signal).float() snr = SignalNoiseRatio() initial_snr = snr(preds=noisy_signal_tensor, target=clean_signal_tensor) reconstructed_snr = snr(preds=denoised_signal_tensor, target=clean_signal_tensor) print(f"Initial SNR: {initial_snr:.2f}") print(f"Reconstructed SNR: {reconstructed_snr:.2f}") .. rst-class:: sphx-glr-script-out .. code-block:: none Initial SNR: 3.58 Reconstructed SNR: 3.92 .. GENERATED FROM PYTHON SOURCE LINES 83-84 To show the effect of different noise levels on the SNR, we create an animation that iterates over different noise levels and updates the plot accordingly: .. GENERATED FROM PYTHON SOURCE LINES 84-115 .. code-block:: Python :lineno-start: 84 fig, ax = plt.subplots(figsize=(12, 4)) noise_levels = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] def update(num: int) -> tuple: """Update the plot for each frame.""" t, clean_signal = generate_clean_signal(length) noisy_signal = add_noise(clean_signal, noise_level=noise_levels[num]) denoised_signal = fft_denoise(noisy_signal, threshold=10) clean_signal_tensor = torch.tensor(clean_signal).float() noisy_signal_tensor = torch.tensor(noisy_signal).float() denoised_signal_tensor = torch.tensor(denoised_signal).float() initial_snr = snr(preds=noisy_signal_tensor, target=clean_signal_tensor) reconstructed_snr = snr(preds=denoised_signal_tensor, target=clean_signal_tensor) ax.clear() (noisy,) = plt.plot(t, noisy_signal, label="Noisy Environment", color="blue", alpha=0.7) (denoised,) = plt.plot(t, denoised_signal, label="Denoised Signal", color="green", alpha=0.7) (clean,) = plt.plot(t, clean_signal, label="Clean Song", color="red", linewidth=3) ax.set_xlabel("Time") ax.set_ylabel("Amplitude") ax.set_title( f"Initial SNR: {initial_snr:.2f} - Reconstructed SNR: {reconstructed_snr:.2f} - Noise level: {noise_levels[num]}" ) ax.legend(loc="upper right") ax.set_ylim(-3, 3) return noisy, denoised, clean ani = animation.FuncAnimation(fig, update, frames=len(noise_levels), interval=1000) .. container:: sphx-glr-animation .. raw:: html
.. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.522 seconds) .. _sphx_glr_download_gallery_audio_signal_to_noise_ratio.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: signal_to_noise_ratio.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: signal_to_noise_ratio.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: signal_to_noise_ratio.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_