2012-02-17 158 views
3

以下代碼僅顯示一個圖形,但我想要聲音的頻率。我試圖錄制聲音並獲得實時頻率,以便我可以彈奏鋼琴或吉他聲音並找到頻率。使用Android FFT獲取聲音頻率

public class AudioProcessing extends Activity implements OnClickListener { 

int frequency = 8000; 
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 

private RealDoubleFFT transformer; 
int blockSize = 256; 

Button startStopButton; 
boolean started = false; 

RecordAudio recordTask; 

ImageView imageView; 
Bitmap bitmap; 
Canvas canvas; 
Paint paint; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    startStopButton = (Button) this.findViewById(R.id.StartStopButton); 
    startStopButton.setOnClickListener(this); 

    transformer = new RealDoubleFFT(blockSize); 

    imageView = (ImageView) this.findViewById(R.id.ImageView01); 
    bitmap = Bitmap.createBitmap((int) 256, (int) 100, 
      Bitmap.Config.ARGB_8888); 
    canvas = new Canvas(bitmap); 
    paint = new Paint(); 
    paint.setColor(Color.GREEN); 
    imageView.setImageBitmap(bitmap); 
} 



private class RecordAudio extends AsyncTask<Void, double[], Void> { 
    @Override 
    protected Void doInBackground(Void... params) { 
     try { 
      int bufferSize = AudioRecord.getMinBufferSize(frequency, 
        channelConfiguration, audioEncoding); 

      AudioRecord audioRecord = new AudioRecord(
        MediaRecorder.AudioSource.MIC, frequency, 
        channelConfiguration, audioEncoding, bufferSize); 

      short[] buffer = new short[blockSize]; 
      double[] toTransform = new double[blockSize]; 

      audioRecord.startRecording(); 

      while (started) { 
       int bufferReadResult = audioRecord.read(buffer, 0, 
         blockSize); 

       for (int i = 0; i < blockSize && i < bufferReadResult; i++) { 
        toTransform[i] = (double) buffer[i]/32768.0; // signed 
        // 16 
        // bit 
       } 

       transformer.ft(toTransform); 

       publishProgress(toTransform); 
      } 

      audioRecord.stop(); 
     } catch (Throwable t) { 
      Log.e("AudioRecord", "Recording Failed"); 
     } 

     return null; 
    } 

    protected void onProgressUpdate(double[]... toTransform) { 
     canvas.drawColor(Color.BLACK); 

     for (int i = 0; i < toTransform[0].length; i++) { 
      int x = i; 
      int downy = (int) (100 - (toTransform[0][i] * 10)); 
      int upy = 100; 

      canvas.drawLine(x, downy, x, upy, paint); 
     } 
     imageView.invalidate(); 
    } 
} 

public void onClick(View v) { 
    if (started) { 
     started = false; 
     startStopButton.setText("Start"); 
     recordTask.cancel(true); 
    } else { 
     started = true; 
     startStopButton.setText("Stop"); 
     recordTask = new RecordAudio(); 
     recordTask.execute(); 
    } 
} 
    } 

如何從此代碼獲取頻率?

回答

3

你的FFT代碼不給你的頻率。它爲您提供了一系列不同頻率的複數值。並有可能在你的代碼中的錯誤,如果你只是在看「真實」或餘弦的FFT結果的組件,而不是每一個成分複雜的矢量幅度。

FFT後的toTransform [i]數組的每個元素爲您提供了一個複數值(i * sampleRate/blockSize)。你可以找到這個數組的大小的最大值來估計幅度最大的近似頻率。你也可以內插最大值來改善這個頻率估計值。

但是,如果您正在尋找音高估計值(例如吉他音符),那可能與峯值頻率估計值有很大差異。也許你可能想研究一些音調估計算法。