/// <summary> /// Pitch estimation by autocorrelation method /// </summary> /// <param name="signal"></param> /// <param name="samplingRate"></param> /// <param name="startPos"></param> /// <param name="endPos"></param> /// <param name="low"></param> /// <param name="high"></param> /// <returns></returns> public static float FromAutoCorrelation(float[] signal, int samplingRate, int startPos = 0, int endPos = -1, float low = 80, float high = 400) { if (endPos == -1) { endPos = signal.Length; } var pitch1 = (int)(1.0 * samplingRate / high); // 2,5 ms = 400Hz var pitch2 = (int)(1.0 * samplingRate / low); // 12,5 ms = 80Hz var block = new DiscreteSignal(samplingRate, signal)[startPos, endPos].Samples; var fftSize = MathUtils.NextPowerOfTwo(2 * block.Length - 1); var cc = new float[fftSize]; new Convolver(fftSize).CrossCorrelate(block, block.FastCopy(), cc); var start = pitch1 + block.Length - 1; var end = Math.Min(start + pitch2, cc.Length); var max = start < cc.Length ? cc[start] : 0; var peakIndex = start; for (var k = start; k < end; k++) { if (cc[k] > max) { max = cc[k]; peakIndex = k - block.Length + 1; } } return(max > 1.0f ? (float)samplingRate / peakIndex : 0); }