2012-02-17 161 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)。你可以找到这个数组的大小的最大值来估计幅度最大的近似频率。你也可以内插最大值来改善这个频率估计值。

但是,如果您正在寻找音高估计值(例如吉他音符),那可能与峰值频率估计值有很大差异。也许你可能想研究一些音调估计算法。