Подтвердить что ты не робот

Библиотека FFT в android Sdk

Я работаю с проектом android. Мне нужен алгоритм FFT для обработки данных акселерометра андроида. Есть ли библиотека FFT, доступная в android sdk?

4b9b3361

Ответ 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

Использование класса at: https://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8java-source.html

Краткое объяснение: вызов fft(), предоставляющий x как данные амплитуды, y как массив all-zeros, после того, как функция вернет ваш первый ответ, будет [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 [x.length/2] имеют данные с частотой f = 0 Гц. x [0] == x [x.length-1] имеет данные для частоты, равной частоте дискретизации (например, если вы выбрали выборку на 44000 Гц, то это означает, что f [0] реферирует до 22 кГц).

Полная процедура:

  • создать массив p [n] с 512 образцами с нулями
  • Соберите 1024 аудиокассеты, напишите их на x
  • Установите y [n] = 0 для всех n
  • вычислить fft (x, y)
  • вычислить p [n] + = x [n + 512] ^ 2 + y [n + 512] ^ 2 для всех n = 0 до 512
  • перейти 2, чтобы взять еще одну партию (после того, как 50 партий перейдут к следующему шагу)
  • plot p
  • перейти к 1

Затем скорректируйте фиксированное количество для вашего вкуса.

Число 512 определяет окно выборки, я не буду объяснять это. Просто не уменьшайте его слишком много.

Число 1024 должно всегда быть двойным от последнего числа.

Число 50 определяет скорость обновления. Если ваша частота дискретизации составляет 44000 выборок в секунду, скорость обновления будет равна: R = 44000/1024/50 = 0,85 с.

Ответ 3

kissfft - достаточно приличная библиотека, которая компилируется на Android. Он имеет более универсальную лицензию, чем FFTW (хотя FFTW, по общему признанию, лучше).

Вы можете найти привязку android для kissfft в libgdx https://github.com/libgdx/libgdx/blob/0.9.9/extensions/gdx-audio/src/com/badlogic/gdx/audio/analysis/KissFFT.java

Или, если вы хотите, чтобы на основе чистого Java-решения попытались jTransforms https://sites.google.com/site/piotrwendykier/software/jtransforms

Ответ 4

Используйте этот класс (тот, из которого получен ответ EricLarch).

Замечания по использованию

Эта функция заменяет ваши входные массивы выходом FFT.

Ввод

  • N = количество точек данных (размер вашего входного массива должен быть равен 2)
  • X = реальная часть ваших данных, которые нужно преобразовать
  • Y = мнимая часть преобразуемых данных

то есть. если ваш вход (1 + 8i, 2 + 3j, 7-i, -10-3i)

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

Выход

  • X = действительная часть выхода FFT
  • Y = мнимая часть выхода FFT

Чтобы получить свой классический график FFT, вы захотите рассчитать величину реальной и мнимой частей.

Что-то вроде:

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;
}

Также см. fooobar.com/questions/46893/... о том, как получить частоты, если ваш исходный вход был величиной против времени.

Ответ 5

@J Wang Ваша выходная величина кажется лучше, чем ответ, указанный в потоке, который вы связали, но который по-прежнему равен квадрату... величина комплексного числа

z = a + ib

рассчитывается как

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

ответ в связанном потоке предполагает, что для чистых реальных входов выходы должен использовать a 2 или a для вывода, потому что значения для

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

с b_(i) = a_(i+N/2) означает, что сложная часть в их таблице находится во второй половину выходной таблицы.

i.e вторая половина таблицы вывода для входной таблицы реалов является сопряжением реального...

поэтому z = a-ia, дающее величину

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

поэтому стоит отметить масштабные коэффициенты... Я бы порекомендовал посмотреть все это в книге или на wiki, чтобы быть уверенным.

Ответ 6

Да, есть JTransforms, которая поддерживается на GitHub здесь Доступна опция как плагин Maven здесь.

Использовать с:

compile group: 'com.github.wendykierp', name: 'JTransforms', version: '3.1'

Но с более свежими версиями Gradle вам нужно использовать что-то вроде:

dependencies {
    ... 
    implementation 'com.github.wendykierp:JTransforms:3.1'
}