Я работаю с проектом android. Мне нужен алгоритм FFT для обработки данных акселерометра андроида. Есть ли библиотека FFT, доступная в android sdk?
Библиотека 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;
}
}
}
}
}
Предупреждение: этот код выводится из здесь и имеет лицензию 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'
}