Android Java: Simple fft example using libgdx

This is an Android development example on how to implement the FFT libraries from Badlogic games to calculate the Fourier Transform and Inverse Fourier Transform of a small float array.

The code I have provided is developed on eclipse using the Android SDK. Before you start, be sure to download the libgdx jar library files.

Here is a good resource for learning how to install libgdx in eclipse along with some great tutorials on where to begin.

This example is very similar to a post I did last year on the reconstruction of the fast Fourier transform on a real valued signal, however, in this example I also provide access to the project files and print the result to the Android display. In this example calculate the magnitude and phase of a real one dimensional array or signal. This is useful for many apps, especially those that do image/video or audio processing of some kind. Once the magnitude and phase signals are obtained, the program reconstructs the original array with the inverse Fourier transform and simply outputs one element on the screen. Feel free to use this code.

Download source: Simple FFT.zip

Firstly we want to set up our project with the OnCreate routine:

import com.badlogic.gdx.audio.analysis.FFT; import android.app.Activity; import android.graphics.Typeface; import android.os.Bundle; import android.view.ViewGroup.LayoutParams; import android.widget.LinearLayout; import android.widget.TextView; public class SimpleFFTActivity extends Activity { float[] array = { 1, 6, 1, 4, 5, 0, 8, 7, 8, 6, 1, 0, 5, 6, 1, 8 }; static int fs = 8000; int N = 32; float[] buff; float[] buff_audio; float[] new_sig; TextView left; TextView right; TextView title; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SetupUI(); new_sig = fft(N, fs, array); for (int i = 0; i < array.length; i++) { left.append(Integer.toString((int) array[i]) + "n"); } for (int i = 0; i < new_sig.length; i++) { right.append(Integer.toString((int) Math.round(new_sig[i])) + "n"); } }

Next we want to Setup our UI and display: you’ll notice I haven’t used the android default setup with main.xml, the UI here is set up programatically.

private void SetupUI() { LayoutParams param1 = new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, (float) 1.0f); LayoutParams param2 = new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT, (float) 1.0f); LayoutParams param3 = new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); LayoutParams param4 = new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, (float) 1.0f); LinearLayout main = new LinearLayout(this); LinearLayout secondary = new LinearLayout(this); title = new TextView(this); left = new TextView(this); right = new TextView(this); main.setLayoutParams(param4); main.setOrientation(LinearLayout.VERTICAL); secondary.setLayoutParams(param1); secondary.setOrientation(LinearLayout.HORIZONTAL); title.setLayoutParams(param3); left.setLayoutParams(param2); right.setLayoutParams(param2); secondary.addView(left); secondary.addView(right); main.addView(title); main.addView(secondary); setContentView(main); title.setText("FFT Libgdx example by DigiPhD"); title.setTextSize(15); title.setTypeface(null, Typeface.BOLD); left.setText("Input:n"); right.setText("Output:n"); }

And finally, we want to add the fft function:

private float[] fft(int N, int fs, float[] array) { float[] fft_cpx, tmpr, tmpi; float[] res = new float[N / 2]; // float[] mod_spec =new float[array.length/2]; float[] real_mod = new float[N]; float[] imag_mod = new float[N]; double[] real = new double[N]; double[] imag = new double[N]; double[] mag = new double[N]; double[] phase = new double[N]; float[] new_array = new float[N]; // Zero Pad signal for (int i = 0; i < N; i++) { if (i < array.length) { new_array[i] = array[i]; } else { new_array[i] = 0; } } FFT fft = new FFT(N, 8000); fft.forward(new_array); fft_cpx = fft.getSpectrum(); tmpi = fft.getImaginaryPart(); tmpr = fft.getRealPart(); for (int i = 0; i < new_array.length; i++) { real[i] = (double) tmpr[i]; imag[i] = (double) tmpi[i]; 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, imag_mod, res); return res; }

To see a working example of this library for a signal processing application, you can take a look at my android app on the market, called ‘Enhancement‘.

This application is an educational platform for university students to learn about Digital Signal Processing (DSP) techniques and Speech Enhancement algorithms currently used in teleconferencing, radio communication, mobile phones and even forensic science. Alternatively you can check out the web site enhancementapp.com or even the ‘Enhancement Demo‘ App on the market.