android sdk中的FFT库

我正在使用android项目。我需要FFTalgorithm来处理android加速度计数据。是否有在android sdk中可用的FFT库?

你可以使用这个类,它足够快速的实时audio分析

public class FFT { int n, m; // Lookup tables. Only need to recompute when size of FFT changes. double[] cos; double[] sin; public FFT(int n) { this.n = n; this.m = (int) (Math.log(n) / Math.log(2)); // Make sure n is a power of 2 if (n != (1 << m)) throw new RuntimeException("FFT length must be power of 2"); // precompute tables cos = new double[n / 2]; sin = new double[n / 2]; for (int i = 0; i < n / 2; i++) { cos[i] = Math.cos(-2 * Math.PI * i / n); sin[i] = Math.sin(-2 * Math.PI * i / n); } } public void fft(double[] x, double[] y) { int i, j, k, n1, n2, a; double c, s, t1, t2; // Bit-reverse j = 0; n2 = n / 2; for (i = 1; i < n - 1; i++) { n1 = n2; while (j >= n1) { j = j - n1; n1 = n1 / 2; } j = j + n1; if (i < j) { t1 = x[i]; x[i] = x[j]; x[j] = t1; t1 = y[i]; y[i] = y[j]; y[j] = t1; } } // FFT n1 = 0; n2 = 1; for (i = 0; i < m; i++) { n1 = n2; n2 = n2 + n2; a = 0; for (j = 0; j < n1; j++) { c = cos[a]; s = sin[a]; a += 1 << (m - i - 1); for (k = j; k < n; k = k + n2) { t1 = c * x[k + n1] - s * y[k + n1]; t2 = s * x[k + n1] + c * y[k + n1]; x[k + n1] = x[k] - t1; y[k + n1] = y[k] - t2; x[k] = x[k] + t1; y[k] = y[k] + t2; } } } } } 

警告:此代码似乎是从这里派生,并具有GPLv2许可证。

使用该类: https : //www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8java-source.html

简单的解释:调用fft()提供x作为你的振幅数据, y作为全零数组,在函数返回你的第一个答案后将是一个[0] = x [0] ^ 2 + y [0] ^ 2。

完整的解释: FFT是复数变换,需要N个复数,产生N个复数。 所以x [0]是第一个数字的实部,y [0]是复数部分。 这个函数就地计算,所以当函数返回时,x和y将具有变换的实部和复合部分。

一个典型的用法是计算audio的功率谱。 您的audio样本只有实数部分,您的复杂部分为0.要计算功率谱,请添加实部和复数部分的平方P [0] = x [0] ^ 2 + y [0] ^ 2。

此外,重要的是要注意,当应用于实数时,傅里叶变换产生对称的结果(x [0] == x [x.lenth-1])。 x [x.length / 2]处的数据具有来自频率f = 0Hz的数据。 x [0] == x [x.length-1]的数据的频率等于采样率(例如,如果采样频率是44000Hz,那么f [0]的估计值为22kHz)。

完整程序:

  1. 用512个带零点的采样创build数组p [n]
  2. 收集1024个audio样本,写在x上
  3. 对于所有n,设置y [n] = 0
  4. 计算fft(x,y)
  5. 对于所有n = 0到512计算p [n] + = x [n + 512] ^ 2 + y [n + 512] ^ 2
  6. 去2个批次(50个批次去下一个步骤)
  7. 图p
  8. 去1

根据你的口味调整固定的数字。

数字512定义了采样窗口,我不会解释它。 只是避免太多减less它。

数字1024必须始终是最后一个数字的两倍。

数字50定义你更新率。 如果您的采样率是每秒44000个样本,则更新率将为:R = 44000/1024/50 = 0.85秒。

kissfft是一个足够体面的库编译在Android上。 它具有比FFTW更通用的许可证(即使FFTW无疑更好)。

你可以在libgdxfind一个android的kissfft绑定https://github.com/libgdx/libgdx/blob/0.9.9/extensions/gdx-audio/src/com/badlogic/gdx/audio/analysis/KissFFT.java

或者,如果您想要一个纯粹的基于Java的解决scheme,请尝试jTransforms https://sites.google.com/site/piotrwendykier/software/jtransforms

使用这个类 (EricLarch的答案来自于这个类 )。

使用说明

该function用FFT输出取代您的inputarrays。

input

  • N =数据点的数量(input数组的大小,必须是2的幂)
  • X =要转换的数据的实际部分
  • Y =要变换的数据的虚部

即如果你的input是(1 + 8i,2 + 3j,7-i,-10-3i)

  • N = 4
  • X =(1,2,7,10)
  • Y =(8,3,-1,-3)

产量

  • X = FFT输出的实部
  • Y = FFT输出的虚部

要获得经典的FFTgraphics,您需要计算实部和虚部的大小。

就像是:

 public double[] fftCalculator(double[] re, double[] im) { if (re.length != im.length) return null; FFT fft = new FFT(re.length); fft.fft(re, im); double[] fftMag = new double[re.length]; for (int i = 0; i < re.length; i++) { fftMag[i] = Math.pow(re[i], 2) + Math.pow(im[i], 2); } return fftMag; } 

如果您的原始input是幅度与时间的关系,请参阅此StackOverflow答案以了解如何获取频率。

@J Wang你的输出幅度似乎比你所链接的线索上给出的答案要好,但仍然是幅度平方…复数的幅度

 z = a + ib 

计算为

 |z|=sqrt(a^2+b^2) 

链接线程的答案表明,对于纯真实input,输出应该使用2或者a作为输出,因为其值为

 a_(i+N/2) = -a_(i), 

其中b_(i) = a_(i+N/2)表示表中的复数部分在输出表的后半部分。

即input表的后半部分的实数input表是真实的共轭…

所以z = a-ia给出一个数量级

 |z|=sqrt(2a^2) = sqrt(2)a 

所以这是值得注意的比例因素…我会build议看看所有这一切在一本书或维基可以肯定。