Calculating the DFT with Jtransform's DoubleFFT_1D() for android

digiphd picture digiphd · Apr 21, 2011 · Viewed 9.6k times · Source

I have been searching everywhere to find a reliable method to calculate the FFT of an audio byte stream received by a native function in android SDK (through eclipse IDE). I have come across the libgdx fft and Jtransform. Jtransform Found here JTransform . I have downloaded them all and added the .jar files to a created libs folder in the root directory for the project. I have then linked the project to the new .jar files through project properties > java Build Path > Libraries.

My src java file looks like this attempting to use Jtransform.

package com.spectrum;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.view.View;

import com.badlogic.gdx.audio.analysis.*;
import edu.emory.mathcs.jtransforms.fft.*;
import edu.emory.mathcs.utils.*; 

public class spectrum extends Activity {
static byte [] sin = null;
static int f = 2000;
static int fs = 44100;
double buf;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //initialize(new SpectrumDesktop(), false);

    sin = playsin(f,fs);
    buf = bytearray2double(sin);
    public DoubleFFT_1D(512);        //<Undefined>
    public void complexForward(sin)  //<Undefined>
    playsound(sin);

}
public static double bytearray2double(byte[] b) {  
          ByteBuffer buf = ByteBuffer.wrap(b);  
          return buf.getDouble();  
      }  

 private void playsound(byte[] sin2){

int intSize = android.media.AudioTrack.getMinBufferSize(44100,     AudioFormat.CHANNEL_CONFIGURATION_STEREO,
            AudioFormat.ENCODING_PCM_16BIT);

AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
            AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);

at.play();
at.write(sin2, 0, sin2.length ); 
at.stop();
at.release();

}

@Override
protected void onDestroy() {
    super.onDestroy();
    // TODO Auto-generated method stub
    if (mMediaPlayer != null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
    }

}

 public native byte[] playsin(int f,int fs);

 /** Load jni .so on initialisation */
 static {
   System.loadLibrary("SPL");
}
}

In this example I am only using the Jtransform packages, however I have been getting the same compile error for the lingdx packages. The compiler says that DoubleFFT_1D and complexForward are undefined. So there is something I am missing, like not linking my libraries correctly, I am not sure. Any help would be greatly appreciated. Am I meant to declare an instance of DoubleFFT_1D and complexForward before onCreate or something?

I know this is a noob question, but I am new to object oriented languages and learning java on the go. Thanks :)

Answer

Adam picture Adam · Aug 8, 2012

You first need to create a Fourier Transform object

DoubleFFT_1D fft = new DoubleFFT_1D(int n);

Where n is the size of the transform you want. n may have to be 2 times bigger than you think since it expects real and imaginary parts side by side in the same input matrix.

Then you can apply your methods to fft, eg

fft.complexForward(double[]);

Strangely the result is saved into the input array.