python - 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 的输出。它应该回到音频数据,对吗?我哪里错了或者我错过了什么?
解决方案
这与其说是一个代码问题,不如说是一个数学问题。
傅里叶变换试图提取复杂信号的分量。该信号可以是真实信号或理论信号。因此,傅立叶输出具有实部和虚部的复数以更好地描述信号,范围为 -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]
推荐阅读
- python - 在浏览器中查看 Dash App 时 Heroku 应用程序部署错误
- sql - PolyBase创建外部表查询Hadoop,列数不匹配
- c++ - 调整大小时没有重载函数的实例
- r - 多元多元回归的 VIF 检验
- reactjs - 当容器中的输入值更改时,不会记录 HOC 内部的 ComponentDidUpdate
- c++ - 如何过滤pcl中给定3d(一般)平面之前的所有点
- c - 比较相似的数据类型无效?
- javascript - 如何在 vuejs 中渲染一个复杂的数组?
- c# - Blazor 组件在控制器返回 401 时引发异常
- plotly - 在 Dash 中为 Julia 制作子图