android getting sound frequencies real time?
android, audio, frequency, java, real-time
Solution
Try this FFT:
public class FFT {
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
public FFT(int n) {
this.n = n;
this.m = (int) (Math.log(n) / Math.log(2));
// Make sure n is a power of 2
if (n != (1 << m))
throw new RuntimeException("FFT length must be power of 2");
// precompute tables
cos = new double[n / 2];
sin = new double[n / 2];
for (int i = 0; i < n / 2; i++) {
cos[i] = Math.cos(-2 * Math.PI * i / n);
sin[i] = Math.sin(-2 * Math.PI * i / n);
}
}
public void fft(double[] x, double[] y) {
int i, j, k, n1, n2, a;
double c, s, t1, t2;
// Bit-reverse
j = 0;
n2 = n / 2;
for (i = 1; i < n - 1; i++) {
n1 = n2;
while (j >= n1) {
j = j - n1;
n1 = n1 / 2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i = 0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j = 0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m - i - 1);
for (k = j; k < n; k = k + n2) {
t1 = c * x[k + n1] - s * y[k + n1];
t2 = s * x[k + n1] + c * y[k + n1];
x[k + n1] = x[k] - t1;
y[k + n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
}
}
It should address what you have in mind. If you decided to re-use it, give the proper credit to the author.
Source/Author: EricLarch
Problem
I have been trying to get the sound frequency(number) in real time using fft and i am having run time errors. can any one help? ``` package com.example.recordsound; import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; import ca.uol.aig.fftpack.RealDoubleFFT; public class MainActivity extends Activity implements OnClickListener{ int audioSource = MediaRecorder.AudioSource.MIC; // Audio source is the device MIC int channelConfig = AudioFormat.CHANNEL_IN_MONO; // Recording in mono int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; // Records in 16bit private DoubleFFT_1D fft; // The fft double array private RealDoubleFFT transformer; int blockSize = 256; // deal with this many samples at a time int sampleRate = 8000; // Sample rate in Hz public double frequency = 0.0; // the frequency given RecordAudio recordTask; // Creates a Record Audio command TextView tv; // Creates a text view for the frequency boolean started = false; Button startStopButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.textView1); startStopButton= (Button)findViewById(R.id.button1); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private class RecordAudio extends AsyncTask<Void, Double, Void>{ @Override protected Void doInBackground(Void... params){ /*Calculates the fft and frequency of the input*/ //try{ int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); // Gets the minimum buffer needed AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording short[] buffer = new short[blockSize]; // Save the raw PCM samples as short bytes // double[] audioDataDoubles = new double[(blockSize*2)]; // Same values as above, as doubles // ----------------------------------------------- double[] re = new double[blockSize]; double[] im = new double[blockSize]; double[] magnitude = new double[blockSize]; // ---------------------------------------------------- double[] toTransform = new double[blockSize]; tv.setText("Hello"); // fft = new DoubleFFT_1D(blockSize); try{ audioRecord.startRecording(); //Start }catch(Throwable t){ Log.e("AudioRecord", "Recording Failed"); } while(started){ /* Reads the data from the microphone. it takes in data * to the size of the window "blockSize". The data is then * given in to audioRecord. The int returned is the number * of bytes that were read*/ int bufferReadResult = audioRecord.read(buffer, 0, blockSize); // Read in the data from the mic to the array for(int i = 0; i < blockSize && i < bufferReadResult; i++) { /* dividing the short by 32768.0 gives us the * result in a range -1.0 to 1.0. * Data for the compextForward is given back * as two numbers in sequence. Therefore audioDataDoubles * needs to be twice as large*/ // audioDataDoubles[2*i] = (double) buffer[i]/32768.0; // signed 16 bit //audioDataDoubles[(2*i)+1] = 0.0; toTransform[i] = (double) buffer[i] / 32768.0; // signed 16 bit } //audiodataDoubles now holds data to work with // fft.complexForward(audioDataDoubles); transformer.ft(toTransform); //------------------------------------------------------------------------------------------ // Calculate the Real and imaginary and Magnitude. for(int i = 0; i < blockSize; i++){ // real is stored in first part of array re[i] = toTransform[i*2]; // imaginary is stored in the sequential part im[i] = toTransform[(i*2)+1]; // magnitude is calculated by the square root of (imaginary^2 + real^2) magnitude[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i])); } double peak = -1.0; // Get the largest magnitude peak for(int i = 0; i < blockSize; i++){ if(peak < magnitude[i]) peak = magnitude[i]; } // calculated the frequency frequency = (sampleRate * peak)/blockSize; //---------------------------------------------------------------------------------------------- /* calls onProgressUpdate * publishes the frequency */ publishProgress(frequency); try{ audioRecord.stop(); } catch(IllegalStateException e){ Log.e("Stop failed", e.toString()); } } // } return null; } protected void onProgressUpdate(Double... frequencies){ //print the frequency String info = Double.toString(frequencies[0]); tv.setText(info); } } @Override public void onClick(View v) { // TODO Auto-generated method stub if(started){ started = false; startStopButton.setText("Start"); recordTask.cancel(true); } else { started = true; startStopButton.setText("Stop"); recordTask = new RecordAudio(); recordTask.execute(); } } } ``` AS SOON AS I run the program with the OnClick it crashes I tried two libraries for fft but ran one at a time to see if the library works or not As soon as it reaches the line where I assign the the block size to the FFT object it crashes can any one help