/// <summary> /// Finds fundamental frequency: calculates spectrogram, finds peaks, analyzes /// and refines frequency by diff sample values. /// </summary> /// <param name="x">The sounds samples data</param> /// <param name="sampleRate">The sound sample rate</param> /// <param name="minFreq">The min useful frequency</param> /// <param name="maxFreq">The max useful frequency</param> /// <returns>Found frequency, 0 - otherwise</returns> internal static double FindFundamentalFrequency(double[] x, int sampleRate, double minFreq, double maxFreq) { double[] spectr = FftAlgorithm.Calculate(x); int usefullMinSpectr = Math.Max(0, (int)(minFreq * spectr.Length / sampleRate)); int usefullMaxSpectr = Math.Min(spectr.Length, (int)(maxFreq * spectr.Length / sampleRate) + 1); // find peaks in the FFT frequency bins const int PeaksCount = 5; int[] peakIndices; peakIndices = FindPeaks(spectr, usefullMinSpectr, usefullMaxSpectr - usefullMinSpectr, PeaksCount); if (Array.IndexOf(peakIndices, usefullMinSpectr) >= 0) { // lowest usefull frequency bin shows active // looks like is no detectable sound, return 0 return(0); } // select fragment to check peak values: data offset const int verifyFragmentOffset = 0; // ... and half length of data int verifyFragmentLength = (int)(sampleRate / minFreq); // trying all peaks to find one with smaller difference value double minPeakValue = Double.PositiveInfinity; int minPeakIndex = 0; int minOptimalInterval = 0; for (int i = 0; i < peakIndices.Length; i++) { int index = peakIndices[i]; int binIntervalStart = spectr.Length / (index + 1), binIntervalEnd = spectr.Length / index; int interval; double peakValue; // scan bins frequencies/intervals ScanSignalIntervals(x, verifyFragmentOffset, verifyFragmentLength, binIntervalStart, binIntervalEnd, out interval, out peakValue); if (peakValue < minPeakValue) { minPeakValue = peakValue; minPeakIndex = index; minOptimalInterval = interval; } } return((double)sampleRate / minOptimalInterval); }
// Находим фундаментальную частоту: вычисляем спектрограмму, находим пики, анализируем //х - звуковые сэмплы //sampleRate частота семплирования //minFreq минимальная полезная частота //maxFreq максимальная полезная частота //returns Найденная частота, 0 - в противном случае internal static double FindFundamentalFrequency(double[] x, int sampleRate, double minFreq, double maxFreq) { double[] spectr = FftAlgorithm.Calculate(x); int usefullMinSpectr = Math.Max(0, (int)(minFreq * spectr.Length / sampleRate)); int usefullMaxSpectr = Math.Min(spectr.Length, (int)(maxFreq * spectr.Length / sampleRate) + 1); // находим пики частот по БПФ const int PeaksCount = 5; int[] peakIndices; peakIndices = FindPeaks(spectr, usefullMinSpectr, usefullMaxSpectr - usefullMinSpectr, PeaksCount); if (Array.IndexOf(peakIndices, usefullMinSpectr) >= 0) { // // если звука не будет - вернет 0 return(0); } // выбирает фрагмент для регистрации пиковых значений: смещение данных const int verifyFragmentOffset = 0; // ... и половина длины данных int verifyFragmentLength = (int)(sampleRate / minFreq); // перебираем все пики для поиска одного с наименьшим отличием от других double minPeakValue = Double.PositiveInfinity; int minPeakIndex = 0; int minOptimalInterval = 0; for (int i = 0; i < peakIndices.Length; i++) { int index = peakIndices[i]; int binIntervalStart = spectr.Length / (index + 1), binIntervalEnd = spectr.Length / index; int interval; double peakValue; // сканирование частот/интервалов ScanSignalIntervals(x, verifyFragmentOffset, verifyFragmentLength, binIntervalStart, binIntervalEnd, out interval, out peakValue); if (peakValue < minPeakValue) { minPeakValue = peakValue; minPeakIndex = index; minOptimalInterval = interval; } } return((double)sampleRate / minOptimalInterval); }
protected override void ProcessData(short[] data) { foreach (short[] portion in windowBuffer.Process(data)) { for (int i = 0; i < buffer.Length; i++) { buffer[i] = portion[i]; } double[] spectr = FftAlgorithm.Calculate(buffer); owner.OnSpectrographData(new SpectrographDataEventArgs(spectr)); } }