android getting sound frequencies real time?

后端 未结 3 450
不思量自难忘°
不思量自难忘° 2020-12-24 08:06

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.recordsou         


        
相关标签:
3条回答
  • 2020-12-24 08:25

    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

    0 讨论(0)
  • 2020-12-24 08:31

    Did you solved the problem? The crush is occurred because of the ArrayIndexOutOfBoundsException.

    So, modify your code to :

                    double[] re = new double[blockSize];
                    double[] im = new double[blockSize];
                    double[] magnitude = new double[blockSize];
    
                    // Calculate the Real and imaginary and Magnitude.
                    for(int i = 0; i < blockSize+1; i++){
                        try {
                            // 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]));
                        }catch (ArrayIndexOutOfBoundsException e){
                            Log.e("test", "NULL");
                        }
                    }
    
                    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 = Double.toString((sampleRate * peak)/blockSize);
    
    0 讨论(0)
  • 2020-12-24 08:33

    If you really want to perform a real-time audio analysis, a Java-based approach won't do. I had a similar task in Q4 2013 for my company, and we decided to use Kiss FFT (perhaps the most simple FFT library with a BSD license), compiled for Android using the NDK.

    A native C/C++ approach is tons of times faster than its Java counterpart. With the former, we have been able to perform real-time audio decoding and audio features analysis on nearly every mid to high end device, something that was obviously impossible with the latter.

    I strongly suggest you to consider the native approach as your best option to do this task. Kiss FFT is a really simple library (literally stands for Keep It Simple FFT), and you won't find much troubles in compiling and using it on Android. You won't be disappointed by the performance results.

    0 讨论(0)
提交回复
热议问题