Port Matlab's FFT to native Java
I want to port Matlab's Fast Fourier transform function fft() to native Java code.
As a starting point I am using the code of JMathLib where the FFT is implemented as follows:
// given double[] x as the input signal
n = x.length; // assume n is a power of 2
nu = (int)(Math.log(n)/Math.log(2));
int n2 = n/2;
int nu1 = nu - 1;
double[] xre = new double[n];
double[] xim = new double[n];
double[] mag = new double[n2];
double tr, ti, p, arg, c, s;
for (int i = 0; i < n; i++) {
xre[i] = x[i];
xim[i] = 0.0;
}
int k = 0;
for (int l = 1; l <= nu; l++) {
while (k < n) {
for (int i = 1; i <= n2; i++) {
p = bitrev (k >> nu1);
arg = 2 * (double) Math.PI * p / n;
c = (double) Math.cos (arg);
s = (double) Math.sin (arg);
tr = xre[k+n2]*c + xim[k+n2]*s;
ti = xim[k+n2]*c - xre[k+n2]*s;
xre[k+n2] = xre[k] - tr;
xim[k+n2] = xim[k] - ti;
xre[k] += tr;
xim[k] += ti;
k++;开发者_运维问答
}
k += n2;
}
k = 0;
nu1--;
n2 = n2/2;
}
k = 0;
int r;
while (k < n) {
r = bitrev (k);
if (r > k) {
tr = xre[k];
ti = xim[k];
xre[k] = xre[r];
xim[k] = xim[r];
xre[r] = tr;
xim[r] = ti;
}
k++;
}
// The result
// -> real part stored in xre
// -> imaginary part stored in xim
Unfortunately it doesn't give me the right results when I unit test it, for example with the array
double[] x = { 1.0d, 5.0d, 9.0d, 13.0d };
the result in Matlab:
28.0
-8.0 - 8.0i -8.0 -8.0 + 8.0i
the result in my implementation:
28.0
-8.0 + 8.0i -8.0 -8.0 - 8.0i
Note how the signs are wrong in the complex part.
When I use longer, more complex signals the differences between the implementations affects also the numbers. So the implementation differences does not only relate to some sign-"error".
My question: how can I adapt my implemenation to make it "equal" to the Matlab one? Or: is there already a library that does exactly this?
in order to use Jtransforms for FFT on matrix you need to do fft col by col and then join them into a matrix. here is my code which i compared with Matlab fft
double [][] newRes = new double[samplesPerWindow*2][Matrixres.numberOfSegments];
double [] colForFFT = new double [samplesPerWindow*2];
DoubleFFT_1D fft = new DoubleFFT_1D(samplesPerWindow);
for(int y = 0; y < Matrixres.numberOfSegments; y++)
{
//copy the original col into a col and and a col of zeros before FFT
for(int x = 0; x < samplesPerWindow; x++)
{
colForFFT[x] = Matrixres.res[x][y];
}
//fft on each col of the matrix
fft.realForwardFull(colForFFT); //Y=fft(y,nfft);
//copy the output of col*2 size into a new matrix
for(int x = 0; x < samplesPerWindow*2; x++)
{
newRes[x][y] = colForFFT[x];
}
}
hope this what you are looking for. note that Jtransforms represent Complex numbers as
array[2*k] = Re[k], array[2*k+1] = Im[k]
精彩评论