从自相关数据中查找基频

信息处理 采样 自相关 爪哇
2022-02-20 20:44:46

我正在编写一个应用程序,我需要在其中找到由长号产生的音符的基频。为此,我从麦克风中获取音频数据的 FFT,然后使用从这个问题中获取的自相关代码。

完成此操作后,我将尝试通过查找最高和第二高峰位置以及它们分开的样本数量来找到基本频率。然后,我找到一个样本以 44100 的采样率持续的时间量,并将其乘以两个峰值之间的样本数,得到基频的周期。最后我使用 1/period 来找到基频本身。这是我为此编写的代码(用Java):

public double findFundamentalFrequency(double[] autoCorrelatedData){

    double max = Integer.MIN_VALUE;
    double secondMax = Integer.MIN_VALUE;
    int maxLoc = Integer.MIN_VALUE;
    int secondMaxLoc = Integer.MIN_VALUE;

    for(int i = 0; i < autoCorrelatedData.length; i++){
        if(autoCorrelatedData[i] > max){
            secondMaxLoc = maxLoc;
            secondMax = max;

            max = autoCorrelatedData[i];
            maxLoc = i;
        }
        else if(autoCorrelatedData[i] > secondMax){
            secondMax = autoCorrelatedData[i];
            secondMaxLoc = i;
        }
    }

    double samplingPeriod = 1/44100.0;
    //Log.i("a", String.valueOf(maxLoc));
    //Log.i("b", String.valueOf(secondMaxLoc));
    double period = samplingPeriod * Math.abs(maxLoc - secondMaxLoc);
    double fundamentalFreq = 1.0/period;
    return fundamentalFreq;
}

这是使用自相关找到基频的正确方法吗?这给出的答案似乎是不正确的,所以我不确定我是否在某个地方犯了错误,或者我是否以错误的方式解决这个问题。

1个回答

三个建议:

  • 尝试仅在您的预期音高范围内搜索:从比您对相关乐器的最高预期音高稍短的滞后或周期,到比预期最低音高两倍的滞后稍长的滞后。

  • 确保您的最高峰和第二高峰之间有足够的倾斜度,否则您可能会找到第一高峰的肩部,从而完全找不到任何第二高峰。

  • 您可能还想尝试使用抛物线插值来更好地估计每个音调周期(如果有)在自相关​​滞后之间。