【问题标题】:Using gdx Library and FFT to Calculate Frequency (Java)使用 gdx 库和 FFT 计算频率 (Java)
【发布时间】:2013-12-06 12:59:22
【问题描述】:

我目前正在使用gdx库com.badlogic.gdx.audio.analysis.FFT和方法:

private float[] fft(int N, int fs, float[] array) {
    float[] fft_cpx, tmpr, tmpi;
    float[] res = new float[N / 2];
    // float[] mod_spec =new float[array.length/2];
    float[] real_mod = new float[N];
    float[] imag_mod = new float[N];
    double[] real = new double[N];
    double[] imag = new double[N];
    double[] mag = new double[N];
    double[] phase = new double[N];
    float[] new_array = new float[N];
    // Zero Pad signal
    for (int i = 0; i < N; i++) {
        if (i < array.length) {
            new_array[i] = array[i];
        } 
        else {
            new_array[i] = 0;
        }
    }

    FFT fft = new FFT(N, 8000);

    fft.forward(new_array);
    fft_cpx = fft.getSpectrum();
    tmpi = fft.getImaginaryPart();
    tmpr = fft.getRealPart();
    for (int i = 0; i < new_array.length; i++) {
        real[i] = (double) tmpr[i];
        imag[i] = (double) tmpi[i];

        mag[i] = Math.sqrt((real[i] * real[i]) + (imag[i] * imag[i]));
        phase[i] = Math.atan2(imag[i], real[i]);

        /**** Reconstruction ****/
        real_mod[i] = (float) (mag[i] * Math.cos(phase[i]));
        imag_mod[i] = (float) (mag[i] * Math.sin(phase[i]));

    }
    fft.inverse(real_mod, imag_mod, res);
    return res;

}

那么我该如何使用这种方法来找到从麦克风录制的声音的频率(然后是音符)?

【问题讨论】:

    标签: java android signal-processing fft frequency


    【解决方案1】:

    您的目标是获取 mag[i] 中各个频率的所有幅度并找到最大的频率。首先,您可以遍历它们并找到最大 mag[i]。然后你必须从i索引重新计算它对应的频率。

    频率由以下公式确定:

    freq = i * Fs / N;
    

    Fs 是您的时域数据(输入波数据)的采样频率,N - 您计算 FFT 的样本数。 i 是您的频域数据的索引(计算的幅度和相位)

    在你的情况下,你可以在你的 for 循环中添加行来调试它:

    double freq = (double)i*(double)fs/(double)N;
    System.out.println("Frequency: "+ Double.toString(freq) + "Magnitude: "+ Double.toString(mag[i]));
    

    查看此链接了解更多信息: How to get frequency from fft result?

    Nyquist theorem

    ... 声明只有当您有两倍的样本时,您才能完美地重建频率......对于重建 1000Hz,您必须每秒至少有 2000 个样本。 (这个波还是会很失真。)。

    如果您的采样率为 22000Hz,您将能够以某种方式测量高达 11000Hz 的频率。您在magphase 中的数据将对数组0..N/2 的前半部分有意义,然后,您将看到之前数据的镜像(请参阅wikipedia page 的链接以获取图片。)

    如果你想确定你的 N check this answer 或谷歌更多。尝试从任意数字开始,例如采样率 fs 的十分之一。 N 越大,你的算法就越慢。

    Table of note frequencies

    最简单的方法是制作一个您将检测到的所有频率的表格,然后将您的频率与最大幅度进行比较,以与表格中的所有频率值进行比较。公差很小,例如表中值的 +-2%。确保这些公差不会在两个连续的音符上重叠。

    麦克风输入

    搜索java麦克风输入库教程之类的关键字,或查看this answer

    【讨论】:

    • 对于麦克风输入,我遇到了一些麻烦。我以为我发现了如何使用 javax.sound 来做到这一点,但我使用的是没有该软件包的 Android SDK。我想我需要使用 android.media.audiorecord 但我不知道如何使用,也找不到太多关于它的信息。你有什么建议/信息可以给我吗?其他一切看起来都不错。
    • 你应该重新标记你的android问题,如果你对麦克风输入有困难,你可以从生成带有sin函数的测试输入开始,搜索带有麦克风输入的android示例项目
    猜你喜欢
    • 2021-03-09
    • 2014-03-18
    • 1970-01-01
    • 2014-12-18
    • 2011-05-12
    • 2013-04-10
    • 2020-05-22
    • 1970-01-01
    • 2017-06-06
    相关资源
    最近更新 更多