Android Sdk 中的 FFT 库 [已关闭]

2022-09-01 04:25:10

我正在与安卓项目合作。我需要FFT算法来处理安卓加速度计数据。Android sdk中是否有FFT库?


答案 1

您可以使用此类,该类对于实时音频分析来说足够快

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许可证。


答案 2

在以下位置使用类:https://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8java-source.html

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

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

一种典型的用法是计算音频的功率谱。您的音频样本只有真实部分,您的复杂部分是0。要计算功率谱,您需要将实部和复数部分的平方 P[0]=x[0]^2+y[0]^2 相加。

同样重要的是要注意,傅里叶变换在应用于实数时,会产生对称的结果(x[0]==x[x.lenth-1])。x[0]==x[x.length-1]的数据来自频率f=0Hz.x[x.length-1],其频率等于采样率的数据(例如,如果采样频率为44000Hz,则意味着f[0]反频器为22kHz)。

完整程序:

  1. 创建数组 p[n] 包含 512 个零的样本
  2. 收集1024个音频样本,将它们写在x上
  3. 为所有 n 设置 y[n]=0
  4. 计算 fft(x,y)
  5. 计算 p[n]+=x[n+512]^2+y[n+512]^2 对于所有 n=0 到 512
  6. 转到 2 以采取另一批(50 批次后转到下一步)
  7. 绘图 p
  8. 转到 1

比调整固定数量根据您的口味。

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

数字 1024 必须始终是最后一个数字的双精度。

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


推荐