音符检测问题的音频样本

Audio samples to musical note detection issue

我正在尝试设置一个管道,允许我从音频样本中检测音符,但是我识别样本频率内容的输入层没有落在预期值上。在下面的示例中,我...

void GenerateSinWave(fftw_complex* outputArray, int N, double frequency, double samplingRate)
{
    double sampleDurationSeconds = 1.0 / samplingRate;
    for (int i = 0; i < N; ++i)
    {
        double sampleTime = i * sampleDurationSeconds;
        outputArray[i][0] = sin(M_2_PI * frequency * sampleTime);
    }
}

void HammingWindow(fftw_complex* array, int N)
{
    static const double a0 = 25.0 / 46.0;
    static const double a1 = 1 - a0;
    for (int i = 0; i < N; ++i)
        array[i][0] *= a0 - a1 * cos((M_2_PI * i) / N);
}
int main()
{
    const int N = 4096;
    double samplingRate = 44100;
    double A4Frequency = 440;
    fftw_complex in[N] = { 0 };
    fftw_complex out[N] = { 0 };
    fftw_plan plan = fftw_plan_dft_1d(N, 0, 0, FFTW_FORWARD, FFTW_ESTIMATE);

    GenerateSinWave(in, N, A4Frequency, samplingRate);
    HammingWindow(in, N);
    fftw_execute_dft(plan, in, out);

    // Find the 4 top values
    double binHzRange = samplingRate / N;
    for (int i = 0; i < 4; ++i)
    {
        double maxValue = 0;
        int maxBin = 0;
        for (int bin = 0; bin < (N/2); ++bin)
        {
            if (out[bin][0] > maxValue)
            {
                maxValue = out[bin][0];
                maxBin = bin;
            }
        }
        out[maxBin][0] = 0; // remove value for next pass
        double binMidFreq = (maxBin * binHzRange) + (binHzRange / 2);
        std::cout << (i + 1) << " -> Freq: " << binMidFreq << " Hz - Value: " << maxValue << "\n";
    }
    fftw_destroy_plan(plan);
}

我期待接近 440 或 lower/higher 谐波,但结果远非如此:

1 -> Freq: 48.4497Hz - Value: 110.263
2 -> Freq: 59.2163Hz - Value: 19.2777
3 -> Freq: 69.9829Hz - Value: 5.68717
4 -> Freq: 80.7495Hz - Value: 2.97571

此流程的灵感主要来自 this other SO answer。我觉得我对信号处理知识的缺乏可能是原因!我的sin wave generation和window功能貌似没问题,但是audio analysis和FFTW就充满了玄机...

任何关于如何改进我对 FFTW 的使用、方法信号处理或简单地编写更好的代码的见解都将受到赞赏!

编辑:固定整数除法导致 Hamming a0 参数始终为 0。结果略有变化,但仍远未达到预期的 440 Hz

我认为您误解了 GenerateSinWave 函数中的 M_2_PI 常量。 M_2_PIdefined2.0 / PI。 您应该改用 2 * M_PI

这个错误意味着您生成的信号的频率只有 45 赫兹左右。这应该接近您看到的输出频率。

同样的常量也需要在您的 HammingWindow 函数中更正。