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

Original source

Related problems