Python 音频信号不能很好地过滤

发布于 2025-01-13 06:00:28 字数 2571 浏览 3 评论 0原文

我需要获取一个有噪音的 .wav 音频文件并过滤掉所有噪音。我必须使用傅里叶变换来做到这一点。经过几天的研究和实验,我终于做出了一个可以工作的功能,问题是它没有按照我的预期工作。这是我制作的函数:

# Audio signal processing
from scipy.io.wavfile import read, write
import matplotlib.pyplot as plt
import numpy as np
from scipy.fft import fft, fftfreq, ifft


def AudioSignalProcessing(audio):

    
    # Import the .wav format audio into two variables: 
    # sampling (int)
    # audio signal (numpy array)
    
    sampling, signal = read(audio)
    
    # time duration of the audio
    length = signal.shape[0] / sampling

    # x axis based on the time duration
    time = np.linspace(0., length, signal.shape[0])
    
    # show original signal
    plt.plot(time, signal)
    plt.xlabel("Time (s)")
    plt.ylabel("Amplitude")
    plt.title("Original signal")
    plt.show()

    
    # apply Fourier transform and normalize
    transform = abs(fft(signal))
    transform = transform/np.linalg.norm(transform)
    
    # obtain frequencies
    xf = fftfreq(transform.size, 1/sampling) 
    
    # show transformed signal (frequencies domain)
    plt.plot(xf, transform)
    plt.xlabel("Frecuency (Hz)")
    plt.ylabel("Amplitude")
    plt.title("Frequency domain signal")
    plt.show()

    
    # filter the transformed signal to a 40% of its maximum amplitude
    threshold = np.amax(transform)*0.4
    filtered = transform[np.where(transform > threshold)]
    xf_filtered = xf[np.where(transform > threshold)]
    
    # show filtered transformed signal
    plt.plot(xf_filtered, filtered)
    plt.xlabel("Frecuency (Hz)")
    plt.ylabel("Amplitude")
    plt.title("FILTERED time domain signal")
    plt.show()
    
    
    # transform the signal back to the time domain
    filtrada = ifft(signal)
    
    # show original signal filtered
    plt.plot(time, filtrada)
    plt.xlabel("Time (s)")
    plt.ylabel("Amplitude")
    plt.title("Filtered signal")
    plt.show()
    
    
    # convert audio signal to .wav format audio
    # write(audio.replace(".wav", " filtrado.wav"), sampling, filtrada.astype(signal.dtype))
    
    return None

AudioSignalProcessing("audio.wav")

这是输出图:

原始信号

转换信号

过滤后的转换信号

过滤后的音频信号

过滤后的频率看起来不像我认为的那样,并且在将过滤后的信号转换回音频后,听起来一点也不好。另外,我尝试过不同的音频,但发生了相同的滤波器失真。

I need to take an .wav audio file that's noisy and filter out all that noise. I have to do it using Fourier Transform. After some days researching and experimenting, I finally made a working function, the problem is that it doesn't work as I intend it to. Here is the function I made:

# Audio signal processing
from scipy.io.wavfile import read, write
import matplotlib.pyplot as plt
import numpy as np
from scipy.fft import fft, fftfreq, ifft


def AudioSignalProcessing(audio):

    
    # Import the .wav format audio into two variables: 
    # sampling (int)
    # audio signal (numpy array)
    
    sampling, signal = read(audio)
    
    # time duration of the audio
    length = signal.shape[0] / sampling

    # x axis based on the time duration
    time = np.linspace(0., length, signal.shape[0])
    
    # show original signal
    plt.plot(time, signal)
    plt.xlabel("Time (s)")
    plt.ylabel("Amplitude")
    plt.title("Original signal")
    plt.show()

    
    # apply Fourier transform and normalize
    transform = abs(fft(signal))
    transform = transform/np.linalg.norm(transform)
    
    # obtain frequencies
    xf = fftfreq(transform.size, 1/sampling) 
    
    # show transformed signal (frequencies domain)
    plt.plot(xf, transform)
    plt.xlabel("Frecuency (Hz)")
    plt.ylabel("Amplitude")
    plt.title("Frequency domain signal")
    plt.show()

    
    # filter the transformed signal to a 40% of its maximum amplitude
    threshold = np.amax(transform)*0.4
    filtered = transform[np.where(transform > threshold)]
    xf_filtered = xf[np.where(transform > threshold)]
    
    # show filtered transformed signal
    plt.plot(xf_filtered, filtered)
    plt.xlabel("Frecuency (Hz)")
    plt.ylabel("Amplitude")
    plt.title("FILTERED time domain signal")
    plt.show()
    
    
    # transform the signal back to the time domain
    filtrada = ifft(signal)
    
    # show original signal filtered
    plt.plot(time, filtrada)
    plt.xlabel("Time (s)")
    plt.ylabel("Amplitude")
    plt.title("Filtered signal")
    plt.show()
    
    
    # convert audio signal to .wav format audio
    # write(audio.replace(".wav", " filtrado.wav"), sampling, filtrada.astype(signal.dtype))
    
    return None

AudioSignalProcessing("audio.wav")

Here is the output plots:

Original signal

Transformed signal

Filtered transformed signal

Filtered audio signal

The filtered frequencies don't look as I think they should, and after converting the filtered signal back to audio it doesn't sound good at all. Also, I've tried with different audios but the same filter distortion happens.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苍景流年 2025-01-20 06:00:28

我建议在 https://dsp.stackexchange.com/ 询问详细的信号处理问题。

看起来您只想保留最大分量至少 40% 以内的频率分量。如果是这种情况:

  1. 保留 DFT 的复数形式,否则将无法变换回来;因此,请从 transform = abs(fft(signal)) 行中删除 abs

  2. 不要使用np.where来“保留”您想要的频率;相反,将变换幅度低于阈值的位置设置为 0;类似的东西
    变换[abs(变换) < 0.4 * 最大值(abs(变换))] = 0

  3. 最后,将逆 DFT 应用于此更改后的变换;您已将其应用于signal(请参阅filtrata = ifft(signal)行)。 (在绘制 filtrada 时,您可能会收到关于丢弃虚值的警告。)

I suggest asking at https://dsp.stackexchange.com/ for detailed signal processing questions.

It looks like you want to keep only those frequency components that are within at least 40% of the maximum component. If that is the case:

  1. Keep the complex form of the DFT, or you won't be able to transform back; so remove the abs from the line transform = abs(fft(signal)).

  2. Don't use np.where to "keep" the frequencies you want; instead, set the places where the transform magnitude is below you threshold to 0; something like
    transform[abs(transform) < 0.4 * max(abs(transform))] = 0

  3. Finally, apply the inverse DFT to this altered transform; you've applied it to signal (see line filtrata = ifft(signal)). (You probably get warning when plotting filtrada about discarding imaginary values.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文