简体   繁体   English

使用gdx库和FFT计算频率(Java)

[英]Using gdx Library and FFT to Calculate Frequency (Java)

I am currently using the gdx library com.badlogic.gdx.audio.analysis.FFT and the method: 我目前正在使用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;

}

How then do I use this method to find the frequency (and then note) of sound recorded from the microphone? 然后如何使用此方法查找从麦克风录制的声音的频率(然后是音符)?

Your goal is to take all magnitudes of individual frequencies in mag[i] and to find the largest one. 您的目标是获取mag [i]中各个频率的所有幅度,并找到最大的一个。 For start, you can just loop over them and find the maximum mag[i]. 首先,您可以遍历它们并找到最大mag [i]。 Then you have to recalculate it's corresponding frequency from i index. 然后,您必须根据i索引重新计算其对应的频率。

Frequency is determined by this equation: 频率由以下公式确定:

freq = i * Fs / N;

Where Fs is sampling frequency of your time domain data (input wave data), N - number of samples you did compute FFT from. 其中Fs是您的时域数据(输入波数据)的采样频率, N您用来计算FFT的采样数。 i is the index of your frequency domain data (computed magnitudes and phases) i是您的频域数据的索引(计算的幅度和相位)

In your case you can add line like into your for cycle to debug it: 在您的情况下,您可以在for循环中添加如下行以对其进行调试:

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

Check this link for more information: How to get frequency from fft result? 检查此链接以获取更多信息: 如何从fft结果中获取频率?

Nyquist theorem 奈奎斯特定理

... states that you can perfectly reconstruct frequencies only if you have twice the samples.... for reconstructing 1000Hz, you have to have at least 2000 samples per second. ...指出只有采样数增加一倍,您才能完美地重构频率。...要重构1000Hz,每秒至少必须有2000个采样。 (Still this wave will be very distorted.). (但此波将非常失真。)。

If you have samplerate of 22000Hz, you would be able to somehow measure frequencies up to 11000Hz. 如果您的采样率为22000Hz,则可以以某种方式测量高达11000Hz的频率。 Your data in mag and phase will be meaningful to the first half of array 0..N/2 , then, you'll see just a mirror image of previous data (see the link to wikipedia page for a picture.) magphase数据将对数组0..N/2的前半部分有意义,然后,您将仅看到先前数据的镜像(有关图片,请参阅Wikipedia页面的链接。)

If you want to determine your N check this answer or google more. 如果您想确定您的N, 请查看此答案或更多Google。 Try to start with arbitrary numbers like one tenth of samplerate fs. 尝试以任意数字开始,例如采样率fs的十分之一。 The larger N, the slower will be your algorithm. N越大,算法就越慢。

Table of note frequencies 音符频率表

Simplest way is to make a table of all frequencies you will detect and then just compare your frequency with maximum magnitude to all frequencie values in table. 最简单的方法是制作一个将要检测到的所有频率的表格,然后将最大幅度的频率与表格中的所有频率值进行比较。 With a small tolerance, for example +-2% of the value in table. 公差较小,例如表中值的+ -2%。 Be sure those tolerances do not overlap for two consecutive notes. 确保两个连续的音符的公差不重叠。

Microphone input 麦克风输入

Google up keywords like java microphone input library tutorial, or check this answer . Google up关键字,例如Java麦克风输入库教程,或查看此答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM