pitch detection: which is the most robust way to distinguish voiced from unvoiced audio

I am trying to write a voice/whistle driven synth but I am struggling with pitch detection. As a premise I must say I am quite skilled and experienced at dsp coding plus I have pretty read almost everything I could find in literature about this very thorny topic and I understood that a single robust solution does not exist. I tried and invented every possible and fancy approach in frequency domain based on analysis of the harmonic series or HPS and variations thereof, but I am still plagued by octave errors, plus the lack of a robust criterion to distinguish pitched from unpitched frames (i.e containing noise). At the end I decided to give up spectral approaches and use time domain autocorrelation (by FFT, squared magnitude plus IFFT) which turned out the most reliable approach of all even if still not 100% error prone. But again, I cannot find any reliable and robust rationale to decide when a frame is voiced/pitched and when it contains noise or transients and therefore the detected highest peak in autocorrelation has to be deemed invalid and discarded.

I found the sourcecode of a plugin called Autotalent which I judged interesting, the author there relies on a "confidence" value obtained by multiplying thr height of the highest peak in autocorrelation by the value at the corresponding position of the autocorrelation of the window used to window the processed frames but I really failed to understand the logics behind that. I tried for curiosity to use the same trick but what I get is a value which seems completely unrelated to the fact a frame is pitched or unpitched.

I kindly ask where should I start looking for a solution which is not, possibly, too complicated (everything is meant for realtime operation). Any hints ? Do you know any robust method to distinguish pitched and unpitched frames (either in time or frequency domain ) ? Thanks

• there are some pitch detection answers here and here. essentially normalize the autocorrelation so that $R_x = 1$ and then find the peak value of $R_x[k]$ where $k>0$ and that value of the normalized peak is the measure of periodicity. voiced is periodic (mostly) and unvoiced is aperiodic. Mar 8 '20 at 3:54

SWIPE is a pitch estimator that worked well for me in the past. You can find dissertation & code in MATLAB here. It might give you some ideas.

Pitch estimation is not a trivial problem. As a basic approach you can use the autocorrelation and/or cepstrum methods. The results can even be combined to obtain optimal results. For pre-processing you can do low-pass filtering and define the fundamental frequency ranges.

• I downloaded the SWIPE paper by Camacho but it is very long and difficult to follow to me... still trying to understand the principle. I am not using matlab so I can' t quite read its code but I will have a look anyway...as for cepstrum and AC as I said I found AC being far superior even if still not 100% error prone, and however I can' t figure out any obvious way to tell when a frame is pitched or not Mar 5 '20 at 18:23
• you should expect an AC peak within a specific time range (inverse to the frequency range that you expect). That peak should be quite prominent and higher in energy than the next frequency peak (first formant). Additionally when you compare several frames, there should be an F0 peak in a similar location. Mar 6 '20 at 18:54
• What language are you coding in? Mar 6 '20 at 18:55
• I code in c. Anyway, there are cases when you have 2 or 3 peaks in AC with very close magnitude, and in some cases the "wrong" peak has larger magnitude so here is an octave error... I prefer to avoid considering more than one frame at time because in cases of rapid glissando there is pretty no consistency beteeen subsequent frames Mar 7 '20 at 23:01
• Maybe you can use Praat's pitch estimation algorithms: fon.hum.uva.nl/praat/download_sources.html Mar 9 '20 at 16:04

Maybe normalized autocorrelation and zero crossig rate used together can work nicely...

Normalized autocorrelation can be defined as:

$$NAC(k) = \frac{\sum^{N-1}_{m=k}S[m-k]{\cdot}S[m]}{\sqrt{\sum^{N-1}_{m=k}S^2[m-k]\cdot\sum^{N-1}_{m=k}S^2[m]}}$$

The great advantage of using a NAC function is that we are normalizing Autocorrelation values, so these values will vary between 1 and 0 always, no matter the difference in signal energy, obviously it could be used to define confidence ... the value NAC = 1 will tell you that the signal is completely periodic, maybe you will never get 1 in real world signal lol

This can be used to make a decision whether a frame is considered voiced or not, you can track Pitch and the V/U at the same time, course NAC has the same octave error problem, to deal it this you will need ckeck subperiods ...

• Suppose $S[n]$ comes out of a DC-blocking filter. How do you know that there is no value of $k$ in which $NAC[k]<0$? Mar 7 '20 at 5:17
• I was already using normalized AC of course. What I found rather is that I have to further scale the normalized peak value in function of the AC of the window function used (in my case it is simply a rised cosine) for peaks of all corresponding frequencies to have a same magnitude. Despite that, the level of the highest AC peak still does not correlate too well with the fact a frame is pitched or not. I found a theshold of 0.7 is a good choice but the criterion is still far from optimal. Mar 13 '20 at 16:05