¿Cómo extraer Audio Wave de una mezcla de Signal usando Scipy – Python?

Prerrequisitos: Scipy

El análisis espectral se refiere al análisis del espectro de frecuencia/respuesta de las ondas. Este artículo, como sugiere el título, trata sobre la extracción de ondas de audio de una mezcla de señales y lo que ocurre exactamente en el proceso se puede explicar como:

Considere que tenemos 3 señales de audio mixtas que tienen una frecuencia de 50 Hz, 1023 Hz y 1735 Hz, respectivamente. Además de estas señales, también implementaremos ruido a la señal de antemano. El análisis espectral se realizará mediante el uso de un filtro para que podamos separar las señales. Bajo requerimiento, podemos ajustar nuestras señales de acuerdo a la frecuencia de la señal que queremos extraer.

Acercarse

  • Importar módulos
  • Especifique condiciones como el número de muestras, la frecuencia de muestreo, el tiempo de muestra interno y la creación de nuestra onda de audio mixta
  • Añadir ruido a la señal de audio
  • Estimación de la ventana de filtro y la frecuencia de corte de computación
  • Crear un filtro para filtrar el ruido
  • Trazar la señal ruidosa, la respuesta de frecuencia del filtro, la onda de audio extraída, el espectro de frecuencia de la señal de audio mixta, el espectro de frecuencia de nuestra señal de audio extraída
  • Gráfico de visualización

Programa:

Python3

# Original, high sample rate signal
# Let us imagine this is like our analog signal
from scipy import signal
from scipy.fft import fft
import numpy as np
import matplotlib.pyplot as plt
  
# Number of samples
N_sample = 512
  
# Sampling frequency
fs = 10000
  
# inter sample time = 0.001s = 1kHz sampling
dt = 1/fs
  
# time vector
t = np.arange(0, N_sample)*dt
  
# Create signal vector that is the sum of 50 Hz, 1023 Hz, and 1735 Hz
Signal = np.sin(2*np.pi*50*t) + np.sin(2*np.pi*1023*t)+np.sin(2*np.pi*1735*t)
  
# Add random noise to the signal
Signal = Signal+np.random.normal(0, .1, Signal.shape)
  
# Part A: Estimation of Length and Window
# Select design  Specification
# Lower stopband frequency in Hz
fstop_L = 500
  
# Lower passband frequency in HZ
fpass_L = 800
  
# Upper stopband frequency in Hz
fstop_U = 1500
  
# Upper passband frequency in HZ
fpass_U = 1200
  
# Calculations
# Normalized lower transition band w.r.t. fs
del_f1 = abs(fpass_L-fstop_L)/fs
  
# Normalized upper transition band w.r.t. fs
del_f2 = abs(fpass_U-fstop_U)/fs
  
# Filter length using selected window based
# on Normalized lower transition band
N1 = 3.3/del_f1
  
# Filter length using selected window based
# on Normalized upper transition band
N2 = 3.3/del_f2
print('Filter length based on lower transition band:', N1)
print('Filter length based on upper transition band:', N2)
  
# Select length as the maximum of the N1 and N2
# and if it is even, make it next higher integer
N = int(np.ceil(max(N1, N2)))
if(N % 2 == 0):
    N = N+1
print('Selected filter length :', N)
  
# Calculate lower and uper cut-off frequencies
# Lower cut-off frequency in Hz
fL = (fstop_L+fpass_L)/2
  
# Upper cut-off frequency in Hz
fU = (fstop_U+fpass_U)/2
  
# Normalized Lower cut-off frequency in (w/pi) rad
wL = 2*fL/fs
  
# Normalized upper cut-off frequency in (w/pi) rad
wU = 2*fU/fs
  
# Cutoff frequency array
cutoff = [wL, wU]
  
# Since the given specification of Stopband attenuation = 50 dB
# and Passband ripple = 0.05 dB, atleast satisfy with
# Hamming window, we have to choose it.
  
# Determine Filter coefficients
# Call filter design function using Hamming window
b_ham = signal.firwin(N, cutoff, window="hamming", pass_zero="bandpass")
  
# Determine Frequency response of the filters
# Calculate response h at specified frequency
# points w for Hamming window
w, h_ham = signal.freqz(b_ham, a=1)
  
# Calculate Magnitude in dB
# Calculate magnitude in decibels
h_dB_ham = 20*np.log10(abs(h_ham))
  
a = [1]
  
# Filter the noisy signal by designed filter
# using signal.filtfilt
filtOut = signal.filtfilt(b_ham, a, Signal)
  
  
# Plot filter magnitude and phase responses using
# subplot. Digital frequency w converted in analog
# frequency
fig = plt.figure(figsize=(12, 18))
  
# Original signal
sub1 = plt.subplot(5, 1, 1)
sub1.plot(t[0:200], Signal[0:200])
sub1.set_ylabel('Amplitude')
sub1.set_xlabel('Time')
sub1.set_title('Noisy signal', fontsize=20)
  
# Magnitude response Plot
sub2 = plt.subplot(5, 1, 2)
sub2.plot(w*fs/(2*np.pi), h_dB_ham, 'r', label='Bandpass filter',
          linewidth='2')  # Plot for magnitude response window
  
sub2.set_ylabel('Magnitude (db)')
sub2.set_xlabel('Frequency in Hz')
sub2.set_title('Frequency response of Bandpass Filter', fontsize=20)
sub2.axis = ([0,  fs/2,  -110,  5])
sub2.grid()
  
sub3 = plt.subplot(5, 1, 3)
sub3.plot(t[0:200], filtOut[0:200], 'g', label='Filtered signal',
          linewidth='2')  # Plot for magnitude response window
sub3.set_ylabel('Magnitude ')
sub3.set_xlabel('Time')
sub3.set_title('Filtered output of Band pass Filter', fontsize=20)
  
  
# Show spectrum of noisy input signal
Sigf = fft(Signal)  # Compute FFT of noisy signal
sub4 = plt.subplot(5, 1, 4)
xf = np.linspace(0.0, 1.0/(2.0*dt), (N_sample-1)//2)
sub4.plot(xf, 2.0/N_sample * np.abs(Sigf[0:(N_sample-1)//2]))
sub4.set_ylabel('Magnitude')
sub4.set_xlabel('Frequency in Hz')
sub4.set_title('Frequency Spectrum of Original Signal', fontsize=20)
sub4.grid()
  
# Show spectrum of filtered output signal
Outf = fft(filtOut)  # Compute FFT of filtered signal
sub5 = plt.subplot(5, 1, 5)
xf = np.linspace(0.0, 1.0/(2.0*dt), (N_sample-1)//2)
sub5.plot(xf, 2.0/N_sample * np.abs(Outf[0:(N_sample-1)//2]))
sub5.set_ylabel('Magnitude')
sub5.set_xlabel('Frequency in Hz')
sub5.set_title('Frequency Spectrum of Filtered Signal', fontsize=20)
sub5.grid()
  
fig.tight_layout()
plt.show()

Producción:

Publicación traducida automáticamente

Artículo escrito por sagnikmukherjee2 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *