简体   繁体   中英

Finding the peaks of a spectrogram

I am currently working on a project for my 2nd year. I am supposed to code in java a tuner. I have chosen to do a guitar tuner.

After looking around on the internet, I found a java code to do a FFT. I changed it a bit, understood it and have tested it. I know it works fine (i made a graph of it and looked at the different peaks using simple sines functions).

I am now trying to find the fundamental frequency. From what I understand, this frequency is given by the first peak.

I would thus like to create a method that finds for instance the first 5 peaks of my FFT and gives them to me with their indexes.

I first did a simple method where I compared two by two each point of my spectrogram and when the sign changed that's where I knew there was a peak. This method works great with ideal signals (without any noise). However it becomes completely useless if I add noise.

I am really bad in java (I actually started with this project and basically the simple function I described above is my master piece.... just so you get an idea of my level).

Can anyone help me? I would really appreciate it! :) Thanks in advance!

Have a great day!

fireangel

I'd say your best bet is going to be to read in all the values as an array, then run over them and 'smooth' them using a rolling average of some kind.

Afterwards, you'll have a much smoother curve. Find your peaks using this curve, then go back to your original data and use the peak indexes to find the actual peak there.

pseudocode:

// Your raw data
int[] data = getData();

// This is an array to hold your 'smoothed' data
int[] newData = new int[data.length]; 

// Iterate over your data, smooth it, and read it into your smoothed array
for (i <  data.length) {
    newData[i] = (data[i-2] + data[i-1] + data[i] + data[i+1] + data[i+2]) / 5;
}

// Use your existing peak finding function on your smoothed data, and get 
// another array of the indexes your peaks occur.
int[] peakIndexes = yourPeakFindingFunction(newData);

// Create an array to hold your final values.
int[] peakValues = new int[peakIndexes.length];

// Iterate over your peak indexes and get the original data's value at that location.
for(i < peakIndexes.length) {
    peadValues[i] = data[peakIndexes[i]];
}

Very basic and very brute-force, but it should get you on the right track for an assignment.

You'll need to play with the algorithms for smoothing the data so it's representative and for finding the actual peak at the location indicated by the smoothed data (as it won't be exact).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM