ОК, так что все должно быть просто ... Но я все еще не могу понять это.Я пишу программу на Java для Android, чтобы взять FFT массива с плавающей точкой.На возвращенном спектре сложной частоты я извлекаю действительные и мнимые компоненты, чтобы можно было рассчитать некоторые параметры, такие как величина и фаза.Проблема в том, что я использую преобразование libgdx fft, использует float, однако большинство операций класса Math используют double.Это означает, что мне нужно конвертировать число с плавающей точкой в удвоение.Кажется, что он отлично работает на вещественном компоненте БПФ, однако с мнимым я получаю ошибки точности, или, скорее, я получаю для одного частотного бина я получаю мнимое значение с плавающей запятой 45.188522, однако, когда я преобразовываю в удвоенное значение, оно изменяется на -45.188522.
fft.forward(array);
fft_cpx=fft.getSpectrum();
tmpi = fft.getImaginaryPart();
tmpr = fft.getRealPart();
for(int i=0;i<array.length/2;i++)
{
real[i] = (double) tmpr[i];
imag[i] = (double) tmpi[i]; // THIS CONVERSION
mag[i] = (float)Math.sqrt((real[i]*real[i]) + (imag[i]*imag[i]));
phase[i] = (float) ((float) Math.atan2(imag[i], real[i]));
}
Я знаю и пробовал класс FloatMath для Android, однако atan2 не реализован, поэтому я вынужден независимо конвертировать в double.
Я также пробовал несколько разных преобразований, таких как:
imag[i] = tmpi[i];
imag[i] = Double.parseDouble(Float.toString(tmpi[i])); // Of course you loose accuracy
Но все они по-прежнему возвращают -45.18852 вместо 45.18852
^^^^^ ORIGINAL ^^^^^^
Подробнее:
Ниже приведен мой src-код и использование для заинтересованных.
Хорошо, я использую Ubuntu 10.10 с Eclipse JDK, Версия: Helios ServiceВыпуск 2 Android SDK: последняя версия r10 от разработчиков Android .Я компилирую для Android 1.6, API уровня 4. Я использую libgdx для fft, вы можете получить его здесь, Libgdx и убедиться, что вы добавили gdx.jar в свои библиотеки и добавили в свои библиотеки путей сборки.Если вы создаете новый проект с той же или новой активностью для Android 1.6, настраиваете AVD, у того, что я настроил, есть следующая поддержка (включенная для полноты):
SD Card yes
Accellerometer yes
DPas Support yes
Abstracted LCD Density 240
Audio Playback Support yes
Max VM Application heap size 24
camera support no
Touch Screen support yes
Вот мойкод src:
package com.spec.example;
import android.app.Activity;
import android.os.Bundle;
import com.badlogic.gdx.audio.analysis.FFT;
import java.lang.String;
import android.util.FloatMath;
import android.widget.TextView;
public class spectrogram extends Activity {
/** Called when the activity is first created. */
float[] array = {1, 6, 1, 4, 5, 0, 8, 7, 8, 6, 1,0, 5 ,6, 1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float[] array_hat,res=new float[array.length/2];
float[] fft_cpx,tmpr,tmpi,mod_spec =new float[array.length/2];
float[] real_mod = new float[array.length], imag_mod = new float[array.length];
double[] real = new double[array.length], imag= new double[array.length];
double[] mag = new double[array.length] ,phase = new double[array.length];
int n;
float tmp_val;
String strings;
FFT fft = new FFT(32, 8000);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
fft.forward(array);
fft_cpx=fft.getSpectrum();
tmpi = fft.getImaginaryPart();
tmpr = fft.getRealPart();
for(int i=0;i<array.length;i++)
{
real[i] = (double) tmpr[i]; // This works well
imag[i] = (double) tmpi[i]; // However this is creates a problem
//mag[i] = FloatMath.sqrt((tmpr[i]*tmpr[i]) + (tmpi[i]*tmpi[i])); //using FloatMath android class (works fine)
mag[i] = Math.sqrt((real[i]*real[i]) + (imag[i]*imag[i]));
phase[i]=Math.atan2(imag[i],real[i]);
/****Reconstruction****/
real_mod[i] = (float) (mag[i] * Math.cos(phase[i]));
imag_mod[i] = (float) (mag[i] * Math.sin(phase[i]));
}
fft.inverse(real_mod,tmpi,res);// inverse fft to reconstruct original array if input = output It works as it is, however it is using the input imaginary, not imag_mod
strings=String.valueOf(tmpi[1]); // Just printing the second imaginary element Calculated using: |X|e^(j*phaseofX) = |X|(cos(X) + jsin(X))
//strings=String.valueOf(imag_mod[1]); // Just printing the second imaginary element (Original returned from fft.getImaginary())
//this ^^ is the one which returns a -ve (Uncomment to test)
tv.setText(strings);
setContentView(tv);
}
}
Я новичок в разработке для Android и Java, поэтому, пожалуйста, будьте терпеливы со мной, если ответ кажется очевидным или мой синтаксис кажется странным.Надеюсь, кто-нибудь решит это ...