finding peaks at specific indices/values

26 views (last 30 days)
Hey guys, I am given a wav file with 3 notes playing. The standard fundamental frequencies for these three notes are 196 Hz, 246.9 Hz, and 329.6 Hz. I have found the fundamental frequencies of these notes by finding the peaks within the range of these frequencies shown below. Now I need to find the amplitude of the first 5 harmonics where the fundamental is called the first harmonic, the component at twice the fundamental frequency is called the second harmonic etc. To do this I created an array of 1 through 5 and stored where the fundamental frequency of g was and multiplied it by the array giving me the harmonic frequency values. Now i was wondering if there was a way to find the peaks at these frequency values rather than a range like i did for the fundamental frequency. Below is the graph with the 3 fundamental frequencies pointed out.
%read the audio file x samples, output Fs
[x,Fs]= audioread('Guitar_notes.wav');
%take the fourier transform
xdft = fft(x);
xdft = xdft(1:length(x)/2+1);
% create a frequency vector
freq = 0:Fs/length(x):Fs/2;
%locs is now in frequency
[pks,locs] = findpeaks(20*log10(abs(xdft)));
%finds the peaks within the range of the fundamental frequency of the notes
indesiredrange = locs > 150 & locs < 500;
%gets the subsets within range
pks_subset = pks(indesiredrange);
locs_subset = locs(indesiredrange);
figure(3)
semilogx(freq,20*log10(abs(xdft)))
hold on
plot(freq(locs_subset), pks_subset, 'or')
hold off
xlabel('f(Hz)');
title('FFT of signal')
%harmonics 1 through 5
k = 5;
harm = 1:k;
%points of frequencies in range
z = freq(locs_subset);
%stores fundamental frequency of note g(193.8 hz)
freqG = z(36);
%gets harmonics 1 through 5
harmG = harm*freqG;

Accepted Answer

dpb
dpb on 6 Aug 2020
The actual bin frequency is unlikely to match the harmonics frequencies exactly (as in they won't match) so simply selecting the bin number is likely not going to hit the peak frequency identically.
The simplest is probably to just return the closed frequency to the actual frequency of interest returned from the findpeaks function for the peaks.
If you pass the frequency vector to findpeaks, the returned locations will be in frequency so can do direct comparison.
  4 Comments
Michael Zhu
Michael Zhu on 7 Aug 2020
Thank you for your help and I have tried implementing what you have said with the code below but I am running to an issue where the peaks are not where I want them to appear shown in the graph below.
harmonic = [1:5];
[peaks,freqs] = findpeaks(20*log10(abs(xdft)),freq);
harmB = 244.3*harmonic;
vqB = interp1(freqs,peaks,harmB, 'nearest');
figure(3)
semilogx(freq,20*log10(abs(xdft)))
hold on
plot(harmB, vqB, 'or')
hold off
xlabel('f(Hz)');
title('FFT of signal');
The above code is how i coded and plotted the graph. If you could point what I did wrong or how I could get the plots to be at the desired peaks that would be appreciated as I am very new to matlab.
dpb
dpb on 7 Aug 2020
Edited: dpb on 8 Aug 2020
Your code
[peaks,freqs] = findpeaks(20*log10(abs(xdft)),freq);
harmB = 244.3*harmonic;
vqB = interp1(freqs,peaks,harmB, 'nearest');
is returning the peak height at the nearest frequency, not the nearest frequency peak in the freqs vector...maybe it's not totally obvious but use
vqB = interp1(freqs,freqs,harmB, 'nearest');
which will then give you the closest value in the freqs vector corresponding to the nth harmonic. This will be matched with the actual peak location that was found and may not be precisely the identical value of the harmonic as discussed above owing to binning and how close the actual frequency is to the bin center.
Alternatively, if you want the location of that peak in the x-axis freq vector, use
indx = interp1(freqs,1:numel(freq),harmB, 'nearest');
which will be the index position of the nearest peak in the freq vector; the frequency of vqB above would be freq(indx) in the latter.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!