削波 FFT 矩阵

发布于 2024-07-21 14:09:26 字数 1070 浏览 2 评论 0原文

音频处理对我来说是相当新鲜的。 目前使用 Python Numpy 处理波形文件。 计算 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 正弦波的合成波文件。

Audio processing is pretty new for me. And currently using Python Numpy for processing wave files. After calculating FFT matrix I am getting noisy power values for non-existent frequencies. I am interested in visualizing the data and accuracy is not a high priority. Is there a safe way to calculate the clipping value to remove these values, or should I use all FFT matrices for each sample set to come up with an average number ?

regards

Edit:

    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()

Here is the plot in non-logarithmic scale, for synthetic wave file containing 500hz(fading out) + 200hz sine wave created using Goldwave.

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

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

发布评论

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

评论(4

回眸一遍 2024-07-28 14:09:26

值得一提的是,对于 1D FFT,第一个元素(索引 [0])包含 DC(零频率)项,元素 [1:N/2]包含正频率,元素 [N/2+1:N-1] 包含负频率。 由于您没有提供代码示例或有关 FFT 输出的附加信息,因此我不能排除“不存在频率处的噪声功率值”不仅仅是频谱的负频率的可能性。


编辑这里是基数的示例-2 FFT 在纯 Python 中实现,通过一个简单的测试例程来查找矩形脉冲的 FFT,[1.,1.,1.,1.,0.,0.,0.,0.]< /代码>。 您可以在 codepad 上运行该示例,并看到该序列的 FFT 为

[0j,                    Negative frequencies
(1+0.414213562373j),    ^
0j,                     |
(1+2.41421356237j),     |
(4+0j),                <= DC term
(1-2.41421356237j),     |
0j,                     v
(1-0.414213562373j)]    Positive frequencies

请注意,代码打印出傅里叶系数频率递增的顺序,即从最高负频率到DC,然后到最高正频率。

It's worth mentioning for a 1D FFT that the first element (index [0]) contains the DC (zero-frequency) term, the elements [1:N/2] contain the positive frequencies and the elements [N/2+1:N-1] contain the negative frequencies. Since you didn't provide a code sample or additional information about the output of your FFT, I can't rule out the possibility that the "noisy power values at non-existent frequencies" aren't just the negative frequencies of your spectrum.


EDIT: Here is an example of a radix-2 FFT implemented in pure Python with a simple test routine that finds the FFT of a rectangular pulse, [1.,1.,1.,1.,0.,0.,0.,0.]. You can run the example on codepad and see that the FFT of that sequence is

[0j,                    Negative frequencies
(1+0.414213562373j),    ^
0j,                     |
(1+2.41421356237j),     |
(4+0j),                <= DC term
(1-2.41421356237j),     |
0j,                     v
(1-0.414213562373j)]    Positive frequencies

Note that the code prints out the Fourier coefficients in order of ascending frequency, i.e. from the highest negative frequency up to DC, and then up to the highest positive frequency.

挥剑断情 2024-07-28 14:09:26

FFT 是因为它们是窗口化的并且采样导致混叠 以及频域采样。 时域中的滤波只是频域中的乘法,因此您可能只想应用一个滤波器,该滤波器只需将每个频率乘以您正在使用的滤波器的函数值。 例如,在通带中乘以 1,在其他区域乘以 0。 意外值可能是由混叠引起的,其中较高的频率被折叠到您所看到的频率。 原始信号需要将频带限制为采样率的一半或您将获得别名。 更令人担忧的是混叠会扭曲感兴趣的区域,因为对于该频段,您想知道频率是否来自预期频率。

另一件要记住的事情是,当您从波形文件中获取一段数据时,您会在数学上将其乘以方波。 这会导致 sinx/x 与频率响应进行卷积以最小化这种情况,您可以将原始加窗信号乘以类似 汉宁窗

FFT's because they are windowed and sampled cause aliasing and sampling in the frequency domain as well. Filtering in the time domain is just multiplication in the frequency domain so you may want to just apply a filter which is just multiplying each frequency by a value for the function for the filter you are using. For example multiply by 1 in the passband and by zero every were else. The unexpected values are probably caused by aliasing where higher frequencies are being folded down to the ones you are seeing. The original signal needs to be band limited to half your sampling rate or you will get aliasing. Of more concern is aliasing that is distorting the area of interest because for this band of frequencies you want to know that the frequency is from the expected one.

The other thing to keep in mind is that when you grab a piece of data from a wave file you are mathmatically multiplying it by a square wave. This causes a sinx/x to be convolved with the frequency response to minimize this you can multiply the original windowed signal with something like a Hanning window.

旧时模样 2024-07-28 14:09:26

模拟波形不应像您的图那样显示 FFT,因此出现了很大的问题,并且可能不是 FFT,而是输入波形。 图中的主要问题不是波纹,而是 1000 Hz 左右的谐波以及 500 Hz 的分谐波。 模拟波形不应该显示任何这些(例如,请参见下面的图)。

首先,您可能只想尝试绘制原始波形,这可能会指出一个明显的问题。 另外,将波解压缩为无符号短路(即“H”)似乎很奇怪,尤其是在此之后没有大的零频率分量。

正如分谐波和高次谐波(以及 Trevor)所建议的那样,通过对波形应用限幅,我能够获得与 FFT 相当接近的重复。 您可以在模拟或拆包中引入裁剪。 不管怎样,我通过在 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()

Simulated waveforms shouldn't show FFTs like your figure, so something is very wrong, and probably not with the FFT, but with the input waveform. The main problem in your plot is not the ripples, but the harmonics around 1000 Hz, and the subharmonic at 500 Hz. A simulated waveform shouldn't show any of this (for example, see my plot below).

First, you probably want to just try plotting out the raw waveform, and this will likely point to an obvious problem. Also, it seems odd to have a wave unpack to unsigned shorts, i.e. "H", and especially after this to not have a large zero-frequency component.

I was able to get a pretty close duplicate to your FFT by applying clipping to the waveform, as was suggested by both the subharmonic and higher harmonics (and Trevor). You could be introducing clipping either in the simulation or the unpacking. Either way, I bypassed this by creating the waveforms in numpy to start with.

Here's what the proper FFT should look like (i.e. basically perfect, except for the broadening of the peaks due to the windowing)

alt text

Here's one from a waveform that's been clipped (and is very similar to your FFT, from the subharmonic to the precise pattern of the three higher harmonics around 1000 Hz)

alt text

Here's the code I used to generate these

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()
十年不长 2024-07-28 14:09:26

我对你的问题了解不够,无法实际回答任何具体问题。

但根据我自己编写 FFT 的经验,可以尝试以下几点:

  • 确保遵循奈奎斯特规则
  • 如果您正在查看 FFT 的线性输出...您将很难看到自己的信号并认为一切都损坏了。 确保您查看的是 FFT 幅度的 dB。 (即“plot(10*log10(abs(fft(x))))”)
  • 通过输入生成的数据(如纯音)为 FFT() 函数创建一个单元测试。 然后将生成的相同数据输入 Matlab 的 FFT()。 在两个输出数据系列之间进行绝对值差异,并确保最大绝对值差异约为 10^-6 (即唯一的差异是由小浮点误差引起的)
  • 确保您是 窗口数据

如果所有这三件事都有效,那么您的 fft 就可以了。 您的输入数据可能是问题所在。

时间域限幅显示为频域中信号以特定规则间隔且幅度较小的镜像。

I don't know enough from your question to actually answer anything specific.

But here are a couple of things to try from my own experience writing FFTs:

  • Make sure you are following Nyquist rule
  • If you are viewing the linear output of the FFT... you will have trouble seeing your own signal and think everything is broken. Make sure you are looking at the dB of your FFT magnitude. (i.e. "plot(10*log10(abs(fft(x))))" )
  • Create a unitTest for your FFT() function by feeding generated data like a pure tone. Then feed the same generated data to Matlab's FFT(). Do a absolute value diff between the two output data series and make sure the max absolute value difference is something like 10^-6 (i.e. the only difference is caused by small floating point errors)
  • Make sure you are windowing your data

If all of those three things work, then your fft is fine. And your input data is probably the issue.

Time doamin clipping shows up as mirror images of the signal in the frequency domain at specific regular intervals with less amplitude.

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