I have a sound file (.3gp) and its about ~1 min. I would like to get the frequency of this sound file in every 1/4 seconds. My idea is to receive samples in every 1/4 seconds from the audio file and using FFT I might get the frequency values. Is there any way to do this?
Actually I would split the sound file into 1/4sec samples sound files (alwyas overwriting the preveious one), then using FFT algorithm and detect the frequency where the magintude is the bigggest. But there might be easier solutions however I dont have a clue how to do this either.
***UPDATE 2 - new code
I use this code so far:
public class RecordAudio extends AsyncTask<Void, double[], Void> {
@Override
protected Void doInBackground(Void... arg0) {
try {
int bufferSize = AudioRecord.getMinBufferSize(frequency,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
//int bufferSize = AudioRecord.getMinBufferSize(frequency,
// channelConfiguration, audioEncoding);
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, frequency,
channelConfiguration, audioEncoding, bufferSize);
short[] buffer = new short[blockSize];
//double[] toTransform = new double[blockSize];
audioRecord.startRecording();
// started = true; hopes this should true before calling
// following while loop
while (started) {
sampling++;
double[] re = new double[blockSize];
double[] im = new double[blockSize];
double[] newArray = new double[blockSize*2];
double[] magns = new double[blockSize];
double MaxMagn=0;
double pitch = 0;
int bufferReadResult = audioRecord.read(buffer, 0,
blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
re[i] = (double) buffer[i] / 32768.0; // signed 16bit
im[i] = 0;
}
newArray = FFTbase.fft(re, im,true);
for (int i = 0; i < newArray.length; i+=2) {
re[i/2]=newArray[i];
im[i/2]=newArray[i+1];
magns[i/2] = Math.sqrt(re[i/2]*re[i/2]+im[i/2]*im[i/2]);
}
// I only need the first half
for (int i = 0; i < (magns.length)/2; i++) {
if (magns[i]>MaxMagn)
{
MaxMagn = magns[i];
pitch=i;
}
}
if (sampling > 50) {
Log.i("pitch and magnitude", "" + MaxMagn + " " + pitch*15.625f);
sampling=0;
MaxMagn=0;pitch=0;
}
}
audioRecord.stop();
} catch (Throwable t) {
t.printStackTrace();
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
I use this: http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29
Guitar strings seem correct, but my own sound is not good because of this:
The magnitude of the two peaks change most of the time and I always find the biggest to get the fundamental frequency.
Pitch tracking with the FFT is asked so often on Stack Overflow I wrote a blog entry with sample code. The code is in C, but with the explanation and links you should be able to do what you want.
As to dividing it up into 1/4 second increments, you could simply take FFTs of 1/4 second segments as you suggested, instead of the default (which I think is about 1 second). If this doesn't give you the frequency resolution you want, you may have to use a different pitch recognition method. Another thing you could do is use overlapping segments that are longer than 1/4 second, but start at intervals that are 1/4 second apart. This method is alluded to the blog entry, but it may not meet your design spec.
Try AsyncTask:
Call this in your MainActivity by,