Reputation: 201
I have a signal which is a linear combination of two frequencies and I am trying to use MATLAB to determine what frequencies the (main) signal consists of. As an input I have the sample rate, rate
and a row vector with the signal data, segment
.
Now I have the following code:
N=length(segment);
freq = rate*(0:N/2)/N;
X = fft(segment);
X=X(1:N/2+1);
plot(freq*2, abs(X))
And this indeed returns a graph with two peaks, one at each of the frequencies the signal consists of. Now I want to extract these frequencies. So I want to return a variable, signal
, which is a vector of the two frequencies.
Hence, if my signal is created by the linear combination of a signal of 30 Hz
and one of 60 Hz
, then I want signal = [30,60]
. I can create a graph and then identify this, but I want to cut out that middle man and just return the found frequencies, without using any toolboxes.
How can I find my desired frequencies?
Upvotes: 0
Views: 1144
Reputation: 31
2 simpleish ways:
take the returned fft array, and replace the section with each of the peaks (1 at a time) and replace with zeros (so you end up with just 1 peak. Then do an inverse fft on the array to retrieve the signal without the zeroed frequency.
If you know the phase of the original signals - take one at a time and create a new signal with just that frequency and invert it (i.e. 0-signal - where it went up it now goes down!). And add the it to the original signal. That frequency will disappear from the audio signal with the need for fft (except to verify your results.
Upvotes: 0
Reputation: 201
What I end up doing was to use the max()
function. This would return the peak, and then the corresponding x-index would correspond with the right frequency. After retrieving this frequency, I chose a certain bracket around the peak and set those indices equal to zero. Then I would again run max()
to find the second peak and its corresponding frequency.
Upvotes: 0
Reputation: 18187
Without toolboxes: select some threshold you deem acceptable, then simply do abs(x)>threshold
, which will give you a logical array to index into freq
, giving the frequencies above the threshold. For increased accuracy you can then do things like diff()
on the resulting array, and find neighbouring indices, then select the maximum value on those consecutive indices on that sequence as the "peak" there.
Alternatively you can sort()
the values, retain the indices of the maximum n
(in your case 2) values and index that into the frequency arrays. Again not a very robust method, but quick and dirty.
Combining the two above techniques you could iteratively lower the threshold as per the sorted array, then check for things as proximity of peaks, their prominence etc.
If you don't want to implement this all yourself, see below for a one-stop function to do this.
If you are willing to use the signal processing toolbox you can use findpeaks()
. This gives you indices, which you can then use to index your frequency array to get the desired frequencies. Alternatively use the peaks = findpeaks(data,x)
syntax to directly extract the x
location (frequencies in your case).
Upvotes: 2