10

Before, I asked question about Get frequency wav audio using FFT and Complex class ,

There, I need to calculate FFT value from AudioRecord input --> from microphone , I somehow managed to get the FFT value...

Now I need to calculate FFT value from *.wav audio file that I saved before, I saved the audio in 'raw' folder inside 'res' folder from my project

I still using the same FFT Class: http://www.cs.princeton.edu/introcs/97data/FFT.java

The complex class to go with it: http://introcs.cs.princeton.edu/java/97data/Complex.java.html

I use this method to read audio file from my raw foldern, then I call method calculateFFT to go with it

private static final int RECORDER_BPP = 16;
  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;


private void asli(){

            int counter = 0;
            int data;
            InputStream inputStream  = getResources().openRawResource(R.raw.b1);
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            List<Integer> content = new ArrayList<Integer>(); 

            try {
                while ((data = dataInputStream.read()) != -1) {
                    content.add(data);
                    counter++; }
            } catch (IOException e) {
                e.printStackTrace();}

                int[] b = new int[content.size()];
                int cont = 0;
                byte[] audio = convertArray(b);
        }

Method to convert to byte

public byte[] convertArray(int[] array) { 

            int minBufferSize = AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING);
                AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING,minBufferSize, AudioTrack.MODE_STREAM);

        byte[] newarray = new byte[array.length];
        for (int i = 0; i < array.length; i++) {
        newarray[i] = (byte) ((array[i]) & 0xFF);       }

            absNormalizedSignal = calculateFFT(newarray);
            return newarray;
        }

And this is the CalculateFFT method

public double[] calculateFFT(byte[] signal)
        {           
            final int mNumberOfFFTPoints =1024;
            double mMaxFFTSample;
            double temp;
            Complex[] y;
            Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
            double[] absSignal = new double[mNumberOfFFTPoints/2];

            for(int i = 0; i < mNumberOfFFTPoints; i++){
                temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
                complexSignal[i] = new Complex(temp,0.0);
            }

            y = FFT.fft(complexSignal);

            mMaxFFTSample = 0.0;
            mPeakPos = 0;
            for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
            {
                 absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
                 if(absSignal[i] > mMaxFFTSample)
                 {
                     mMaxFFTSample = absSignal[i];
                     mPeakPos = i;
                 } 
            }

            return absSignal;

        }

I used this CalculateFFT method too to process audio from AudioRecorder --> that one with microphone input before... I managed to get value from the AudioRecorder, but I failed to get value from my audio file... I'm not planning to play the audio.. I just need to process it with FFT.

Is there any wrong with my code ?? :o Seems like I fail at getting value from method Asli(); But I dont know which part is wrong..

Any help would be appreciated... :) Thanks

Community
  • 1
  • 1
raisa_
  • 594
  • 2
  • 10
  • 28
  • 1
    You've just posted a lot of code, but a very unclear description of in what way your code fails, and what you've already tried to resolve it. – marko Jul 10 '13 at 08:12
  • 1
    @Marko I'm sorry about that.. :( Since I read many question without passing proper codes then people vote it down..very unclear description in what my codes fails --> I already wrote I failed to get value from my audio file... to process it with FFT. What I already tried is --> method asli() I try to connect to the audio using InputStream inputStream =getResources().openRawResource(R.raw.b1); DataInputStream dataInputStream = new DataInputStream(inputStream); then I read the array data with the buffer size, but I seemed that I failed – raisa_ Jul 10 '13 at 08:22
  • 2
    Samples in RIFF/WAV files are typically stored as 16-bit little-endian signed integers, not bytes or doubles. So you may be missing a type conversion. – hotpaw2 Jul 10 '13 at 14:53
  • I think hotpaw is correct. In addition, I don't see any code that parses the wav file format. I could be misreading, but it looks like you just open the file and pass the raw bytes to the fft function. You can read about how to parse wav files or use java to parse them. There's more info here I believe: http://www.jsresources.org/ – Bjorn Roche Jul 10 '13 at 15:24
  • @hotpaw2 Thanks a lot for ur correction.. :) , so now I have to parse it first. I'm really new in this audio processing.. and ur answer was a great help. Thanks – raisa_ Jul 10 '13 at 22:53
  • @BjornRoche Yes.. thanks a lof for page reccomendation.. :) I'm learning to it... – raisa_ Jul 10 '13 at 23:01
  • @hotpaw2 I've edited my code.. I add the conversion method now the result is out, but the return always 0.0 ... any suggestion ?? :( – raisa_ Jul 11 '13 at 12:01
  • @Silviya Hi. I have created a .wav file with 2 alternating frequencies, the ambulance's siren can be one of the examples. Now I need to read that file and fetch the two frequencies and return it in bits format i.e. where there is 1st frequency I get '0' and for the 2nd frequency '1' or vice versa. For example: '11100010', this shows that the 1st frequency was in the 1st three and the 2nd last position. I am really stuck here. I am very new in Java Audios. If you can help me out with this it would be really great. If you want to see my code I can also send you that. Thanks. – Vibhav Chaddha Dec 05 '16 at 06:46

1 Answers1

12

I spent a better part of the morning coding a solution for this using bits and pieces of FFT java snippets I was finding... but then I stumbled upon this amazingly wondeful google code project that has a bunch of util classes for doing signal processing tasks on WAV and MP3 files alike.

https://github.com/Uriopass/audio-analysis Formerly SVN export was on Google code here: https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/audio-analysis/source-archive.zip

It now becomes INSANELY easy:

WaveDecoder decoder = new WaveDecoder(new FileInputStream(wavFile));
FFT fft = new FFT(1024, wavFileObj.getSampleRate());

Now you can use the fft object to do various calculations. They have a bunch of great examples, such as generating a List containing the spectral flux:

    float[] samples = new float[1024];
    float[] spectrum = new float[1024 / 2 + 1];
    float[] lastSpectrum = new float[1024 / 2 + 1];
    List<Float> spectralFlux = new ArrayList<Float>();

    while (decoder.readSamples(samples) > 0) {
        fft.forward(samples);
        System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length);
        System.arraycopy(fft.getSpectrum(), 0, spectrum, 0, spectrum.length);

        float flux = 0;
        for (int i = 0; i < spectrum.length; i++)
            flux += (spectrum[i] - lastSpectrum[i]);
        spectralFlux.add(flux);
    }

My company needed a way for me to analyze some audio to see if some expected hold music had happened. So first I generated a WAV file for an example that did have the hold music. Then I captured some audio of one of thee examples that did not have the hold music. Now all that is left is to average up the spectral flux of the wav and I'm set.

Note: I could not have simply taken amplitudes... but the fourier transformation has frequencies that I could correctly use to make my comparison.

I love math.

Nicholas DiPiazza
  • 10,029
  • 11
  • 83
  • 152