FFT

2014-01-28 3 views
0

현재 Android 값은 AudioRecord로 수집 된 AudioData에 대해 FFT를 수행하려고 시도한 후에 모두 0입니다. 내 문제는 모든 값은 FFT 후 0입니다. 나는 이유를 모른다.FFT

다음 코드를 FFT (FFT library in android Sdk)로 사용하고 있습니다. 샘플 수는 균일합니다.

private void writeToScreen() 
     { 
      while(isRecording) 
      { 
       double[] y = new double[bufferSize]; 

       for (int i = 0; i < y.length; i++) { 
        y[i]=0; 
       } 

       double[] x = new double[bufferSize]; 
       //short[] to double[] 
       for (int i = 0; i < x.length; i++) 
       { 
        x[i]= audioBuffer[i]/32768; 
       } 

       //perform fft 
       fft meinfft = new fft(bufferSize); 
       meinfft.FFT(x, y); 


         System.out.println("Alle Werte x und y nach FFT:"); 
         for (int i = 0; i < x.length; i++) { //Every Value is 0.0 
          if(x[i] != 0 || y[i] != 0) 
          System.out.println("x["+i+"]: "+ x[i] +" y["+i+"]: "+y[i]); 
         } 
         System.out.println("Ende Aller Werte"); 

       // calculate index of max Value 
       int maxIndex =0; 
       for (int i = 1; i < x.length; i++) { 
        if(Math.sqrt(x[i]*x[i]+y[i]*y[i]) > Math.sqrt(x[maxIndex]*x[maxIndex]+y[maxIndex]*y[maxIndex])) 
        { 
         maxIndex = i; 
        } 
       } 
       System.out.println("Index des Maximums: "+maxIndex); 

       double freq = ((1.0 * sampleRate)/(1.0 * bufferSize)) * maxIndex; //Frequency is always 0 
       System.out.println("wahrscheinliche Frequenz: "+freq); 

       try 
       { 
        Thread.sleep(1000); 
       } 
       catch (InterruptedException e) 
       {} 
      } 
      System.out.println("Writethread beendet"); 
     } 

불행하게도 내가 FFT에 대해 매우 많이 알고 dosn't : (8192)

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; 
       } 
      } 
     } 
    } 
} 

는이 주파수를 계산하는 코드입니다. 나는 짧은 []에서 이중 []으로의 변환이 잘못되었거나 완전한 FFT 자체를 상상할 수 있습니다. 누군가가 나를 도울 수 있기를 바랍니다.

당신은 당신이 찾을 시도 할 경우 아래의 전체 코드 :

import java.io.IOException; 

import android.os.Bundle; 
import android.app.Activity; 
import android.view.Menu; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
//import android.os.Bundle; 
import android.os.Environment; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.content.Context; 
import android.util.Log; 
import android.media.MediaRecorder; 
import android.media.MediaPlayer; 
import de.benediktbock.fft.fft; 
import android.media.AudioFormat; 
import android.media.AudioRecord; 
import android.media.MediaRecorder.AudioSource; 
import java.io.IOException; 


public class MainActivity extends Activity { 
    private static final String LOG_TAG = "FFTTEST"; 
    private PlayButton mPlayButton = null; 
    private TextView realTeil = null; 
    private TextView imgTeil = null; 
    private fft   mFFT = null; 

    private int channel_config = AudioFormat.CHANNEL_IN_MONO; 
    private int format = AudioFormat.ENCODING_PCM_16BIT; 
    private int sampleRate = 8000; 
    private int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format); 
    private AudioRecord audioInput = null; //new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize); 
    private short[] audioBuffer = new short[bufferSize]; 
    private Thread readingThread = null,writingThread=null; 
    private boolean isRecording = false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     LinearLayout ll = new LinearLayout(this); 
     mPlayButton = new PlayButton(this); 

     ll.addView(mPlayButton,new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       0)); 

     realTeil = new TextView(this); 
     ll.addView(realTeil,new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       0)); 

     imgTeil = new TextView(this); 
     ll.addView(imgTeil,new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       0)); 
     setContentView(ll); 

     realTeil.setText("Realteil"); 
     imgTeil.setText("Imaginärteil"); 


    } 

    @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; 
    } 

    class PlayButton extends Button { 
     boolean mStartPlaying = true; 

     OnClickListener clicker = new OnClickListener() { 
      public void onClick(View v) { 
       onPlay(mStartPlaying); 
       if (mStartPlaying) { 
        setText("Stop"); 
       } else { 
        setText("Start"); 
       } 
       mStartPlaying = !mStartPlaying; 
      } 
     }; 

     public PlayButton(Context ctx) { 
      super(ctx); 
      setText("Start"); 
      setOnClickListener(clicker); 
     } 
    } 

    private void onPlay(boolean start) { 
     if (start) { 
      startRecording(); 
     } else { 
      stopRecording(); 
     } 

    } 

    private void startRecording() 
    { 
     audioInput = new AudioRecord(AudioSource.MIC, sampleRate, channel_config, format, bufferSize); 


     audioInput.startRecording(); 
     isRecording = true; 
     readingThread = new Thread(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        readAudioToBuffer(); 
       } 
      },"readAudio Thread"); 

     readingThread.start(); 

     writingThread = new Thread(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       writeToScreen(); 
      } 
     },"write Thread"); 

     writingThread.start(); 
    } 
    private void writeToScreen() 
    { 
     while(isRecording) 
     { 
      double[] y = new double[bufferSize]; 

      for (int i = 0; i < y.length; i++) { 
       y[i]=0; 
      } 

      double[] x = new double[bufferSize]; 
      //short[] to double[] 
      for (int i = 0; i < x.length; i++) 
      { 
       x[i]= audioBuffer[i]/32768; 
      } 

      //perform fft 
      fft meinfft = new fft(bufferSize); 
      meinfft.FFT(x, y); 


        System.out.println("Alle Werte x und y nach FFT:"); 
        for (int i = 0; i < x.length; i++) { //Every Value is 0.0 
         if(x[i] != 0 || y[i] != 0) 
         System.out.println("x["+i+"]: "+ x[i] +" y["+i+"]: "+y[i]); 
        } 
        System.out.println("Ende Aller Werte"); 

      // calculate index of max Value 
      int maxIndex =0; 
      for (int i = 1; i < x.length; i++) { 
       if(Math.sqrt(x[i]*x[i]+y[i]*y[i]) > Math.sqrt(x[maxIndex]*x[maxIndex]+y[maxIndex]*y[maxIndex])) 
       { 
        maxIndex = i; 
       } 
      } 
      System.out.println("Index des Maximums: "+maxIndex); 

      double freq = ((1.0 * sampleRate)/(1.0 * bufferSize)) * maxIndex; //Frequency is always 0 
      System.out.println("wahrscheinliche Frequenz: "+freq); 

      try 
      { 
       Thread.sleep(1000); 
      } 
      catch (InterruptedException e) 
      {} 
     } 
     System.out.println("Writethread beendet"); 
    } 

    private void readAudioToBuffer() 
    { 
     while(isRecording) 
     { 
      audioInput.read(audioBuffer, 0,bufferSize); 
     } 

     System.out.println("Thread wurde beendet"); 

    } 

    private void stopRecording() 
    { 
     isRecording = false; 
     audioInput.stop(); 
     audioInput.release(); 
     audioInput= null; 
     readingThread = null; 
    } 
} 

답변

1

귀하의 입력은 COS 죄 배열의 모든 0

short s = 32767; 
double d = s/32768; 
System.out.println("dividing a short yields a truncated result " + d); 
d = (double) s/32768; 
System.out.println("casting to a double and then dividing yields " + d); 
+0

그리고 아마도 트위 요인이 있습니다 또한 정의에서 정수 나누기 i/n 때문에 잘못되었습니다. pi/n * i로 더 잘 재정렬하십시오. – LutzL

+0

질문에 대해서는 직접적인 내용이 아니지만 ((1.0 * sampleRate)/(1.0 * bufferSize)) * maxIndex가 맞습니까? 순간에 나는 +/- 5Hz에 대해 tollerance 있습니다. 아니면 마이크입니까? –