Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android getting sound frequencies real time?

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

like image 338
Prerak Diwan Avatar asked Dec 03 '13 01:12

Prerak Diwan


People also ask

Is there an app to measure sound frequencies?

Sound Meter Pro: Sound Meter PRO works with Android phones to measure sound or decibel level. It can also measure sound pressure.

How can I tell what frequency my audio is?

Frequency of any audible sound can be analysed using FFT (Fast Fourier Transform). Best way to analyse Frequency of Audible sound can is by using SLM (Sound Level Meter). This has best Microphone which can pick sound from 20 Hz to 18kHz. Other Microphones dose not have such a good Frequency Response.

What is a frequency analyzer?

An FFT analyzer serves for assessing the physical aspects of sound or vibration phenomena and for devising suitable countermeasures. General applicability is good because analysis can be carried out in the time domain as well as in the frequency domain.

How do you use the spectrum analyzer app?

What you'll need to do is play a pink noise track through your hi-fi system. Then, open the Decibel app and the spectrum analyzer feature. Analyze the sound at the listening position and see if any frequencies stick out above the others. For even better results, play the white noise through one speaker at a time.


1 Answers

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

like image 74
Avanz Avatar answered Sep 27 '22 19:09

Avanz