2013-08-22 14 views
5

Z jakiegoś powodu częstotliwości jak wypartejJak uzyskać częstotliwość z danych PCM w Javie - FFT

391 hz => 1162 
440 hz => 2196 
493 hz => 2454 

Używam tego ceni

final int audioFrames= 1024; 
final float sampleRate= 44100.0f; 
final int bitsPerRecord= 16; 
final int channels= 1; 
final boolean bigEndian = true; 
final boolean signed= true; 

byteData= new byte[audioFrames * 2]; //two bytes per audio frame, 16 bits 
dData= new double[audioFrames * 2]; // real & imaginary 

To jak ja gotowy danych i przekształcenia to do podwójnej:

format = new AudioFormat(sampleRate, bitsPerRecord, channels, signed, bigEndian); 
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 
microphone = (TargetDataLine) AudioSystem.getLine(info); 
microphone.open(format); 
microphone.start(); 
int numBytesRead = microphone.read(byteData, 0, byteData.length); 

Gdy dane są odczytywane, odlana z 16 bitów, big endian, podpisana podwoić

public void byteToDouble(){ 
    ByteBuffer buf= ByteBuffer.wrap(byteData); 
    buf.order(ByteOrder.BIG_ENDIAN); 
    int i=0; 
    while(buf.remaining()>1){ 
     short s = buf.getShort(); 
     dData[ 2 * i ] = (double) s/32768.0; //real 
     dData[ 2 * i + 1] = 0.0; // imag 
     ++i; 
    } 
} 

I wreszcie uruchomić FFT i znaleźć częstotliwość:

public void findFrequency(){ 

    double frequency; 

      DoubleFFT_1D fft= new DoubleFFT_1D(audioFrames); 
/* edu/emory/mathcs/jtransforms/fft/DoubleFFT_1D.java */ 

    fft.complexForward(dData); // do the magic so we can find peak  
    for(int i = 0; i < audioFrames; i++){ 
     re[i] = dData[i*2]; 
     im[i] = dData[(i*2)+1]; 
     mag[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i])); 
    } 

    double peak = -1.0; 
    int peakIn=-1; 
    for(int i = 0; i < audioFrames; i++){ 
     if(peak < mag[i]){ 
      peakIn=i; 
      peak= mag[i]; 
     } 
    } 
    frequency = (sampleRate * (double)peakIn)/(double)audioFrames; 
    System.out.print("Peak: "+peakIn+", Frequency: "+frequency+"\n"); 
} 
+0

Wygląda dobrze oprócz faktu, że nie używasz funkcji okna, więc Twoje widmo będzie rozmazane. Spróbuj wykreślić 'mag []' i sprawdzić, czy widmo wygląda rozsądnie, tj. Pojedynczy duży pik gdzieś w niższych rzędach rzędu. –

+0

Cześć Paul, wydaje się, że moim problemem jest to, że beczki częstotliwości nie są wystarczająco dokładne, więc na przykład, jeśli dźwięk ma częstotliwość 440 Hz, ale mój przedział częstotliwości jest bliżej 445 Hz, to nie będzie go używać, zamiast tego użyje go harmoniczna podobna do 1320, która może znajdować się w pojemniku częstotliwości. Czy istnieje sposób na zwiększenie dokładności tych pojemników bez konieczności czytania wielu próbek? –

+0

W przypadku niektórych instrumentów muzycznych harmoniczne są w rzeczywistości głośniejsze niż podstawowe - prawdopodobnie warto przyjrzeć się różnym metodom wykrywania wysokości dźwięku, a nie tylko wyszukiwać największego pojedynczego szczytu w FFT, który, jak stwierdzono, nie będzie zbyt duży. niezawodny. Zwróć też uwagę, że rozdzielczość twojego bin jest bardzo grubsza 44100/1024 = około 40 Hz na bin. –

Odpowiedz

0

można interpolować pomiędzy FFT pojemników wynik (parabolicznych lub interpolacji Sinc), aby uzyskać bardziej dokładne oszacowanie częstotliwości. Ale możesz mieć większy problem: twoje źródło częstotliwości może wytwarzać (lub być obcięte do produkcji) jakieś bardzo silne dziwne harmoniczne lub podteksty, które maskują każdą podstawową sinusoidę w wielkościach wyniku FFT. Dlatego powinieneś spróbować użyć algorytmu wykrywania/szacowania wysokości tonu zamiast po prostu szukać (prawdopodobnie brakującego) piku FFT.

0

Po pierwsze, jeśli nagrywany dźwięk jest długi, należy wykonać FFT w porcjach, najlepiej z okienkowaniem każdej części przed wykonaniem FFT. FFT oblicza tylko jedną częstotliwość podstawową, więc musisz wziąć FFT w wielu miejscach, jeśli częstotliwość zmienia się wiele razy.

Dokładność można poprawić również dzięki przesuwanym oknom. Oznacza to, że wziąłbyś kawałek, następnie przesuń lekko i weź kolejny kawałek, tak aby porcje pokrywały się. Ilość przesuwania jest zmienna, a rozmiar każdej porcji również jest zmienny.

Następnie sam FFT może dawać fałszywe wyniki. Możesz wykonać więcej analiz, takich jak analiza Cepstrum lub analiza spektrum harmonicznych produktów na spektrum mocy, które są generowane przez FFT w celu dokładniejszego oszacowania wysokości dźwięku.

Powiązane problemy