好吧,这应该很简单...但我还是不明白。我正在用java为Android编写一个程序来获取 float 组的fft。在返回的复频谱上,我提取了实部和虚部,以便可以计算一些参数,例如幅度和相位。问题是我使用的 libgdx fft 变换使用 float,但是大多数 Math 类运算使用 double。所以这意味着我需要将浮点转换为 double 。 它似乎在 fft 的实数部分上工作得很好,但是对于虚数,我得到了精度误差,或者更确切地说,我得到了一个频率箱,我得到了一个虚浮点值 45.188522,但是,当我转换为 double 时,它会更改为 -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]));
}
我知道并尝试过 android FloatMath 类,但是没有实现 atan2,所以无论如何我都被迫转换为 double 。
我还尝试了一些不同的转换,例如:
imag[i] = tmpi[i];
imag[i] = Double.parseDouble(Float.toString(tmpi[i])); // Of course you loose accuracy
但仍然返回 -45.18852 而不是 45.18852
^^^^^ 原版 ^^^^^^
更多细节:
下面是我的源代码和用法,感兴趣的人可以使用。
好的,我使用 Ubuntu 10.10 和 eclipse JDK,版本:Helios Service Release 2 Android SDK:来自android developers的最新r10 。 我正在为 android 1.6、API 级别 4 进行编译。 我正在使用 libgdx 进行 fft,你可以在这里获取它,Libgdx并确保将 gdx.jar 添加到您的库中并添加到您的构建路径库中。如果您为 android 1.6 创建一个具有相同或新 Activity 的新项目,请设置 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
这是我的源代码:
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 的新手,所以如果答案看起来很明显或者我的语法看起来很奇怪,请耐心等待。希望有人能解决...
最佳答案
可能想尝试 Double.parseDouble(new String(tmpr[i]))
而不是隐式转换:它不应该产生影响,但我见过类似的奇怪事情带花车。
关于java - Android 的浮点到 double 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5839569/