从数据中获取 FFT 峰值 [英] Getting FFT peaks from data

查看:46
本文介绍了从数据中获取 FFT 峰值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Octave 从头开始​​开发语音识别系统.我试图通过检测频率差异来检测音素.目前我已经读入了一个 wav 文件,将值组织成块并将 fft 应用于整体数据.之后,我用 plot(abs(real(fft(q)))) 绘制新数据,它创建了这个图:

I am developing a speech recognition system from scratch using Octave. I am trying to detect phonemes by detecting differences in frequency. Currently I have read in a wav file, organized the values into blocks and applied fft to the overall data. After, I plot the new data with plot(abs(real(fft(q)))) which creates this graph:

如何获得频率值(图表的峰值)?

How could I get the frequency values (the peaks of the graph)?

推荐答案

如果您无法访问 findpeaks,那么其工作原理的基本前提是,对于信号中的每个点,它搜索以该点为中心的三元素窗口,并检查该窗口的中心是否大于该窗口的左右元素.您希望能够找到正峰值和负峰值,因此您需要检查绝对值.

If you don't have access to findpeaks, the basic premise behind how it works is that for each point in your signal, it searches a three element window that is centred at this point and checks to see whether the centre of this window is larger than the left and right element of this window. You want to be able to find both positive and negative peaks, so you'd need to check the absolute value.

因此,您可以做的是制作两个额外的信号,将信号向左移动 1 次,向右移动 1 次.当我们这样做时,我们实际上将检查从 秒开始的峰值元素,以便为向左看腾出空间.我们一直检查到倒数第二个元素,以便为向右看腾出空间.因此,我们实际上将检查信号的 N - 2 版本上的峰值,其中 N 是信号的长度.因此,当我们创建左移信号时,我们提取信号的第一个元素,直到倒数第三个元素.当我们创建右移信号时,我们从第三个元素开始提取,直到最后一个元素.原始信号将简单地删除其第一个和最后一个元素.

As such, what you can do is make two additional signals that shift the signal to the left by 1 and to the right by 1. When we do this, we will actually be checking for peaks starting at the second element in your signal, in order to make room for looking to the left. We keep checking up until the second last element, in order to make room for looking to the right. Therefore, we will actually be checking for peaks on a N - 2 version of the signal where N is the length of your signal. Therefore, when we create the left shifted signal, we extract the first element of the signal up until the third last element. When we create the right shifted signal, we extract from the third element up until the last element. The original signal will simply have its first and last elements removed.

因此,通过这种方式检查峰值,我们将丢失数据的第一个和最后一个点,但这应该是合适的,因为在开始和结束时很可能不会出现任何峰值.之后,创建所有这些信号,简单地使用逻辑索引来查看原始信号中的对应值(不包括第一个和最后一个元素)是否大于其他两个信号在其对应位置上的值.

Therefore, by checking for peaks this way, we will lose out on the first and last point of your data, but that should be suitable as there most likely won't be any peaks at the beginning and at the end. After, creating all of these signals, simply use logical indexing to see whether the corresponding values in the original signal (without the first and last elements) are larger than the other two signals in their corresponding positions.

因此,假设您的信号存储在 f 中,您将执行以下操作:

As such, supposing your signal was stored in f, you would do the following:

f1 = abs(f(2:end-1)); %// Original signal
f2 = abs(f(1:end-2)); %// Left shift
f3 = abs(f(3:end)); %// Right shift

idx = find(f1 > f2 & f1 > f3) + 1; %// Get the locations of where we find our peaks

idx 将包含出现峰值的索引位置.请记住,我们开始在第二位置搜索峰值,因此您需要添加 1 以适应这种变化.如果您想找到实际时间(或您的情况下的频率)值,您只需使用 idx 来索引用于生成信号并找到它们的时间(或频率)数组.因此,让我们使用一个人工案例,其中我以 1 Hz 的频率生成 0 到 3 秒的正弦曲线.因此:

idx will contain the index locations of where the peaks occur. Bear in mind that we started searching for peaks at the second position, and so you need to add 1 to accommodate for this shift. If you wanted to find the actual time (or frequency in your case) values, you would just use idx to index into the time (or frequency) array that was used to generate your signal and find them. As such, let's use an artificial case where I generate a sinusoid from 0 to 3 seconds with a frequency of 1 Hz. Therefore:

t = 0 : 0.01 : 3;
f = sin(2*pi*t);

现在,如果我们用这个信号运行上面的代码,我们就会找到峰值的位置.然后我们可以使用这些位置来索引 tf 并绘制信号以及我们检测到峰值的位置.因此:

Now, if we ran the above code with this signal, we'd find the location of our peaks. We can then use these locations to index into t and f and plot the signal as well as where we have detected our peaks. Therefore:

plot(t, f, t(idx), f(idx), 'r.')

这是我得到的:

请记住,这是一种非常简单的检测峰值的方法,但这实际上是在 findpeaks 中完成的.如果你使用上面的代码,它基本上会找到所有峰值.因此,代码会在上图中找到数十个峰值,因为整个频谱都有局部最大值.您可能想确定峰的位置.人们通常做的是使用阈值来表示峰值应该有多大,然后再决定它是否是一个有效的峰值.因此,您可以强制执行阈值,并执行以下操作:

Bear in mind that this is a very simple way of detecting peaks, but that is what is essentially done in findpeaks. If you used the above code, it would basically find all peaks. As such, the code would find dozens of peaks in that above graph, because there are local maxima all over your spectrum. You probably want to determine where the strong peaks are located. What people usually do is use a threshold to signify how large the peak should be before deciding whether that is a valid peak. As such, you can enforce a threshold, and do something like this:

thresh = ... ; %// Define threshold here
idx = find(f1 > f2 & f1 > f3 & f1 > thresh) + 1; %// Get the locations of where we find our peaks

就您的图表而言,您可能需要设置此项,以便找到可能大于 10 的任何峰值.

In your case for your graph, you may want to set this so that you find any peaks whose magnitude is larger than 10 perhaps.

findpeaks 还可以做很多其他的事情,例如过滤掉嘈杂的峰值和其他一些稳健的措施.如果你想使用findpeaks,你需要确保你安装了信号包.您可以简单地从 Octave 命令提示符使用 pkg install 并安装 signal 包.具体来说,试试这个:

There are a lot of other things that findpeaks does, such as filtering out noisy peaks and some other robust measures. If you want to use findpeaks, you need to make sure that you install signal package. You can simply use pkg install from the Octave Command Prompt and install the signal package. Specifically, try this:

pkg install -forge signal

一旦你安装了 signal 包,你可以通过以下方式将它加载到 Octave 环境中:

Once you install the signal package, you can load it into the Octave environment by doing:

pkg load signal

如果您必须安装依赖项,它会在您尝试安装 signal 包时告诉您.查看此链接了解更多详情:https://www.gnu.org/software/octave/doc/interpreter/Installing-and-Removing-Packages.html

If you have to install dependencies, it'll tell you when you try to install the signal package. Check out this link for more details: https://www.gnu.org/software/octave/doc/interpreter/Installing-and-Removing-Packages.html

mkoctfile 代表制作/编译 Octave 文件.如果您没有 mkoctfile,请确保您安装了最新版本的 Octave.为了让事情变得简单,我建议您安装 HomebrewMacPorts 并以这种方式获得 Octave.安装后,您应该可以使 mkoctfile 正常工作.但是,如果仍然不能,则可能需要安装兼容的编译器.简单的方法是从 Xcode 安装命令行开发工具.转到此链接,然后转到其他工具.

mkoctfile stands for making / compiling an Octave file. If you don't have mkoctfile, make sure you have the most recent version of Octave installed. What I recommend you do to make things simple is to install either Homebrew or MacPorts and get Octave in that fashion. Once you install it, then you should be able to get mkoctfile working. However, if you still can't, you may need to have a compatible compiler installed. The easy approach is to install the Command Line Developer tools from Xcode. Go to this link then go to Additional Tools.

祝你好运!

这篇关于从数据中获取 FFT 峰值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆