Je travaille avec le projet Android. J'ai besoin d'un algorithme FFT pour traiter les données de l'accéléromètre Android. Y a-t-il une bibliothèque FFT disponible dans Android sdk?
Vous pouvez utiliser cette classe, qui est suffisamment rapide pour une analyse audio en temps réel
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;
}
}
}
}
}
Attention: ce code semble dériver de ici , et possède une licence GPLv2.
Utilisation de la classe sur: https://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8Java-source.html
Brève explication: appelez fft () fournissant x comme vous les données d'amplitude, y comme tableau de tous les zéros, après le retourne votre première réponse sera un [0] = x [0] ^ 2 + y [0] ^ 2.
Explication complète: [~ # ~] fft [~ # ~] est une transformation complexe, il faut [~ # ~] n [~ # ~] nombres complexes et produit [~ # ~] n [~ # ~] nombres complexes. Donc x [0] est la partie réelle du premier nombre, y [0] est la partie complexe. Cette fonction calcule sur place, donc lorsque la fonction retourne x et y aura les parties réelles et complexes de la transformation.
Une utilisation typique consiste à calculer le spectre de puissance de l'audio. Vos échantillons audio n'ont qu'une partie réelle, votre partie complexe est 0. Pour calculer le spectre de puissance, vous ajoutez le carré des parties réelle et complexe P [0] = x [0] ^ 2 + y [0] ^ 2.
Il est également important de noter que la transformée de Fourier, lorsqu'elle est appliquée sur des nombres réels, donne un résultat symétrique (x [0] == x [x.lenth-1]). Les données à x [x.length/2] ont les données de la fréquence f = 0Hz. x [0] == x [x.length-1] a les données pour une fréquence égale à avoir la fréquence d'échantillonnage (par exemple, si vous échantillonnez était à 44000 Hz, cela signifie que f [0] se réfère à 22 kHz).
Procédure complète:
Ensuite, ajustez le nombre fixe à votre goût.
Le nombre 512 définit la fenêtre d'échantillonnage, je ne l'expliquerai pas. Évitez simplement de le réduire trop.
Le nombre 1024 doit toujours être le double du dernier nombre.
Le nombre 50 définit votre taux de mise à jour. Si votre taux d'échantillonnage est de 44000 échantillons par seconde, votre taux de mise à jour sera: R = 44000/1024/50 = 0,85 seconde.
kissfft est une bibliothèque suffisamment décente qui se compile sur Android. Il a une licence plus polyvalente que FFTW (même si FFTW est certes meilleure).
Vous pouvez trouver une liaison Android pour kissfft dans libgdx https://github.com/libgdx/libgdx/blob/0.9.9/extensions/gdx-audio/src/com /badlogic/gdx/audio/analysis/KissFFT.Java
Ou si vous souhaitez une pure Java essayez jTransforms https://sites.google.com/site/piotrwendykier/software/jtransforms
Utilisez ceci classe (celui dont la réponse d'EricLarch est dérivée).
Notes d'utilisation
Cette fonction remplace vos tableaux d'entrées par la sortie FFT.
Entrée
c'est-à-dire si votre entrée est (1 + 8i, 2 + 3j, 7-i, -10-3i)
Sortie
Pour obtenir votre graphique FFT classique, vous souhaiterez calculer la magnitude des parties réelles et imaginaires.
Quelque chose comme:
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;
}
Voir aussi cette réponse StackOverflow pour savoir comment obtenir des fréquences si votre entrée d'origine était la magnitude en fonction du temps.
Oui, il y a JTransforms
qui est maintenu sur githubici et disponible en tant que plugin Mavenici .
Utiliser avec:
compile group: 'com.github.wendykierp', name: 'JTransforms', version: '3.1'
Mais avec les versions plus récentes de Gradle, vous devez utiliser quelque chose comme:
dependencies {
...
implementation 'com.github.wendykierp:JTransforms:3.1'
}
@J Wang Votre magnitude de sortie semble meilleure que la réponse donnée sur le fil que vous avez lié, mais qui est toujours au carré ... la magnitude d'un nombre complexe
z = a + ib
est calculé comme
|z|=sqrt(a^2+b^2)
la réponse dans le fil de discussion suggère que pour les entrées réelles pures, les sorties devraient utiliser n2 ou a pour la sortie car les valeurs de
a_(i+N/2) = -a_(i),
avec b_(i) = a_(i+N/2)
signifiant que la partie complexe de leur tableau se trouve dans la seconde moitié du tableau de sortie.
c'est-à-dire que la seconde moitié du tableau de sortie pour un tableau d'entrée de réels est le conjugué du réel ...
donc z = a-ia
donnant une magnitude
|z|=sqrt(2a^2) = sqrt(2)a
il vaut donc la peine de noter les facteurs d'échelle ... Je recommanderais de regarder tout cela dans un livre ou sur wiki pour être sûr.