Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.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 调谐器应用程序中的频率不正确_Java_Android_Fft_Frequency Analysis - Fatal编程技术网

Java 调谐器应用程序中的频率不正确

Java 调谐器应用程序中的频率不正确,java,android,fft,frequency-analysis,Java,Android,Fft,Frequency Analysis,我目前正在开发一个OpenGL调谐器应用程序。我现在在屏幕上有FFT图,我想计算最大的频率。下面是我的代码的样子: main活动 @覆盖 创建时受保护的void(Bundle savedInstanceState){ super.onCreate(savedInstanceState); // ... 变压器=新的RealDoubleFFT(样本); 开始=真; recordAudio=新的recordAudio(); recordAudio.execute(); } // ... 公共类Rec

我目前正在开发一个OpenGL调谐器应用程序。我现在在屏幕上有FFT图,我想计算最大的频率。下面是我的代码的样子:

main活动

@覆盖
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// ...
变压器=新的RealDoubleFFT(样本);
开始=真;
recordAudio=新的recordAudio();
recordAudio.execute();
}
// ...
公共类RecordAudio扩展异步任务{
@凌驾
受保护的Void doInBackground(Void…arg0){
试一试{
int bufferSize=AudioRecord.getMinBufferSize(sampleRate、channelConfig、audioFormat);
AudioRecord AudioRecord=新的录音(MediaRecorder.AudioSource.MIC、sampleRate、,
channelConfig、audioFormat、bufferSize);
short[]buffer=新的short[样本];
double[]fft=新的双[样本];
录音。开始录制();
while(启动){
int bufferReadResult=audioRecord.read(缓冲区,0,样本);
对于(int i=0;i峰值){
颜色=(浮动)(i-峰值)/(浮动)(int)((浮动)样品/2f-峰值);
}否则{
颜色=0f;
}
颜色=1f-颜色;
fftVertices[offset++]=颜色;
fftVertices[offset++]=颜色;
fftVertices[offset++]=颜色;
FFT属性[offset++]=((浮点)i/(浮点)样本)*2f)-1f;
fft属性[offset++]=((浮点)fft[0][i]/2f)-1f;
fftVertices[offset++]=颜色;
fftVertices[offset++]=颜色;
fftVertices[offset++]=颜色;
如果(i%2==0){
幅值[(int)((float)i/2f)]=(float)数学sqrt(fft[0][i]*fft[0][i]+fft[0][i+1]*fft[0][i+1]);
}
}
更新频率(量级);
}
}
私有静态void更新频率(float[]mag){
int峰值=0;
对于(int i=0;i<(int)((浮点)样本/2f);i++){
如果(mag[i]>=mag[peak]){
峰值=i;
}
}
频率=峰值*取样器/样品;
日志d(“主要活动”,“频率:+频率+Hz”);
}
私有静态浮点[]getVertices(){
返回FFT属性;
}
私有静态类呈现器实现GLSurfaceView.Renderer{
// ...
私有浮点[]顶点=新浮点[样本*2*(位置分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量分量;
公共渲染器(上下文){
// ...
整数偏移=0;
对于(int i=0;i
因此,
main活动
包含
RecordAudio
类。我遗漏了一些不重要的行,比如OpenGL或应用程序。基本上,我的应用程序读取音频输入并在屏幕上显示FFT。我设置了一个频率计算,如下所示:

我首先制作一个数量级的浮点数组:

在这里,在通过FFT进行迭代的for循环中,每次迭代(索引为偶数)都会向数组添加一个幅值。最后,计算频率:

  private static void updateFrequency(float[] mag) {
    int peak = 0;
    for (int i = 0; i < (int) ((float) samples / 2f); i++) {
      if (mag[i] >= mag[peak]) {
        peak = i;
      }
    }
    frequency = peak * (int) ((float) sampleRate / (float) samples);
    Log.d("MainActivity", "Frequency: " + frequency + " Hz");
  }

如何获得更稳定、更准确的结果?

DFT的一个问题是,如果你的峰值很宽,位于两个(或多个)仓上,并且移动很小(由于多普勒或其他原因),那么你将得到两个仓之间的能量波动

一种方法是增加FFT的箱数(FFT的点数)。你也可以考虑一下。

如果您不想搞乱FFT的点数,另一种方法是从FFT数据中插值峰值(和频率)。这种技术的好方法


我不确定准确度,但我认为这有助于结果的稳定性(减少波动)。

对于稳定:您可以查看峰值插值,因为峰值可能不完全在箱子内。谢谢,这确实纠正了稳定性和准确性。哦!那很好。让我来回答这个问题,这样人们就可以使用它。调谐器应用程序应该分析音高,而不是峰值频率。@hotpaw2-我如何分析音高?我想我是从峰值频率得到的。
  private static void updateFrequency(float[] mag) {
    int peak = 0;
    for (int i = 0; i < (int) ((float) samples / 2f); i++) {
      if (mag[i] >= mag[peak]) {
        peak = i;
      }
    }
    frequency = peak * (int) ((float) sampleRate / (float) samples);
    Log.d("MainActivity", "Frequency: " + frequency + " Hz");
  }