This content has been marked as final.
Show 13 replies

1. Re: WAVE FILES & FOURIER TRANSFORM
807580 Sep 8, 2009 4:52 AM (in response to 807580)zellazode wrote:
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.
*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). 
2. Re: WAVE FILES & FOURIER TRANSFORM
807580 Sep 8, 2009 4:57 AM (in response to 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 Sep 8, 2009 5:01 AM (in response to 807580)Please repost the code using CODE tags (select the code then press the CODE button). 
4. Re: WAVE FILES & FOURIER TRANSFORM
807580 Sep 8, 2009 5:04 AM (in response to 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 Sep 8, 2009 5:09 AM (in response to 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 Sep 8, 2009 5:11 AM (in response to 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 Sep 8, 2009 5:16 AM (in response to 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 Sep 8, 2009 5:18 AM (in response to 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 Sep 8, 2009 5:21 AM (in response to 807580)zellazode wrote:
So post your code again using copypaste from your original code (not from this forum).
The += were erased too into =. Again I am extremley sorry. I understand what you mean (firstsummation and second summation). 
10. Re: WAVE FILES & FOURIER TRANSFORM
807580 Sep 8, 2009 5:28 AM (in response to 807580)
Edited by: zellazode on Sep 8, 2009 3:26 AMAudioInputStream 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:27 AM 
11. Re: WAVE FILES & FOURIER TRANSFORM
807580 Sep 8, 2009 5:53 AM (in response to 807580)(1) The use of available() in this line
is flawed since available() does not guarantee to give you the length of the stream.byte [] data = new byte [in.available()];
(2) The use of read() in this line
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.in.read(data);
(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
can overflow. You should compute j*k mod data.length. That can be done without actually computing the product.double twoPInjk = ((2 * Math.PI) / n) * (j * k);
(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 Sep 8, 2009 5:59 AM (in response to 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 Sep 8, 2009 6:21 AM (in response to 807580)zellazode wrote:
No. The use of available is wrong. Just wrong!
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
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, 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:
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 .
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.