I have been working on an Android project for some time that displays the main frequency of the input signal (to act as a tuner). I have successfully implemented the AudioRecord class and get data from it. However, I hardly perform FFT on this data to get the main frequency of the input signal. I watched the post here , and use FFT in Java and the Complex class to go with it.
I have successfully used the FFT function found in FFT in Java, but I'm not sure that I am getting the correct results. For the FFT value (sqrt [rere + imim]), I get values ββthat start high, about 15000 Hz, and then slowly decrease to about 300 Hz. Doesn't seem right.
In addition, with regard to the raw microphone data, the data seems accurate, except that the first 50 values ββor so are always number 3, unless I hit the setup button again while still in the application, and then I only get about 15. Is this normal?
Here is some of my code.
First of all, I convert the short data (received from the microphone) into double using the following code, which is from the message that I was considering . I donβt quite understand this piece of code, but I think it works.
//Conversion from short to double double[] micBufferData = new double[bufferSizeInBytes];//size may need to change final int bytesPerSample = 2; // As it is 16bit PCM final double amplification = 1.0; // choose a number as you like for (int index = 0, floatIndex = 0; index < bufferSizeInBytes - bytesPerSample + 1; index += bytesPerSample, floatIndex++) { double sample = 0; for (int b = 0; b < bytesPerSample; b++) { int v = audioData[index + b]; if (b < bytesPerSample - 1 || bytesPerSample == 1) { v &= 0xFF; } sample += v << (b * 8); } double sample32 = amplification * (sample / 32768.0); micBufferData[floatIndex] = sample32; }
Then the code continues as follows:
//Create Complex array for use in FFT Complex[] fftTempArray = new Complex[bufferSizeInBytes]; for (int i=0; i<bufferSizeInBytes; i++) { fftTempArray[i] = new Complex(micBufferData[i], 0); } //Obtain array of FFT data final Complex[] fftArray = FFT.fft(fftTempArray); final Complex[] fftInverse = FFT.ifft(fftTempArray); //Create an array of magnitude of fftArray double[] magnitude = new double[fftArray.length]; for (int i=0; i<fftArray.length; i++){ magnitude[i]= fftArray[i].abs(); } fft.setTextColor(Color.GREEN); fft.setText("fftArray is "+ fftArray[500] +" and fftTempArray is "+fftTempArray[500] + " and fftInverse is "+fftInverse[500]+" and audioData is "+audioData[500]+ " and magnitude is "+ magnitude[1] + ", "+magnitude[500]+", "+magnitude[1000]+" Good job!"); for(int i = 2; i < samples; i++){ fft.append(" " + magnitude[i] + " Hz"); }
This last bit is just to check what values ββI get (and keep me sane!). The above article talks about the need for a sampling rate and gives this code:
private double ComputeFrequency(int arrayIndex) { return ((1.0 * sampleRate) / (1.0 * fftOutWindowSize)) * arrayIndex; }
How to implement this code? I do not understand where fftOutWindowSize and arrayIndex come from?
Any help is much appreciated!
Dustin