0

I am trying to get FFT results of a pre-recorded sound which is saved as a .wav file.

For my FFT I used FFT and Complex class that was published here (FFT) and here (Complex).

This is the code that I have right now and when I checked the output file, I have almost similar values for each sound recordings. Why is that?

                    double [] fftdata;
                    File file;
                    file = new File(AudioSavePathInDevice);
                    File file2;
                    file2 = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + number + "FFTvalues.txt");
                    byte[] soundBytes;
                    try {
                        InputStream inputStream = getContentResolver().openInputStream(Uri.fromFile(file));
                        soundBytes = toByteArray(inputStream);
                        fftdata = calculateFFT(soundBytes); <-- this is where I call my calculate FFT method
                        String sfftdata = Arrays.toString(fftdata);
                        FileOutputStream fos = new FileOutputStream(file2);
                        DataOutputStream dos = new DataOutputStream(fos);
                        dos.writeUTF(sfftdata);
                        dos.close();
                        inputStream.close();

                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                   }
                    catch(Exception e){
                        e.printStackTrace();
                    }

This part of my code calls the file saved at "AudioSavePathInDevice", convert it into Byte Array with "toByteArray" method, and then calculate FFT with "calculateFFT" method. These methods are as follows.

Method to convert .wav file data to byte array.

    public byte[] toByteArray(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int read = 0;
        byte[] buffer1 = new byte [1024];
        while (read != -1) {
            read = in.read(buffer1,0,buffer1.length);
            if (read != -1)
                out.write(buffer1,0,read);
        }
        out.flush();
        return out.toByteArray();
    }

Method to calculate FFT.

public double[] calculateFFT(byte[] signal)
    {
        final int mNumberOfFFTPoints = 4096;
        double mMaxFFTSample;
        double mPeakPos;

        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;

    }
  • The question is: What do you want to achieve? Doing FFT is pretty much nonsense for real-time applications. Secondly it is called DFT because you do not have a continuous signal when recording. What you will want is an FIR bandpass filter for each frequency ... Nevertheless cool that you tried, reminds me of my approach 20 years ago. – michaeak Mar 02 '20 at 16:02
  • Well, my project involves recognizing and matching sound profiles for a device made for deaf people. I need this FFT to calculate the euclidean distances of peaks to match the sound profiles. Do you mind taking a look at my code? – totalbeginner Mar 02 '20 at 16:07
  • To test your application just generate several sine waves and check that the result is what you want to see. – michaeak Mar 02 '20 at 16:10
  • I already tested my audio signals on Matlab and I'm not getting the desired output from my app. Hence, asking here for some advice. – totalbeginner Mar 02 '20 at 16:12
  • For simple peaks no DFT is needed. There are simpler approaches. To me it looks like you are just reading the bytes of a file, but a wave file can have several ways it looks like and you need to process header info etc. https://en.wikipedia.org/wiki/WAV – michaeak Mar 02 '20 at 16:17

1 Answers1

0

For me it looks like you are not interpreting the .wav file properly. A wave file can have several ways how the information is stored (see https://en.wikipedia.org/wiki/WAV) There are different encodings and the header information is not audio, it is meta information like bitrate etc. This must not be interpreted as audio signal. Just take a look at the file with a hex editor.

Secondly you cannot assume that two bytes represent your audio input, it could be 1 byte or also 4 bits and not even be pure integer using some encoding or even stored in chunks (meaning there is some length info and maybe other description followed by audio signal) or all combined. To know how many bytes and what it is like you have to interprete the header information.

Maybe you read Reading wav file in Java for more info.

michaeak
  • 1,548
  • 1
  • 12
  • 23