音频处理对我来说很新鲜。目前正在使用Python Numpy处理wave文件。在计算FFT矩阵之后,我得到了不存在频率的噪声功率值。我对可视化数据和准确性感兴趣不是一个高优先级。有没有一种安全的方法可以计算削波值来删除这些值,还是应该使用每个样本集的所有FFT矩阵来得出平均数?
问候
编辑:
from numpy import *
import wave
import pymedia.audio.sound as sound
import time, struct
from pylab import ion, plot, draw, show
fp = wave.open("500-200f.wav", "rb")
sample_rate = fp.getframerate()
total_num_samps = fp.getnframes()
fft_length = 2048.
num_fft = (total_num_samps / fft_length ) - 2
temp = zeros((num_fft,fft_length), float)
for i in range(num_fft):
tempb = fp.readframes(fft_length);
data = struct.unpack("%dH"%(fft_length), tempb)
temp[i,:] = array(data, short)
pts = fft_length/2+1
data = (abs(fft.rfft(temp, fft_length)) / (pts))[:pts]
x_axis = arange(pts)*sample_rate*.5/pts
spec_range = pts
plot(x_axis, data[0])
show()
以下是非对数刻度的图,包含使用Goldwave创建的500hz(淡出)+ 200hz正弦波的合成波文件。
答案 0 :(得分:3)
模拟波形不应该像您的图一样显示FFT,因此有些问题非常错误,可能不是FFT,而是输入波形。你的情节中的主要问题不是涟漪,而是1000 Hz左右的谐波和500 Hz时的次谐波。模拟波形不应显示任何此类(例如,请参见下面的图表)。
首先,您可能只想尝试绘制原始波形,这可能会指出一个明显的问题。另外,将波解包为无符号短路(即“H”)似乎很奇怪,特别是在此之后没有大的零频率分量。
通过对波形应用削波,我能够得到非常接近的FFT,如分谐波和高次谐波(和Trevor)所暗示的那样。您可以在模拟或解包中引入剪辑。无论哪种方式,我都是通过在numpy中创建波形开始绕过它。
这是正确的FFT应该是什么样的(即基本上完美,除了由于窗口引起的峰值变宽)
这是一个被剪切的波形(与你的FFT非常相似,从分谐波到1000 Hz左右的三个高次谐波的精确模式)
的代码from numpy import *
from pylab import ion, plot, draw, show, xlabel, ylabel, figure
sample_rate = 20000.
times = arange(0, 10., 1./sample_rate)
wfm0 = sin(2*pi*200.*times)
wfm1 = sin(2*pi*500.*times) *(10.-times)/10.
wfm = wfm0+wfm1
# int test
#wfm *= 2**8
#wfm = wfm.astype(int16)
#wfm = wfm.astype(float)
# abs test
#wfm = abs(wfm)
# clip test
#wfm = clip(wfm, -1.2, 1.2)
fft_length = 5*2048.
total_num_samps = len(times)
num_fft = (total_num_samps / fft_length ) - 2
temp = zeros((num_fft,fft_length), float)
for i in range(num_fft):
temp[i,:] = wfm[i*fft_length:(i+1)*fft_length]
pts = fft_length/2+1
data = (abs(fft.rfft(temp, fft_length)) / (pts))[:pts]
x_axis = arange(pts)*sample_rate*.5/pts
spec_range = pts
plot(x_axis, data[2], linewidth=3)
xlabel("freq (Hz)")
ylabel('abs(FFT)')
show()
答案 1 :(得分:2)
FFT,因为它们是窗口化的,sampled导致aliasing并在频域中进行采样。时域中的过滤只是频域中的乘法,因此您可能只想应用一个过滤器,该过滤器只是将每个频率乘以您正在使用的过滤器的函数值。例如,在通带中乘以1,在其他情况下乘以零。意外值可能是由于较高频率向下折叠到您看到的频率的混叠引起的。 original signal needs to be band limited to half your sampling rate或者您将获得aliasing。更值得关注的是使感兴趣区域扭曲的混叠,因为对于这个频率频段,您想要知道频率来自预期频率。
要记住的另一件事是,当您从波形文件中获取一段数据时,您将通过数学方法将其乘以方波。这会导致sinx / x与频率响应进行卷积,以最大限度地减少这种情况,您可以将原始窗口信号与Hanning window相乘。
答案 2 :(得分:1)
对于1D FFT,值得一提的是第一个元素(索引[0]
)包含DC(零频率)项,元素[1:N/2]
包含正频率和元素{{1}包含负频率。由于您没有提供有关FFT输出的代码示例或其他信息,因此我不能排除“不存在频率时的噪声功率值”不仅仅是频谱的负频率的可能性。
编辑:Here是纯Python中实现的基数-2 FFT的示例,其中包含一个简单的测试例程,用于查找矩形脉冲的FFT [N/2+1:N-1]
。您可以在codepad上运行该示例,并查看该序列的FFT是
[1.,1.,1.,1.,0.,0.,0.,0.]
请注意,代码按照频率上升的顺序打印出傅立叶系数,即从最高负频率到DC,然后再到最高正频率。
答案 3 :(得分:1)
我对你的问题不太了解实际回答任何具体内容。
但是根据我自己编写FFT的经验,可以尝试以下几点:
如果这三件事都有效,那么你的fft很好。您的输入数据可能就是问题所在。
时间点剪辑以特定的规则间隔以较小的幅度显示为频域信号的镜像。