13 Replies Latest reply: Sep 8, 2009 6:21 AM by 807580 RSS

    WAVE FILES & FOURIER TRANSFORM

    807580
      Hello,
      I want to retrieve information out of a Wav file - for a Fourier transfrom.

      I am using AudioInputStream. The problem is that I would prefer it to be in float(s), because the bytes affect my analysis.

      Alterantivley, if you could provide me with a link to an FT of a wave file, that works well*, I'd be very greatful.

      *By works well, I mean - The FT I have now computes for a certain frequency, a certain amplitude. When I change the wave file to be quieter, the fourier transfrom doesn't always show a change in amplitude (sometimes increase).
      I printed the array of bytes produced by AudioInputStream, and it looks something like this:
      100
      0
      -98
      1
      6
      32
      -45

      and on the more quiet one, it looks like this:
      24
      0
      -23
      1
      1
      1
      -2

      So you see - 1,6 and 32 were all mapped to the value 1, once the sample was of lower volume. I think this is affecting my analysis, and would prefer to retrieve float information out of WAV files.

      Could you help?

      Also, I have encountered pages saying that since java has no unsigned types, one should get the information in bytes, and then compose new numbers out of pair of bytes (depandant on big/small-endian). Is this really necessary? Will it affect my results if I move from WIN to Linux?

      Thank you all.
        • 1. Re: WAVE FILES & FOURIER TRANSFORM
          807580
          zellazode wrote:
          *By works well, I mean - The FT I have now computes for a certain frequency, a certain amplitude. When I change the wave file to be quieter, the fourier transfrom doesn't always show a change in amplitude (sometimes increase).
          Then either the FT code is faulty or your use of it is faulty but since we can't see either your code or the FT code you can't really expect help.
          • 2. Re: WAVE FILES & FOURIER TRANSFORM
            807580
            Sorry,
                 AudioInputStream in = AudioSystem.getAudioInputStream(new File("C:\\c_guitar.wav"));
                 byte [] data = new byte [in.available()];
                 in.read(data);
                 in.close();

                 //Get Audio Format information
            AudioFormat audioFormat = in.getFormat();

                 //Calculate the sample rate
                 float sample_rate = audioFormat.getSampleRate();
                 
            //Calculate the length in seconds of the sample
                 float T = in.getFrameLength() / audioFormat.getFrameRate();
                 
            //Calculate the number of equidistant points in time
                 int n = (int) (T * sample_rate) / 2;

                 //Calculate the time interval at each equidistant point
                 float h = (T / n);
                 
                 
                 //do the DFT for each value of x sub j and store as f sub j
                 double f[] = new double[n/2];
                      
                 for (int j = 20; j < n/2; j++) {

                           double firstSummation = 0;
                           double secondSummation = 0;
                           

                           for (int k = 0; k < data.length; k++) {
                                double twoPInjk = ((2 * Math.PI) / n) * (j * k);
                                firstSummation += data[k] * Math.cos(twoPInjk);
                                secondSummation += data[k] * Math.sin(twoPInjk);
                 
                           }

            f[j] = Math.abs( Math.sqrt(Math.pow(firstSummation,2) +
            Math.pow(secondSummation,2)) );
                      
                      double amplitude = 2*f[j]/n;
                      double frequency = j * sample_rate / n;
                      System.out.println("frq = "+frequency+", amp = "+amplitude);
            }
            }
            • 3. Re: WAVE FILES & FOURIER TRANSFORM
              807580
              Please repost the code using CODE tags (select the code then press the CODE button).
              • 4. Re: WAVE FILES & FOURIER TRANSFORM
                807580
                 AudioInputStream in = AudioSystem.getAudioInputStream(new File("C:\\c_guitar.wav"));
                 byte [] data = new byte [in.available()];
                 in.read(data);
                 in.close();
                
                 //Get Audio Format information 
                 AudioFormat audioFormat = in.getFormat();
                 //Calculate the sample rate
                 float sample_rate = audioFormat.getSampleRate();
                 //Calculate the length in seconds of the sample
                 float T = in.getFrameLength() / audioFormat.getFrameRate();
                 //Calculate the number of equidistant points in time
                 int n = (int) (T sample_rate) / 2;
                 //Calculate the time interval at each equidistant point
                 float h = (T / n);
                
                
                 //do the DFT for each value of x sub j and store as f sub j
                 double f[] = new double[n/2];
                
                 for (int j = 20; j < n/2; j++) {
                
                   double firstSummation = 0;
                   double secondSummation = 0;
                
                
                   for (int k = 0; k < data.length; k++) {
                              double twoPInjk = ((2 Math.PI) / n) (j k);
                              firstSummation = data[k] Math.cos(twoPInjk);
                              secondSummation = data[k] Math.sin(twoPInjk);
                    }
                   f[j] = Math.abs( Math.sqrt(Math.pow(firstSummation,2) 
                   Math.pow(secondSummation,2)) ); 
                  }
                 double amplitude = 2*f[j]/n;
                 double frequency = j * sample_rate / n;
                 System.out.println("frq = "+frequency", amp = "+amplitude);
                  }
                } 
                • 5. Re: WAVE FILES & FOURIER TRANSFORM
                  807580
                  That code does not do a DFT! Either you have coded it wrongly or something has swallowed all arithmetic operators inside the inner loop. Maybe the forum markup is to blame. I hope you did not just copy the code from your first try at posting code.
                  • 6. Re: WAVE FILES & FOURIER TRANSFORM
                    807580
                    I am so sorry for the mess :(
                     AudioInputStream in = AudioSystem.getAudioInputStream(new File("C:\\c_guitar.wav"));
                     byte [] data = new byte [in.available()];
                     in.read(data);
                     in.close();
                     
                     //Get Audio Format information 
                     AudioFormat audioFormat = in.getFormat();
                     //Calculate the sample rate
                     float sample_rate = audioFormat.getSampleRate();
                     //Calculate the length in seconds of the sample
                     float T = in.getFrameLength() / audioFormat.getFrameRate();
                     //Calculate the number of equidistant points in time
                     int n = (int) (T*sample_rate) / 2;
                     //Calculate the time interval at each equidistant point
                     float h = (T / n);
                     
                     
                     //do the DFT for each value of x sub j and store as f sub j
                     double f[] = new double[n/2];
                     
                     for (int j = 20; j < n/2; j++) {
                     
                       double firstSummation = 0;
                       double secondSummation = 0;
                     
                     
                       for (int k = 0; k < data.length; k++) {
                                  double twoPInjk = ((2*Math.PI) / n) (j*k);
                                  firstSummation = data[k]*Math.cos(twoPInjk);
                                  secondSummation = data[k]*Math.sin(twoPInjk);
                        }
                       f[j] = Math.abs( Math.sqrt(Math.pow(firstSummation,2) 
                       Math.pow(secondSummation,2)) ); 
                      }
                     double amplitude = 2*f[j]/n;
                     double frequency = j * sample_rate / n;
                     System.out.println("frq = "+frequency", amp = "+amplitude);
                      }
                    } 
                     
                    • 7. Re: WAVE FILES & FOURIER TRANSFORM
                      807580
                      If that really is your code then the inner loop is wrong since your summations arn't. Go back to your source for the DFT and check.
                      • 8. Re: WAVE FILES & FOURIER TRANSFORM
                        807580
                        The += were erased too into =. Again I am extremley sorry. I understand what you mean (firstsummation and second summation).
                        • 9. Re: WAVE FILES & FOURIER TRANSFORM
                          807580
                          zellazode wrote:
                          The += were erased too into =. Again I am extremley sorry. I understand what you mean (firstsummation and second summation).
                          So post your code again using copy-paste from your original code (not from this forum).
                          • 10. Re: WAVE FILES & FOURIER TRANSFORM
                            807580
                                 AudioInputStream in = AudioSystem.getAudioInputStream(new File("C:\\c_guitar.wav"));
                                 byte [] data = new byte [in.available()];
                                 in.read(data);
                                 in.close();
                            
                                 //Get Audio Format information
                                 AudioFormat audioFormat = in.getFormat();
                                 //Calculate the sample rate
                                 float sample_rate = audioFormat.getSampleRate();
                                 //Calculate the length in seconds of the sample
                                 float T = in.getFrameLength() / audioFormat.getFrameRate();
                                 //Calculate the number of equidistant points in time
                                 int n = (int) (T * sample_rate) / 2;
                                 //Calculate the time interval at each equidistant point
                                 float h = (T / n);
                                 
                                 //do the DFT for each value of x sub j and store as f sub j
                                 double f[] = new double[n/2];
                                                
                                 for (int j = 20; j < n/2; j++) {
                                                       double firstSummation = 0;
                                                       double secondSummation = 0;
                                           
                                                       for (int k = 0; k < data.length; k++) {
                                                              double twoPInjk = ((2 * Math.PI) / n) * (j * k);
                                                              firstSummation +=  data[k] * Math.cos(twoPInjk);
                                                              secondSummation += data[k] * Math.sin(twoPInjk);
                                                       }
                                                      f[j] = Math.abs( Math.sqrt(Math.pow(firstSummation,2) + Math.pow(secondSummation,2)) );
                                                      double amplitude = 2*f[j]/n;
                                                      double frequency = j * sample_rate / n;
                                          System.out.println("frq = "+frequency+", amp = "+amplitude);
                                                }
                            Edited by: zellazode on Sep 8, 2009 3:26 AM

                            Edited by: zellazode on Sep 8, 2009 3:27 AM
                            • 11. Re: WAVE FILES & FOURIER TRANSFORM
                              807580
                              (1) The use of available() in this line
                              byte [] data = new byte [in.available()];
                              is flawed since available() does not guarantee to give you the length of the stream.
                              (2) The use of read() in this line
                              in.read(data);
                              is flawed since read() does not guarantee to read all the bytes requested. It returns the number of bytes actually read. You should read the bytes a chunk at a time from the stream and write them to a ByteArrayOutputStream. When you reach EOF then the ByteArrayOutputStream will contain all the bytes.
                              (3) You need to read from the audio format the information about how many bytes per sample there are. This will most likely be either be two or one and then you must convert the bytes to sample values. Information in the format will tell you whether the bytes are compressed, signed, excess 0x80, pairs in excess 0x8000 or pairs signed.
                              (4) If you have a large number of samples then the j*k term in
                              double twoPInjk = ((2 * Math.PI) / n) * (j * k);
                              can overflow. You should compute j*k mod data.length. That can be done without actually computing the product.
                              (5) Math.pow(firstSummation,2) is very very very slow when all you need is
                              firstSummation*firstSummation
                              .

                              The DFT you have implemented is very very very very slow and has significant problems with the accumulation of errors. You need to look at the Fast Fourier Transform which is a means of rapidly and accurately computing the DFT.

                              What is the magic number 20 being used for? Surely if you are going to ignore some of the lower frequencies you should make that based on frequency,

                              Your current approach will give you an average spectrum taken over the whole of the sample. This can be significantly different from the second to second spectrum. Also, if you are working with very long time periods then you could run out of memory.

                              Edited by: sabre150 on Sep 8, 2009 11:51 AM
                              • 12. Re: WAVE FILES & FOURIER TRANSFORM
                                807580
                                Thank you for your comments, but:
                                I just want to understand how DFT works, and then I will make it better. As for all the hundred of things that can go wrong, I am not worreid about that now.
                                1) I am using a very short wav file, and so avaialble() is enough (according to a print out I did)
                                4) thank you for the advice

                                Now, when I preform the DFT is finds the right frequency! However, it returns let's say amplitude 50. Then I change the wave file to be a bit quieter, but i get ampltude of 52! Only when I decrease the volume much more, I start seeing a difference in amplitudes (going down).

                                Now, according to my prints, the array of data looks like this:
                                23,100,0,-50,1,20
                                and after volume decreasing:
                                1,25,0,-2,1,1 (all numbers were cut by 4, but 1s stayed 1s).

                                I think that this is the cause of my problem - and so - all I am asking is: Is there a way to get this information in floats, so that I may get:
                                0.99,25,0,-0.05,0.05,0.8

                                or something like this?

                                If not, since my DFT is bad as it is - could you please direct me to a good resource with a JAVA impl of this?

                                Thank you very much for your help.
                                • 13. Re: WAVE FILES & FOURIER TRANSFORM
                                  807580
                                  zellazode wrote:
                                  Thank you for your comments, but:
                                  I just want to understand how DFT works, and then I will make it better. As for all the hundred of things that can go wrong, I am not worreid about that now.
                                  1) I am using a very short wav file, and so avaialble() is enough (according to a print out I did)
                                  No. The use of available is wrong. Just wrong!
                                  4) thank you for the advice

                                  Now, when I preform the DFT is finds the right frequency! However, it returns let's say amplitude 50. Then I change the wave file to be a bit quieter, but i get ampltude of 52! Only when I decrease the volume much more, I start seeing a difference in amplitudes (going down).
                                  Could it be that the samples are not just the signed bytes your code assumes (maybe they are two bytes per sample). What does the audio format object say about them?

                                  >
                                  Now, according to my prints, the array of data looks like this:
                                  23,100,0,-50,1,20
                                  and after volume decreasing:
                                  1,25,0,-2,1,1 (all numbers were cut by 4, but 1s stayed 1s).

                                  I think that this is the cause of my problem - and so - all I am asking is: Is there a way to get this information in floats, so that I may get:
                                  0.99,25,0,-0.05,0.05,0.8

                                  or something like this?

                                  If not, since my DFT is bad as it is - could you please direct me to a good resource with a JAVA impl of this?
                                  Not really - simple DFT is just too poor to use in ernest. I use my own mixed radix FFT implementation. If you decide to change to using the FFT then you could look at the very straight forwards implementation about half way down the page here .

                                  >
                                  Thank you very much for your help.