Библиотека FFT в Android Sdk [закрыта]
Я работаю с Android Project.Мне нужен алгоритм FFT для обработки данных акселерометра Android.Доступна ли библиотека FFT в Android sdk?
Переведено автоматически
Ответ 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;
}
}
}
}
}
Предупреждение: этот код, похоже, является производным от here и имеет лицензию 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 [x.длина / 2] содержат данные с частотой f = 0 Гц. x [0]== x [x.длина-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
- перейти ко второму этапу, чтобы выполнить еще один пакет (после 50 пакетов переходите к следующему шагу)
- график 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;
}
Также смотрите этот ответ StackOverflow, чтобы узнать, как получить частоты, если ваш исходный ввод был величиной в зависимости от времени.