[英]Issue with frequency detection in FFT
我正在使用FFT通過設備麥克風計算持續音符的頻率。 我正在使用JTransform計算FFT。 以下是代碼:
//Mic reading variables
int audioSource = MediaRecorder.AudioSource.MIC;
// Audio source is the device mic
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
// Recording in mono
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
// Records in 16bit
//Frequency calculation variables
double[] audioDataDoubles;
private DoubleFFT_1D fft;
// The fft double array I am unsure if these values are correct. I cant seem to find a good balance
int blockSize = 256;
// deal with this many samples at a time
int sampleRate = 8000;
// Sample rate in Hz
double[] ringBuffer = new double[10];
int ring = 0;
double avgFreq = 0.0;
double smoothing = 20.0;
// The power for the low pass filter, The higher the more powerful
我的低通濾波器
//Low pass Filter
public void smoothArray(double[] audio, double smoothing){
/* The Low pass filter removes the high frequency changes to signal.
* That being background noise, e.g. hum of computers*/
// Takes the first audio data value
double smooth = audio[0];
Long lastUpdate = System.currentTimeMillis()/1000;
for(int i = 1; i < audio.length; i++){
Long now = System.currentTimeMillis()/1000;
double currentValue = audio[i];
/*Calculates the difference of two signals and
* divides it by the smoothing power.
* A Smoothing power of 1 will leave the data untouched.
* A higher number will remove the high frequency.
*/
Long elapsedTime = now - lastUpdate;
double elapsed = elapsedTime.doubleValue();
smooth += elapsed * (currentValue - smooth) / smoothing;
lastUpdate = now;
audio[i] = smooth;
}
}
唱片班
short[] buffer = new short[blockSize];
// Save the raw PCM samples as short bytes
audioDataDoubles = new double[(blockSize*2)];
// Same values as above, as doubles
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding);
// Gets the minimum buffer needed
audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig,
audioEncoding, bufferSize);
//bufferSize
audioRecord.startRecording();
// Start working
record = true;
// mic in use
fft = new DoubleFFT_1D(blockSize);
while(started){
/* Reads the data from the microphone. it takes in data
* to the size of the window "blockSize". The data is then
* given in to audioRecord. The int returned is the number
* of bytes that were read*/
int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
// Read in the data from the mic to the array
// takes from buffer and passes to audiodataDoubles
fillArray(audioDataDoubles, buffer, blockSize, bufferReadResult);
}
//Apply the low pass filter to remove noise
smoothArray(audioDataDoubles, smoothing);
//audiodataDoubles now holds data to work with
fft.complexForward(audioDataDoubles);
double[] re = new double[blockSize];
double[] im = new double[blockSize];
double[] magnitude = new double[blockSize];
// Calculate the Real and imaginary and Magnitude.
for(int i = 0; i < blockSize; i++){
// real is stored in first part of array
re[i] = audioDataDoubles[i*2];
// imaginary is stored in the sequential part
im[i] = audioDataDoubles[(i*2)+1];
// magnitude is calculated by the square root of (imaginary^2 + real^2)
magnitude[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i]));
}
double peak = -1.0;
// Get the largest magnitude peak
for(int i = 0; i < blockSize; i++){
if(peak < magnitude[i])
peak = magnitude[i];
}
// calculated the frequency
frequency = sampleRate * peak/blockSize;
ringBuffer[ring] = frequency;
ring++;
if(ring == (ringBuffer.length -1)){
for(int j = 0; j < ring; j++){
avgFreq = avgFreq + ringBuffer[j];
}
double avg = (double) ring;
avgFreq = avgFreq/avg;
Log.i("AudioRecord", "HZ: " + avgFreq);
/* calls onProgressUpdate
* publishes the frequency
*/
publishProgress(avgFreq);
//restart the ring buffer
ring = 0;
}
返回的頻率不正確,並且不是恆定的。 我期待至少一個恆定的頻率數字,但是它會不斷變化。 例如,在440.1 hz中讀取將返回290hz-390hz。 我已經運行了一個圖形,它提供了一個不變的預期峰值。 誰能發現我的錯誤? 謝謝。
它可能無法解決您的基本問題,但是低通濾波器肯定是錯誤的:您使用時鍾中的時間(System.currentTimeMillis()),但是音頻數據已經在以前的某些時間間隔捕獲了。
我不確定過濾器應該做什么。 但是它在您的評論中說, smoothing=1
應該使數據保持不變,我不認為是這種情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.