首页 > 解决方案 > scipy 和 numpy 逆 fft 返回复数而不是浮点数,不能保存为 wav

问题描述

我正在学习傅立叶变换以及如何在 python 中使用它们进行音频操作。但简单地获取 fft 和 ifft 的音频数据会将其转换为复杂的形式,我无法将其保存为 wav。代码和错误如下。

    import librosa
    import scipy
    audio,sr=librosa.load("sample2.wav")
    aud_fft=scipy.fft.fft(audio)
    ref_aud=scipy.fft.ifft(aud_fft)
    librosa.output.write_wav("test.wav",ref_aud,sr)

错误是

File "fft_test.py", line 6, in <module>
    librosa.output.write_wav("test.wav",ref_aud,sr)
  File "<decorator-gen-10>", line 2, in write_wav
  File "/home/vineeth/.local/lib/python3.8/site-packages/librosa/util/decorators.py", line 58, in __wrapper
    return func(*args, **kwargs)
  File "/home/vineeth/.local/lib/python3.8/site-packages/librosa/output.py", line 239, in write_wav
    util.valid_audio(y, mono=False)
  File "/home/vineeth/.local/lib/python3.8/site-packages/librosa/util/utils.py", line 264, in valid_audio
    raise ParameterError('Audio data must be floating-point')
librosa.util.exceptions.ParameterError: Audio data must be floating-point

我所做的只是取 fft,然后取 ifft 的输出。它应该回到音频数据,对吗?我哪里错了或者我错过了什么?

标签: pythonnumpyscipytransformfft

解决方案


这与其说是一个代码问题,不如说是一个数学问题。

傅里叶变换试图提取复杂信号的分量。该信号可以是真实信号或理论信号。因此,傅立叶输出具有实部和虚部的复数以更好地描述信号,范围为 -Hz -> +Hz。您需要绝对值和 0 -> +Hz 的范围来描述真实信号。

要将数据约束为实分量,您需要做两件事 - 找到复杂数据点的绝对值并移除负赫兹范围(FFT 输出数组的后半部分)。

尝试以下操作:

import numpy as np

number_of_datapoints = len(audio)

complex_fft=scipy.fft.fft(audio)
real_absolute_fft = 2.0/number_of_datapoints * \
                    np.abs(complex_fft[:number_of_datapoints//2])

使用2.0/and的杂耍//2是由于奇偶数组和傅里叶变换的特性。

编辑:了解您的信号频率可能会有所帮助。您可以使用该方法计算这些,该fftfreq方法只需要您的采样间隔和数据数组长度。

time_interval = 1/sampling_rate
frequencies = scipy.fftpack.fftfreq(number_of_datapoints, \
                                  d=time_interval)[:number_of_datapoints//2]

推荐阅读