title: Get frequency wav audio using FFT and Complex class
body: <p>It's been asked a lot, but I still stuck about implement FFT class on Android
  I need to process my audio data using FFT...</p>
  
  <p>I already read the almost same question here <a href="https://stackoverflow.com/questions/7604011/how-can-i-get-frequency-data-from-pcm-using-fft">How can I get frequency data from PCM using FFT</a>
  and here <a href="https://stackoverflow.com/questions/7674877/how-to-get-frequency-from-fft-result">How to get frequency from fft result?</a>
  and more questions but still find no answer even after I tried the answers given...</p>
  
  <p>FFT Class I'm using: 
  <a href="http://www.cs.princeton.edu/introcs/97data/FFT.java" rel="noreferrer">http://www.cs.princeton.edu/introcs/97data/FFT.java</a></p>
  
  <p>The complex class to go with it: <a href="http://introcs.cs.princeton.edu/java/97data/Complex.java.html" rel="noreferrer">http://introcs.cs.princeton.edu/java/97data/Complex.java.html</a></p>
  
  <p>Here's my code</p>
  
  <pre><code>import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.DialogInterface;
  import android.media.AudioFormat;
  import android.media.AudioRecord;
  import android.media.MediaRecorder;
  import android.os.Bundle;
  import android.os.Environment;
  import android.view.View;
  import android.widget.Button;
  
  public class Latihan extends Activity{
          private static final int RECORDER_BPP = 16;
          private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
          private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
          private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
          private static final int RECORDER_SAMPLERATE = 44100;
          private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
          private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
          short[] audioData;
  
          private AudioRecord recorder = null;
          private int bufferSize = 0;
          private Thread recordingThread = null;
          private boolean isRecording = false;
          Complex[] fftTempArray;
          Complex[] fftArray;
          int[] bufferData;
          int bytesRecorded;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.p1);
  
          setButtonHandlers();
          enableButtons(false);
  
          bufferSize = AudioRecord.getMinBufferSize
                  (RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING)*3;
  
          audioData = new short [bufferSize]; //short array that pcm data is put into.
  
          }
  
  
      private void setButtonHandlers() {
          ((Button)findViewById(R.id.btStart)).setOnClickListener(btnClick);
          ((Button)findViewById(R.id.btStop)).setOnClickListener(btnClick);
          }
  
  
          private void enableButton(int id,boolean isEnable){
                  ((Button)findViewById(id)).setEnabled(isEnable);
          }
  
          private void enableButtons(boolean isRecording) {
                  enableButton(R.id.btStart,!isRecording);
                  enableButton(R.id.btStop,isRecording);
          }
  
          private String getFilename(){
                  String filepath = Environment.getExternalStorageDirectory().getPath();
                  File file = new File(filepath,AUDIO_RECORDER_FOLDER);
  
                  if(!file.exists()){
                          file.mkdirs();
                  }
  
                  return (file.getAbsolutePath() + "/" + System.currentTimeMillis() + AUDIO_RECORDER_FILE_EXT_WAV);
          }
  
  
          public void convert(){
  
  
  
          }
  
          public void calculate(){
              Complex[] fftTempArray = new Complex[bufferSize];
              for (int i=0; i&lt;bufferSize; i++)
              {
                  fftTempArray[i] = new Complex(audioData[i], 0);
              }
              Complex[] fftArray = FFT.fft(fftTempArray);
  
              double[] micBufferData = new double[bufferSize];
              final int bytesPerSample = 2; 
              final double amplification = 100.0; 
              for (int index = 0, floatIndex = 0; index &lt; bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
                  double sample = 0;
                  for (int b = 0; b &lt; bytesPerSample; b++) {
                      int v = bufferData[index + b];
                      if (b &lt; bytesPerSample - 1 || bytesPerSample == 1) {
                          v &amp;= 0xFF;
                      }
                      sample += v &lt;&lt; (b * 8);
                  }
                  double sample32 = amplification * (sample / 32768.0);
                  micBufferData[floatIndex] = sample32;
              }
  
  
       }
  
  
          private String getTempFilename(){
                  String filepath = Environment.getExternalStorageDirectory().getPath();
                  File file = new File(filepath,AUDIO_RECORDER_FOLDER);
  
                  if(!file.exists()){
                          file.mkdirs();
                  }
  
                  File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);
  
                  if(tempFile.exists())
                          tempFile.delete();
  
                  return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
          }
  
          private void startRecording(){
              recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                                                  RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);
  
                  recorder.startRecording();
  
                  isRecording = true;
  
                  recordingThread = new Thread(new Runnable() {
  
                          public void run() {
                                  writeAudioDataToFile();
                          }
                  },"AudioRecorder Thread");
  
                  recordingThread.start();
          }
  
          private void writeAudioDataToFile(){
                  byte data[] = new byte[bufferSize];
                  String filename = getTempFilename();
                  FileOutputStream os = null;
  
                  try {
                          os = new FileOutputStream(filename);
                  } catch (FileNotFoundException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                  }
  
                  int read = 0;
  
                  if(null != os){
                          while(isRecording){
                                  read = recorder.read(data, 0, bufferSize);
  
                                  if(AudioRecord.ERROR_INVALID_OPERATION != read){
                                          try {
                                                  os.write(data);
                                          } catch (IOException e) {
                                                  e.printStackTrace();
                                          }
                                  }
                          }
  
                          try {
                                  os.close();
                          } catch (IOException e) {
                                  e.printStackTrace();
                          }
                  }
          }
  
          private void stopRecording(){
                  if(null != recorder){
                          isRecording = false;
  
                          recorder.stop();
                          recorder.release();
  
                          recorder = null;
                          recordingThread = null;
                  }
  
                  copyWaveFile(getTempFilename(),getFilename());
                 // deleteTempFile();
          }
  
          private void deleteTempFile() {
                  File file = new File(getTempFilename());
                  file.delete();
          }
  
          private void copyWaveFile(String inFilename,String outFilename){
                  FileInputStream in = null;
                  FileOutputStream out = null;
                  long totalAudioLen = 0;
                  long totalDataLen = totalAudioLen + 36;
                  long longSampleRate = RECORDER_SAMPLERATE;
                  int channels = 2;
                  long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;
  
                  byte[] data = new byte[bufferSize];
  
                  try {
                          in = new FileInputStream(inFilename);
                          out = new FileOutputStream(outFilename);
                          totalAudioLen = in.getChannel().size();
                          totalDataLen = totalAudioLen + 36;
  
                          AppLog.logString("File size: " + totalDataLen);
  
                          WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                                          longSampleRate, channels, byteRate);
  
                          while(in.read(data) != -1){
                                  out.write(data);
                          }
  
                          in.close();
                          out.close();
                  } catch (FileNotFoundException e) {
                          e.printStackTrace();
                  } catch (IOException e) {
                          e.printStackTrace();
                  }
          }
  
          private void WriteWaveFileHeader(
                          FileOutputStream out, long totalAudioLen,
                          long totalDataLen, long longSampleRate, int channels,
                          long byteRate) throws IOException {
              //another code    
  
          }
  
          private View.OnClickListener btnClick = new View.OnClickListener() {
                  public void onClick(View v) {
                       switch(v.getId()){
                                case R.id.btStart:{
                                          AppLog.logString("Start Recording");
                                          enableButtons(true);
                                          startRecording();
                                          break;
                                  }
                                  case R.id.btStop:{
                                      AppLog.logString("Stop Recording");
                                          enableButtons(false);
                                          stopRecording();
                                          calculate();
                                          break;
  
                                  }
                          }
                  }
          }; 
  }
  </code></pre>
  
  <p>I assume the audioData array contains the raw audio data,but my code catch the exception and return "N is not a power of 2"</p>
  
  <p>Is it anything wrong with my code ??
  How do I pass it to FFT.java class and get the fftResult ??</p>
  
  <p>Or is there an other way to convert time domain data to frequency data that more easier ?</p>
  
  <p>It's been a few months since I get stuck with this... My project is too compare 2 audio of *.wav files,
  Any help would be appreciated... :)</p>