title: Java .wav file frequency analysis - incorrect frequency
body: <p>I'm working on a project where I have to analyze <code>.wav</code> files, which basically for me comes down to being able to display the frequencies that are present in said file.
  I'm using the <a href="http://www.labbookpages.co.uk/audio/javaWavFiles.html" rel="nofollow"><code>WavFile</code></a> class to read the file, and then I FFT them using the <a href="https://sites.google.com/site/piotrwendykier/software/jtransforms" rel="nofollow"><code>JTransforms</code></a> class (I actually do a <a href="http://wendykierp.github.io/JTransforms/apidocs/" rel="nofollow"><code>realForward</code></a> since I'm feeding it real numbers only).</p>
  
  <p>Everything seems to work fine, until I feed the data into Excel: I throw a line numeration in the first column (1-8000 for the file that I'm testing with) and I throw the output of the FFT into the next column. The file I'm feeding is a simple one-frequency sound, at 440Hz, with a duration of 1 second.</p>
  
  <p>After seeing the graph, though, there's a problem: I have a single frequency peak, which is exactly what I'm expecting, but the peak is situated at position 880, which is double the actual frequency. Can somebody explain to me why is that?</p>
  
  <p>Bonus question: Why am I getting values around <code>e-16</code>? Everything other than the peak should be 0, right? (I fix this by writing a 0 to the file each time the data I get is <code>&lt;= 1</code>- see code below). Maybe it's "noise"?
  <hr />
  <b>Code:</b></p>
  
  <p>There's two classes. The first one, <code>readWav</code> is used to, well, read the <code>.wav</code> file. The second one, <code>wavFFT</code>, is the one who actually FFTs the data.</p>
  
  <p>Code for <code>readWav.java</code>:</p>
  
  <pre><code>import WavFile.*;
  import java.io.*;
  
  public class readWav {
  
      // getter methods
      public static long getWavFrames(File file)
      {
          // try loop to catch any exception
          try {
              // open the wav file
              WavFile wavFile = WavFile.openWavFile(file);
  
              // return the number of frames
              return wavFile.getNumFrames();
  
          } catch (Exception e) {
              System.err.println(e);
  
              // error value
              return -1;
          }
  
      }
  
      public static int getWavChannels(File file)
      {
          // try loop to catch any exception
          try {
              WavFile wavFile = WavFile.openWavFile(file);
  
               return wavFile.getNumChannels();
  
          } catch (Exception e) {
              System.err.println(e);
  
              // error value
              return -1;
          }
      }
  
      public static double[] getWavData(File file)
      {
          // try loop to catch any exception
          try {
              // open the file
              WavFile wavFile = WavFile.openWavFile(file);
  
              // use the getter method to get the channel number (should be mono)
              int numChannels = getWavChannels(file);
  
              // same, but with the frame getter method
              int numFrames = (int) getWavFrames(file); // possible data loss
  
              // create a buffer the size of the number of frames
              double[] buffer = new double[numFrames * numChannels];
  
              // Read frames into buffer
              wavFile.readFrames(buffer, numFrames);
  
              // Close the wavFile
              wavFile.close();
  
              return buffer;
  
          } catch (Exception e) {
              System.err.println(e);
  
              // throw an error, if this runs something went wrong in reading the .wav file
              throw new RuntimeException("[could not read wav file " + file + "]");
          }
      }
  
  
      // main method, solely for testing purposes
      public static void main(String[] args)
      {
          // test, everything seems to be working
          File fichier_son = new File("son/freq1.wav");
          double[] test = getWavData(fichier_son);
          for(int i = 0; i&lt;test.length; i++){
              System.out.println(test[i]);
          }
      }
  
  }
  </code></pre>
  
  <p>Code for <code>wavFFT.java</code>:</p>
  
  <pre><code>import org.jtransforms.fft.DoubleFFT_1D;
  import java.io.File;
  import java.io.PrintWriter;
  import java.io.IOException;
  
  public class wavFFT {
  
      public static double[] realFFT(File file)
      {
          // Get the .wav data using the readWav class
          double[] data_to_fft = readWav.getWavData(file);
  
          /* Get the length of the array.
          Since we are feeding real numbers into the fft,
          the length of the array should be equal to the
          number of frames, which we get using the readWav class. */
          int n = (int) readWav.getWavFrames(file);
  
          // Make a new fft object
          DoubleFFT_1D fft = new DoubleFFT_1D(n);
  
          // Perform the realForward fft
          fft.realForward(data_to_fft);
  
          // Return the final data
          return data_to_fft;
      }
  
  
      public static void writeToFile(File in, File out) throws IOException
      {
          PrintWriter print_out = new PrintWriter(out);
          int i;
          double[] data_to_file = realFFT(in);
  
          for(i=0; i&lt;data_to_file.length; i++){
              if(data_to_file[i] &gt; 1){
                  print_out.println(data_to_file[i]);
              } else {
                  print_out.println(0);
              }
  
          }
          print_out.close();
      }
  
      // main method, solely for testing purposes
      public static void main(String[] args) {
          File fichier_son = new File("son/freq1.wav");
          double[] test = realFFT(fichier_son); 
          int i;
  
          for(i=0; i&lt;test.length; i++){
              System.out.println(test[i]);
          }
  
  
          try{
              writeToFile(fichier_son, new File("datafiles/output.txt"));
          } catch (IOException e){
              System.out.println("error");
          }
      }
  
  }
  </code></pre>