2016-05-01 13 views
3

私は、特定の周波数(1000Hz〜1500Hz)のホイッスルを検出することができるアプリケーションを実装しようとしています。環境的な背景雑音があっても、マイクから取り込まれた最大振幅がホイッスルの周波数に対応しているかどうかを調べるためにFFTメソッドを試してみました。Androidのホイッスル検出とマイク

public void run() { 
    if (ar == null) { 
     bufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); 
     ar = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,bufferSize); 
     audioBuffer = new short[bufferSize]; 
     ar.startRecording(); 
     ar.read(audioBuffer, 0, bufferSize); 

     //Conversion from short to double 
     double[] micBufferData = new double[bufferSize];//size may need to change 
     final int bytesPerSample = 2; // As it is 16bit PCM 
     final double amplification = 1.0; // choose a number as you like 
     for (int index = 0, floatIndex = 0; index < (byte) bufferSize - bytesPerSample + 1; index += bytesPerSample, floatIndex++) { 
      double sample = 0; 
      for (int b = 0; b < bytesPerSample; b++) { 
       int v = audioBuffer[index + b]; 
       if (b < bytesPerSample - 1 || bytesPerSample == 1) { 
        v &= 0xFF; 
       } 
       sample += v << (b * 8); 
      } 
      double sample32 = amplification * (sample/32768.0); 
      micBufferData[floatIndex] = sample32; 
     } 

     //Create Complex array for use in FFT 
     Complex[] fftTempArray = new Complex[bufferSize]; 
     for (int i=0; i< (byte) bufferSize; i++) 
     { 
      fftTempArray[i] = new Complex(micBufferData[i], 0); 
     } 

     //Obtain array of FFT data 
     final Complex[] fftArray = FFT.fft(fftTempArray); 
     //final Complex[] fftInverse = FFT.ifft(fftTempArray); 

     //Create an array of magnitude of fftArray 
     double[] magnitude = new double[fftArray.length]; 
     for (int i=0; i<fftArray.length; i++){ 
      magnitude[i]= fftArray[i].abs(); 
     } 


     double maxVal = -1.0; 
     int maxIndex = 1; 
     for(int j=0; j < fftArray.length/2; ++j) { 
      double v = magnitude[2*j] * magnitude[2*j] + magnitude[2*j+1] * magnitude[2*j+1]; 
      if(v > maxVal) { 
       maxVal = v; 
       maxIndex = j; 
      } 
     } 

     maxFrequency = ((1.0 * 44100)/(1.0 * bufferSize)) * maxIndex; 

    } 
    runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      if (isRunning) { 
       tv2.setText("Frequency Detected: " + maxFrequency); 
      } 
     } 
    }); 

} 

私はすでになどマイク録音を設定しているが、私はコードがやっていると私は私のfftarrayが負であることを言っていくつかのエラーを取得していますかを理解することはできません。誰かが私が正しい方向を指すのを助けることができますか?またはホイッスル検出を実装するためのより良い方法はありますか?私はhereのコードを使用しています。私は2つの例外がスローされるのではなく、Nを得ています。

+0

コードが何をしているのか分かりませんが、どういう意味ですか?あなたのものではありませんか? – stackoverflowuser2010

+0

特定の周波数がサウンドに含まれているかどうかを確認する場合は、FFTを使用するのが適切です。あなたの質問は何ですか? – stackoverflowuser2010

+0

コードを実行しようとするとエラーが発生します。私はjava.lang.RuntimeExceptionを取得します:Nは2の累乗ではありません最終複合体[] fftArray = FFT.fft(fftTempArray); –

答えて

0

次の行が確実に動作しません:

for (int i=0; i< (byte) bufferSize; i++) 

bufferSizeはバイトよりもはるかに大きくすることができ、あなたのループが一回実行されないように、キャストは、その後も、負の数を生成することができます。 fftTempArrayは初期化されません。

(byte)を削除すると、このエラーが修正されます。

しかし、少なくとも2番目のエラーがあります。「短文から短文への変換」が間違っています。 2つの連続する16ビット・サンプルをmicBufferDataの1つのダブル・サンプルに結合し、各16ビット・サンプルはそれ自身の2倍のサンプルに対応する必要があります。

EDITはコメントショーから

エラー、あなたの配列は、さらに2^Nの大きさを持っている必要があること。だから、bufferSizeより次に小さい2^Nサイズを見つけてください。

+0

これはなぜ発生するのか分かりませんか?私は印刷文から、N = 5の時にエラーが出るのを見ることができます。私はその開始インデックスが640であると信じています。 –

+0

私のbufferSize = 640はインデックス2ではありません。興味深いのは –

+0

ですから、次の下位2^N番号は512(= 2^9)です。 –