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");
}
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. –
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? –
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. –