我正在学习傅立叶变换以及如何在 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。它应该返回音频数据,对吧?我哪里出错了或者我错过了什么?
最佳答案
与其说这是一个代码问题,不如说这是一个数学问题。
傅立叶变换尝试提取复信号的分量。该信号可以是真实信号或理论信号。因此,傅里叶输出具有实部和虚部的复数,以更好地描述信号,范围为 -Hz -> +Hz。您需要绝对值和 0 -> +Hz 范围来描述真实信号。
要将数据限制为实数分量,您需要做两件事 - 找到复数数据点的绝对值并删除负 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/
和 //2
的杂耍是由于奇偶数组和傅里叶变换的特性造成的。
编辑:
了解您的信号频率可能会有所帮助。您可以使用 fftfreq
方法计算这些,该方法只需要您的采样间隔和数据数组长度。
time_interval = 1/sampling_rate
frequencies = scipy.fftpack.fftfreq(number_of_datapoints, \
d=time_interval)[:number_of_datapoints//2]
关于python - scipy 和 numpy 逆 fft 返回复数而不是 float ,无法保存为 wav,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60812290/