2011-04-25 7 views
38

현재 안드로이드를 사용하여 전화의 마이크를 통해 특정 오디오 주파수 범위를 재생할 때 감지 할 수있는 코드를 구현하려고합니다.audiorecord를 사용하여 특정 주파수 크기를 검색하는 Android 오디오 FFT

int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
int format = AudioFormat.ENCODING_PCM_16BIT; 
int sampleSize = 8000; 
int bufferSize = AudioRecord.getMinBufferSize(sampleSize, channel_config, format); 
AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize); 

오디오 다음에 읽기 : FFT를 수행

short[] audioBuffer = new short[bufferSize]; 
audioInput.startRecording(); 
audioInput.read(audioBuffer, 0, bufferSize); 

나는이 지역에있는 약간의 경험을 가지고 내가 붙어 될 곳이다 나는 AudioRecord 클래스를 사용하여 클래스를 설정 한 . 나는이 클래스를 사용하는 것을 시도하고있다 :

FFT in JavaComplex class to go with it

내가 다음 값을 보낸다 :이 쉽게 날이 클래스가 작동하기위한 것입니다 방법 오해 될 수

Complex[] fftTempArray = new Complex[bufferSize]; 
for (int i=0; i<bufferSize; i++) 
{ 
    fftTempArray[i] = new Complex(audio[i], 0); 
} 
Complex[] fftArray = fft(fftTempArray); 

을하지만, 반환 된 값은 모든 곳에서 점프하며 침묵 속에서도 일관된 빈도를 나타내지 않습니다. 누구나이 작업을 수행 할 수있는 방법을 알고 있습니까? 아니면 그래픽 표현으로 그려야하는 대신 작은 수의 주파수 범위 만 잡으려고 문제를 복잡하게 만듭니다.

+10

이봐, 당신은 코드의 최종 버전을 게시하시기 바랍니다 수 있을까? thx –

답변

33

먼저 결과가 올바르게 float/double로 변환되었는지 확인해야합니다. 나는 짧은 [] 버전이 어떻게 작동하는지 모르겠다.하지만 byte [] 버전은 원시 바이트 버전 만 리턴한다. 이 바이트 배열을 올바르게 부동 소수점 숫자로 변환해야합니다. 변환 코드는 다음과 같아야합니다.

double[] micBufferData = new double[<insert-proper-size>]; 
    final int bytesPerSample = 2; // As it is 16bit PCM 
    final double amplification = 100.0; // choose a number as you like 
    for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) { 
     double sample = 0; 
     for (int b = 0; b < bytesPerSample; b++) { 
      int v = bufferData[index + b]; 
      if (b < bytesPerSample - 1 || bytesPerSample == 1) { 
       v &= 0xFF; 
      } 
      sample += v << (b * 8); 
     } 
     double sample32 = amplification * (sample/32768.0); 
     micBufferData[floatIndex] = sample32; 
    } 

그런 다음 micBufferData []를 사용하여 입력 복합 배열을 만듭니다.

결과를 얻은 후에는 결과에 복소수의 크기를 사용하십시오. 대부분의 크기는 실제 값을 갖는 주파수를 제외하고는 0에 가깝습니다.

당신은 주파수에 같은 크기로 배열 인덱스를 변환하는 샘플링 주파수가 필요합니다 : 당신이 그것을 알아 낸 경우

private double ComputeFrequency(int arrayIndex) { 
    return ((1.0 * sampleRate)/(1.0 * fftOutWindowSize)) * arrayIndex; 
} 
+2

답장을 보내 주셔서 감사합니다.하지만 몇 가지 문제점이 있습니다. 'ComputeFrequency'메소드를 실행하기 전에 반환 된 복합 배열에서 값을 추출 할 수 있습니까? 같은 문제는 여전히 산발적 인 숫자가 10에서 약 3000까지 나타나는 것을 허용하는 것 같습니다. 불행히도 방이 침묵 상태에 있습니다. – user723060

+0

예, 여전히 복잡한 배열에서 값을 추출 할 수 있어야합니다. 복소수 (예 : sqrt (re * re + im * im)). 방이 완전히 조용하더라도 FFT에 표시되는 마이크에서 배경 잡음이 들릴 수 있습니다. 배열 인덱스를 주파수로 변환하여 나타나는 정확한 주파수가 무엇인지 확인하십시오. 이러한 주파수 값은 배경 잡음인지 아닌지를 이해하는 데 도움이 될 수 있습니다. – shams

+0

만약 허수에 관해서 복잡한 배열을 올바르게 호출하고 싶다면 궁금합니다. 지금 구현 한 방법은 원래 예제에서 사용한 방법과 매우 비슷하지만 새로운 micBufferData 배열을 순환하면서 각 값을 허수로 항상 실수로 복잡한 배열에 할당합니다. 이것은 내가 잘못 가고있는 곳일 수도 있지만 이전에 읽은 예는 이것이 올바른 방법임을 나타내는 것 같습니다. 거기에 갈 의도가있는 다른 아이디어가 있으면 어떤 아이디어가 있습니까? 다시 한 번 감사드립니다! – user723060