Как получить основную частоту, используя Harmonic Product Spectrum?
Я пытаюсь получить высоту звука от входа микрофона. Сначала я разложил сигнал из временной области в частотную область через БПФ. Я применил окно Хемминга к сигналу перед выполнением БПФ. Тогда я получаю сложные результаты БПФ. Затем я передал результаты в спектр продуктов Harmonic, где результаты были подвергнуты понижающей дискретизации, а затем умножили пики пониженной дискретизации и дали значение в виде комплексного числа. Тогда что я должен сделать, чтобы получить основную частоту?
public float[] HarmonicProductSpectrum(Complex[] data)
{
Complex[] hps2 = Downsample(data, 2);
Complex[] hps3 = Downsample(data, 3);
Complex[] hps4 = Downsample(data, 4);
Complex[] hps5 = Downsample(data, 5);
float[] array = new float[hps5.Length];
for (int i = 0; i < array.Length; i++)
{
checked
{
array[i] = data[i].X * hps2[i].X * hps3[i].X * hps4[i].X * hps5[i].X;
}
}
return array;
}
public Complex[] Downsample(Complex[] data, int n)
{
Complex[] array = new Complex[Convert.ToInt32(Math.Ceiling(data.Length * 1.0 / n))];
for (int i = 0; i < array.Length; i++)
{
array[i].X = data[i * n].X;
}
return array;
}
Я пытался получить величину, используя,
magnitude[i] = (float)Math.Sqrt(array[i] * array[i] + (data[i].Y * data[i].Y));
внутри цикла for в методе HarmonicProductSpectrum. Затем попытался получить максимальный размер бина,
float max_mag = float.MinValue;
float max_index = -1;
for (int i = 0; i < array.Length / 2; i++)
if (magnitude[i] > max_mag)
{
max_mag = magnitude[i];
max_index = i;
}
а потом я попытался получить частоту, используя,
var frequency = max_index * 44100 / 1024;
Но я получал значения мусора, такие как 1248,926, 1205,859, 2454,785 для ноты A4 (440 Гц), и эти значения не похожи на гармоники A4.
Помощь будет принята с благодарностью.