2014-10-31 3 views
3

18KHz에서 19KHz 사이의 주파수를 가진 초음파를 모든 안드로이드 장치에서 얻고 싶습니다.주파수를 사용하여 안드로이드에서 초음파를 받으십시오.

주파수를 계산하기 위해 아래 코드를 사용하지만 정확한 주파수를 얻지 못하는 것 같습니다. 주파수는 11KHz와 13KHz 사이에 머물러 있습니다. 하나 개 this app로 보내기 초음파이 초음파를 얻기 위해 다른 하나를

private void  calculateFrequency() 
{ 
    // 1 - Initialize audio 
    int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
    int format = AudioFormat.ENCODING_PCM_16BIT; 
    int sampleRate = 8000; 
    int bufferSize = 2048; 

    if (bufferSize < AudioRecord.getMinBufferSize(sampleRate, channel_config, format)) 
     bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format); 
    AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleRate, channel_config, format, bufferSize); 

    // 2 - Get sound 
    byte[] audioBuffer = new byte[bufferSize]; 
    audioInput.startRecording(); 
    int nbRead = audioInput.read(audioBuffer, 0, bufferSize); 
    audioInput.stop(); 
    audioInput.release(); 

    // 3 - Transform to double array 
    double[] micBufferData = new double[bufferSize]; 
    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 < nbRead - 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; 
    } 

    // 4 - Create complex array 
    Complex[] fftTempArray = new Complex[bufferSize]; 
    for (int i=0; i<bufferSize; i++) 
    { 
     fftTempArray[i] = new Complex(micBufferData[i], 0); 
    } 

    // 5 - Calculate FFT 
    Complex[] fftArray = FFT.fft(fftTempArray); 

    // 6 - Calculate magnitude 
    double[] magnitude = new double[bufferSize/2]; 
    for (int i = 0; i < (bufferSize/2); i++) 
    { 
     magnitude[i] = Math.sqrt(fftArray[i*2].re() * fftArray[i*2].re() + fftArray[i*2].im() * fftArray[i*2].im()); 
    } 

    // 7 - Get maximum magnitude 
    double max_magnitude = -1; 
    for (int i = 0; i < bufferSize/2; i++) 
    { 
     if (magnitude[i] > max_magnitude) 
     { 
      max_magnitude = magnitude[i]; 
     } 
    } 

    // 8 - Calculate frequency 
    int freq = (int)(max_magnitude * sampleRate/bufferSize); 

    ((TextView) findViewById(R.id.textView1)).setText("FREQUENCY = " + freq + "Hz"); 
} 

나는 두 개의 휴대 전화를 사용하고 있습니다. question을 시작 지점으로 사용했습니다. FFT복합체 클래스입니다.

내 코드에 어떤 문제가 있습니까?

+0

좋은 아이디어. 설명해 주시겠습니까 :'int freq = (int) (max_magnitude * sampleRate/bufferSize);'. – FelixMarcus

+0

나는이 대답을 사용했다. (http://stackoverflow.com/a/7675171/1770833) 코드의 마지막 줄을 보자. – Drakkin

+0

실수는 7 단계와 8 단계에있다. 최대 크기의 * index *가 필요하다. 강도 자체가 아닌 주파수를 결정합니다. 링크 된 답변의 의사 코드를 좀 더주의 깊게보십시오. –

답변

4

정확한 앨리어싱 제거되지 않은 주파수 추정치를 얻으려면 오디오 입력에서 가장 높은 주파수의 두 배보다 더 많은 샘플링 속도 (필터 롤오프를 피하기 위해 10 % ~ 20 % 더 커야 함)를 사용해야하므로 찾으려는 가장 높은 빈도의 두 배 이상입니다.

이는 샘플링 이론의 필요한 나이키 스트 비율 때문입니다.

19 kHz 신호를 찾으려면 48000에 가까운 샘플링 속도가 필요합니다.

3

7 단계와 8 단계는 맞지 않아요 - 당신이 주파수를 결정하기 위해 가장 큰 크기로 FFT 빈의 인덱스를 사용해야합니다 :

// 7 - Get maximum magnitude 
    double max_magnitude = -1; 
    int max_magnitude_index = -1; 
    for (int i = 0; i < bufferSize/2; i++) 
    { 
     if (magnitude[i] > max_magnitude) 
     { 
      max_magnitude = magnitude[i]; 
      max_magnitude_index = i; 
     } 
    } 

    // 8 - Calculate frequency 
    int freq = (int)(max_magnitude_imdex * sampleRate/bufferSize); 

을 그리고 @ hotpaw2에 의해 언급 한 바와 같이 샘플 속도가 8kHz에서 너무 낮습니다. 최소 44.1kHz, 바람직하게는 48kHz가되어야합니다.

+0

의 값을 주셔서 감사합니다. 내 샘플 레이트를 48kHz로 설정하고 말씀 드렸듯이 7 단계와 8 단계를 변경했습니다. 소리를 내지 않고 시도해도 주파수는 40 ~ 200Hz로 양호합니다. 그러나 두 번째 휴대 전화에서 19kHz로 초음파를 생성 할 때 나는 좋은 가치를 얻지 못하고 때로는 23kHz를 얻습니다. 전화기에서 실제로 초음파를 생성 할 수 있는지 알고 있습니까? 내 컴퓨터 스피커에서 초음파를 만드는 것이 더 나을 것이라고 생각하십니까? – Drakkin

+1

전화기, 컴퓨터 등의 대부분의 소비자 용 변환기 (마이크로폰 및 라우드 스피커)는 실제로 "하이파이 (hi fi)"용도로 설계되지 않았기 때문에 ~ 15kHz 이상의 주파수에서 고생합니다. 이 주파수 범위에서 신뢰할만한 것을하기가 어려울 것입니다. –

+0

@PaulR 안녕하세요, 왜 max_magnitude_index가 매우 큰 가치를 반환하는지 때때로 알 수 있습니까? 그런 다음 500 hertc, 응용 프로그램 언젠가는 45000/49000 및 기타 큰 숫자로 계산했을 때처럼 주파수를 누른 다음 오른쪽 아닌가요? – Peter