Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java FFT中的频率检测问题_Java_Android_Fft_Frequency - Fatal编程技术网

Java FFT中的频率检测问题

Java FFT中的频率检测问题,java,android,fft,frequency,Java,Android,Fft,Frequency,我使用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 = Audio

我使用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;
  }
}
//低通滤波器
公共无效平滑阵列(双[]音频,双平滑){
/*低通滤波器消除信号的高频变化。
*那是背景噪音,例如电脑的嗡嗡声*/
//获取第一个音频数据值
双平滑=音频[0];
Long lastUpdate=System.currentTimeMillis()/1000;
对于(int i=1;i
唱片班

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;
}
short[]buffer=新的short[blockSize];
//将原始PCM样本保存为短字节
audioDataDoubles=新的双精度[(块大小*2)];
//与上述值相同,为双倍值
int bufferSize=AudioRecord.getMinBufferSize(sampleRate、channelConfig、audioEncoding);
//获取所需的最小缓冲区
音频记录=新的音频记录(音频源、采样器、信道配置、,
音频编码,缓冲区大小);
//缓冲区大小
录音。开始录制();
//开始工作
记录=真;
//使用中的麦克风
fft=新的双fft_1D(块大小);
while(启动){
/*从麦克风读取数据。它接收数据
*到窗口“blockSize”的大小。然后
*输入到audioRecord。返回的int是数字
*读取的字节数*/
int bufferReadResult=audioRecord.read(缓冲区,0,块大小);
//将数据从麦克风读入阵列
//从缓冲区提取并传递到AudioDataDouble
fillArray(AudioDataDouble、buffer、blockSize、bufferReadResult);
}
//应用低通滤波器以消除噪声
smoothArray(AudioDataDouble,平滑);
//AudioDataDouble现在保存要使用的数据
fft.complexForward(音频数据双精度);
double[]re=新的double[blockSize];
double[]im=新的double[blockSize];
double[]震级=新的double[blockSize];
//计算实数、虚数和震级。
对于(int i=0;i
返回的频率不正确且不恒定。我希望至少有一个恒定的频率数字,但它会不断变化。例如,在440.1 hz的频率下读取,返回290hz-390hz。我运行了一个图表,它提供了一个不变的预期峰值。有人能看出我的错误吗?
谢谢。

这可能不是您根本问题的答案,但低通滤波器肯定是错误的:您使用的是时钟时间(System.currentTimeMillis()),但音频数据已在以前的一些时间间隔捕获


我不确定过滤器应该做什么。但是在你的评论中说,
smoothing=1
应该保持数据不变,我不认为是这样。

这个问题与你之前的问题不同吗?()我已经实施了前面问题中的选项。我已经包括了环形缓冲区,并尝试增加fft采样窗口。两者都没有用。在FFT之前,您似乎没有解决缺少窗口函数的问题?这里有很多很好的答案,所以在这个主题上,这也是一个很好的起点。一个简单的Hann或Hamming窗口应该就是您所需要的。您可以将窗口函数应用于要传递给FFT的样本块。因此,如果您的FFT大小是2048,那么您将对2048个样本块应用2048点窗函数,然后将这些加窗样本传递给FFT。谢谢,滤波器不正确。我已经删除了它,频率读数更稳定。然而,他们仍然是错误的。