# How to find peak frequency in an audio frequency spectrum?

I have a audio file consisting of multiple frequencies, I need to find all the frequency peaks in the frequency spectrum after doing FFT. But the issue is how can I be able to set the threshold line for the peaks.

As you can clearly see I need to find all the peaks of this spectrum but sometimes amplitude is very high and sometimes it is too low so how will we be able to know the exact frequencies present inside audio.

If we set amplitude threshold to 0.5 the peak present at 17000 Hz will now count but if we set it too low then sometimes noises becomes larger than the value itself.

The way of choosing the threshold is based off of what is called constant false alarm rate (CFAR) energy detection. The idea is that as the user you choose a desired probability of false alarm $$\text{P}_{fa}$$ to calculate what the threshold should be. If you have signal plus Gaussian noise:

$$y[n] = x[n]+w[n]$$ where $$w[n] \sim N(0, \sigma_w^2)$$ and $$\mathbb{E}\big(\big|x[n]\big|^2\big)=\sigma_x^2$$. The CFAR detector takes $$N$$ samples of $$y[n]$$ as input, computes the energy $$\frac{1}{N}\sum_{n=1}^N |y[n]|^2$$, and compares it to a threshold to determine if there was signal present in that chunk. You can just as easily make the extension for this to work on the FFT, as you will have:

\begin{align} \text{FFT}(y[n])&= \text{FFT}(x[n])+\text{FFT}(w[n]) \\ Y[k] &= X[k] + W[k] \end{align}

The choice of threshold value has been worked out in many papers on energy detection, but for the case described here it is:

$$\text{Threshold} = \bigg( \frac{Q^{-1}(\text{P}_{fa})}{\sqrt{N}} +1\bigg) \sigma_w^2$$

This intuitively should make sense. The threshold should depend on the noise power (if $$\sigma_w^2$$ increases, we need to increase the threshold to keep a constant $$\text{P}_{fa}$$), the number of samples (remember law of large numbers), and $$\text{P}_{fa}$$ (you already said that you observed how changing the threshold changes the false alarms).

There are tradeoffs to be had when choosing the parameters. For example, you could choose a very large $$N$$, but this would give you very little frequency resolution. Saying that there is a signal present between 17 kHz and 18 kHz is not very helpful for you (in fact there are multiple signals there), so you need to choose the $$N$$ small enough to get the resolution you want but not too small that you need a super high SNR for this to work properly. Perhaps choosing a moderate sized $$N$$, followed by a peak finder might be robust.

Aside: your signal has structure (periodic signals), use that to your advantage! Looking at the FFT isn't really giving you anything new, just looking at your signal in a different way. Take a look at the FFT of the autocorrelation function, you should have even cleaner peaks there.