FFT audio input

2019-01-20 17:50发布

问题:

I want to apply FFT on a signal recorded by AudioRecorder and saved to a wav file. the FFT i am using has a Complex[] input parameter. I am confused, is there a difference between converting from bytes to comlex dividing by 32768, and converting by just adding 0 to the imaginary part and leaving the real part as a byte?

Edit:

public Complex[] convertToComplex(byte[] file)
{


    int size= file.length;
    double[]x=new double[size];
    Complex[]data= new Complex[size];
    for(int i=0;i<size;i++)
    {
        x[i]=file[i]/32768.0;
        data[i]=new Complex(x[i],0);
        //  Log.d("tag", "indice"+i+":"+data[i]);
    }
    return data;
}

回答1:

If you are working with audio with a bit depth of 16 bits (each sample has 16 bits), then each byte will only have half of a sample.What you need to do is cast your bytes to 16 bit samples then divide the resulting number by 32768 (This is the magnitude of the smallest number a 2's complement 16 bit number can store i.e 2^15) to get the actual audio sample which is a number between -1 and 1.You will then convert this number to a complex number by setting it's imaginary component to 0.

A small C# sample can be seen below (indicative code):

    byte[] myAudioBytes = readAudio();
    int numBytes = myAudioBytes.Length;

    var myAudioSamples = List<short>();

    for( int i = 0; i < numBytes; i = i + 2)
    {
      //Cast to 16 bit audio and then add sample
       short sample = (short) ((myAudioBytes[i] << 8 | myAudioBytes[i + 1]) / 32768 ); 
       myAudioSamples.Add(sample);
    }

    //Change real audio to Complex audio

    Complex[] complexAudio = new Complex[myAudioSamples.Length];

    int i = 0;
    foreach(short sample in myAudioSamples)
       complexAudio[i++] = new Complex(){ Real = sample, Imaginary = 0 };

   //Now you can proceed to getting the FFT of your Audio here

Hope the code has guided you on how you should handle your audio.



回答2:

Generalized FFT functions like working with arrays of complex inputs and outputs. So, for input, you might need to create an array of complex numbers which conform to the Complex data structure that the FFT library wants. This will probably consist of a real and an imaginary component for each. Just set the imaginary portion to 0. The real portion is probably a signed floating point number that is expected to fall between -1.0..1.0, so you are on the right track with dividing integer PCM samples. However, when you wrote "converting bytes", that raised a red flag. These are probably signed, little endian, 16-bit integer PCM samples, so be sure to cast them accordingly before dividing by 32768 (but this is Java, so types will be enforced a bit more stringently anyway).