Getting FFT peaks from data

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

How can I get frequency values ​​(graph peaks)?

+6
source share
2 answers

If you do not have access to findpeaks , the basic premise of how it works is that for each point of your signal, it looks for a three-element window that is centered at that point and checks if the center of this window is larger than the left and right elements of this window. You want to find both positive and negative peaks, so you will need to check the absolute value.

Thus, you can make two additional signals that shift the signal left by 1 and right by 1. When we do this, we will actually check the peaks starting from the second element in your signal to make room for the search to the left. We continue to check until the second last element to make room for the search to the right. Therefore, we will check the peaks on the signal version N - 2 , 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 to the third last element . When we create the right shifted signal, we extract from the third element to the last element. The original signal will simply delete its first and last elements.

Therefore, checking the peaks in this way, we will lose the first and last point of your data, but this should be appropriate, since most likely there will be no peaks at the beginning and at the end. After creating all these signals, simply use logical indexing to see if the corresponding values ​​in the original signal (without the first and last elements) are greater than the other two signals in their respective positions.

Thus, if your signal is stored in f , you should 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 will contain index locations where peaks occur. Keep in mind that we started searching for peaks at position two , so you need to add 1 to accommodate this shift. If you want to find the actual time (or frequency in your case), you would simply use idx to index into the array of time (or frequency) that was used to generate your signal and search. Thus, let me use an artificial case when I create a sinusoid from 0 to 3 seconds with a frequency of 1 Hz. Therefore:

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

Now, if we run the above code with this signal, we will find the location of our peaks. Then we can use these locations to index at t and f and plot, as well as where we found our peaks. Therefore:

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

This is what I get:

enter image description here

Keep in mind that this is a very easy way to detect peaks, but this is what essentially findpeaks . If you used the code above, it would basically find all the peaks . Thus, the code will find dozens of peaks in this above graph because there are local maxima in your spectrum. You probably want to determine where strong peaks are located. Usually people use a threshold to indicate how large the peak should be before deciding if this is a valid peak. So you can set 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 

In your case, for your chart, you can set this to find any peaks whose magnitude is greater than 10.


There are many other things that findpeaks does, for example, filters noisy peaks and some other reliable measures. If you want to use findpeaks , you need to make sure that you are installing the signal package. You can simply use pkg install from the Octave command line and install the signal package. In particular, try the following:

 pkg install -forge signal 

After installing the signal package, you can load it into the Octave environment by following these steps:

 pkg load signal 

If you need to install dependencies, it will tell you when you try to install the signal package. See this link for more information: https://www.gnu.org/software/octave/doc/interpreter/Installing-and-Removing-Packages.html

mkoctfile means creating / compiling an Octave file. If you do not have mkoctfile , make sure you have the latest version of Octave installed. I recommend that you do everything to simplify the installation of Homebrew or MacPorts. And get Octave this way. After installing it, you can get mkoctfile work. However, if you still cannot, you may need to install a compatible compiler. An easy approach is to install command line development tools from Xcode. Go to this link , then go to the "Advanced Tools" section.

Good luck

+15
source

You can use the findpeaks function from the octave signal packet:

http://octave.sourceforge.net/signal/function/findpeaks.html

+2
source

Source: https://habr.com/ru/post/978551/


All Articles