Extraction of frequencies and there indices from FFT graph ( for DTMF Detection)
24 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Here I took fft of my input signal and from here I want to extract the two frequencies and indeces, my x function have. I am trying to implement DTMF detection. I have tried using findpeaks but was not able to get appropriate answer. Below is the part of my code.
Fs=8000
x= sin(2*pi*697*.t) + sin(2*pi*1209*.t)
X1=abs(fft(x))
w_range = -pi:2*pi/length(x):pi-1/length(x);
f_range = w_range*Fs/2/pi;
plot(f_range, abs(fftshift(X1)))
2 Kommentare
dpb
am 29 Mai 2022
Show what you tried with findpeaks; you probably will need to do some peak screening but it will undoubtedly be able to find/return the desired information.
You didn't show your t vector so we can't identically reproduce your example; there is a typo in the line defining x -- the dot operator .* is written backwards as *. . Will have to correct that to run the above code as well as define t.
I'd think for this purpose you'd be better served to also return the one-sided PSD instead of two-sided, but that's a detail.
Akzeptierte Antwort
dpb
am 29 Mai 2022
>> Y=abs(fftshift(X1));
>> [pk,fpk]=findpeaks(Y,f_range)
pk =
1156.37 1132.03 1132.03 1156.37
fpk =
-1211.16 -698.04 694.71 1207.83
>>
You didn't give findpeaks the frequency vector to use to return frequency; it returns indices into the vector otherwise; that's all it's got to work with.
Also, with the 2-sded spectrum you didn't pass it the shifted/zero-centered vector but the unshifted one instead.
Above gives the nearest frequency in the frequency; notice you're not quite symmetric around the DC bin; the negative and positive frequenies aren't quite the same numerically, despite the sign.
I'd use an even number of samples and something like
L=2048;
Fs=1/0.000125;
t=(0:L-1)/Fs;
x= sin(2*pi*697*t) + sin(2*pi*1209*t);
P2=abs(fft(x))/L;
P1=P2(1:L/2+1);
P1(2:end-1)=2*P1(2:end-1);
f=Fs*[0:(L/2)]/L;
plot(f,P1)
xlim([0 2000])
[pk,fpk]=findpeaks(P1,f)
returns
>> [pk,fpk]=findpeaks(P1,f)
pk =
0.72 0.64
fpk =
695.31 1210.94
>>
NB: the peak amplitudes aren't unity and the bins still don't precisely match because the frequency resolution isn't such that the bin peaks match the actual frequency exactly. Hence the total power is distributed across the bins containing the peak and must be integrated to get the total.
Increasing the sample time or zero-padding to interpolate a finer frequency grid would get you frequency binning that would come closer to the input frequencies if these are known and fixed.
Real signal with some noise contamination will also cause some spreading of energy, averaging over the signal span can reduce its end effect as the random noise will tend to cancel.
0 Kommentare
Weitere Antworten (1)
Voss
am 29 Mai 2022
The second output from findpeaks is the location of the peaks, which are the indices in the input vector where the peaks occur. If you want to know where the peaks are in terms of frequencies, you must index your vector of frequencies f_range using those same indices.
(Also, I suspect you want to findpeaks of abs(fftshift(X1)), which is what is plotted, rather than findpeaks of X1 itself.)
t=0:0.000125:0.3;
Fs=8000;
x= sin(2*pi*697*t) + sin(2*pi*1209*t);
X1=abs(fft(x));
w_range = -pi:2*pi/length(x):pi-1/length(x);
f_range = w_range*Fs/2/pi;
plot(f_range, abs(fftshift(X1)))
% [p,i]=findpeaks(X1)
[p,i]=findpeaks(abs(fftshift(X1)))
f_range(i) % 3rd and 4th values here are 695 and 1208, close to what's expected (1st 2 are negative of those, roughly)
0 Kommentare
Siehe auch
Kategorien
Mehr zu DTMF finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!