0

I have an audio file , which represent the sound of a motor running at 2500rpm my aim is to get the period of this signal, so I can automaticlly tell what is the motor speed is. To do that I take a part of the signal and run get it autocorrelation , hopping that this willl tell the period of the singal! but I just don't get it : here is a part of my code :

clear;
clc;
[x0,Fs] = audioread('_2500.wav');
x= x0(1:2000,1);
xc = xcorr(x);
clf; 
subplot(3,1,1);
plot(x);

subplot(3,1,2);
plot(xc);

[peaks,locs] = findpeaks(xc);
hold on 
subplot(3,1,3)
plot(xc(locs),'ro');

and here are the plot :

image

and how should I consider the sampling frequency, which is : 44100 ?

Engine
  • 5,360
  • 18
  • 84
  • 162
  • Please check: http://stackoverflow.com/questions/15261122/determine-frequency-from-signal-data-in-matlab – tashuhka Mar 20 '14 at 11:59
  • There are many many answers to similar questions in the stack universe. As suggested by the answers, there is more than one possible solution, but one that many people find most intuitive is to find the peak in the frequency domain. I wrote a blog post about that approach: http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html – Bjorn Roche Mar 20 '14 at 14:18

3 Answers3

2

You can use the autocorrelation or FFT of the signal to find where is the maximum:

% Parameters
Fc = 1e1;
Fs = 1e3;

% Signal
t = 0:1/Fs:1;
x = sin(2*pi*Fc*t);

% FFT
Y = abs(fft(x));
[~,I] = max(Y(1:floor(end/2)));

% Frequency and period
F = I-1;
T = 1/F;

% Plot
figure; 
subplot(2,1,1); plot(t,x);
subplot(2,1,2); plot(Y);
disp(['The frequency is ',mat2str(F),'Hz, and the period is ',mat2str(T),'sec.']);

This and this post are related.

Community
  • 1
  • 1
tashuhka
  • 5,028
  • 4
  • 45
  • 64
  • it works with an implemented sin wav but hearin, when I'm hearing the audio I don't get it , thanks for your help – Engine Mar 25 '14 at 14:54
0

To go from your auto-correlation function xc to an estimate of the fundamental frequency, do:

fs = 44100; % Unit: Hz
xc = xc((length(xc) - 1) / 2 + 1: end); % Get the half on the positive time axis. 
[~, pidx] = findpeaks(xc);
period = (pidx(1) - 1) / fs;
F0 = 1 / period; % Estimated fundamental frequency. 

Note that there are other potentially more robust fundamental frequency / pitch estimation algorithms. Doing a google scholar search on "fundamental frequency estimation" or "pitch estimation" will lead you to some good reviews.

Shanqing Cai
  • 3,756
  • 3
  • 23
  • 36
0

you find all peaks using "findpeaks" funciton, now compute the difference between each peak

P=diff(locs)

your period can be :

max(P)

The peiod of 250hz sine at 22050 sample rate, is about 88, the Frequency of your signal is equivalent at the Period if you do (Fs/Period) == Frequency

If you Know the frequency of your signal you can find the period just do Fs/Frequency

ederwander
  • 3,410
  • 1
  • 18
  • 23
  • I get 251 , how could that be the period ? – Engine Mar 20 '14 at 12:16
  • where did you got that ? I have a motor with 2500rpm which means => f = 6,63 Hz ! – Engine Mar 20 '14 at 12:23
  • Wow sorry it is a _2500.wav I thought it was a sign at 250 hz lol, if you know your frequency you can know the Period what is the result of Fs/Frequency ?? – ederwander Mar 20 '14 at 12:31
  • It's for the case, that I don't know the frequency, and finding it out ! – Engine Mar 20 '14 at 12:33
  • When you not know the Frequency you need to do the autocorrelation, find all peaks, compute the difference between each peak, now find the max value, this steps can tell to you the Period – ederwander Mar 20 '14 at 12:36
  • What is the sample rate of your Signal ? – ederwander Mar 20 '14 at 12:42
  • 44100 is the sample frequency – Engine Mar 20 '14 at 13:25
  • are you using 2000 samples to do autocorrelation, it say me that you can get minimun frequency at 22.0500Hz, you say me that your frequency is about 6,63Hz you will need more than 7000 samples to track the Period lol ... – ederwander Mar 20 '14 at 13:45