当前位置:硬件测评 > FFT 不精确 C#

FFT 不精确 C#

  • 发布:2023-10-04 14:29

我一直在尝试 FFT 算法。我正在使用 NAudio 以及来自互联网的 FFT 算法的工作代码。根据我对表演的观察,最终的音调是不准确的。 发生的情况是,我将 MIDI(由 GuitarPro 生成)转换为 WAV 文件(44.1khz,16 位,单声道),其中包含从 E2(最低的吉他音符)到大约 E6 的音高级别。低音(E2-B3 附近)的结果通常非常错误。但达到 C4 在某种程度上是正确的,因为您已经可以看到正确的进展(下一个音符是 C#4,然后是 D4,等等)。但是,问题是检测到的音高比实际音高低半音(例如, C4 应该是一个注释,但它写着 D#4)。 您认为可能出了什么问题?如果需要的话我可以发布代码。太感谢了!我还在开始掌握 DSP 领域。 编辑:这是我正在做的事情的一个粗略的草稿
字节[]缓冲区=新字节[8192];
int 字节读取;
做
{
  bytesRead = www.sychzs.cn(buffer, 0, buffer.Length);
while (bytesRead != 0);
那么:(waveBuffer只是一个将byte[]转换为float[]的类,因为该函数只接受float[])
public int Read(byte[] buffer, int offset, int bytesRead)
{
  int 帧 = bytesRead / sizeof(float);
  浮动音高 = DetectPitch(waveBuffer.FloatBuffer, 帧);
}
最后:(smbpitchfft是一个带有FFT算法的类...我相信没有什么问题,所以这里就不贴出来了)
private float DetectPitch(float[] buffer, int inFrames)
{
  Func 窗口 = HammingWindow;
  if (prevBuffer == null)
  {
    prevBuffer = new float[inFrames]; //仅包含零
  }// 双帧,因为我们正在组合当前和先前的缓冲区
  int 帧 = inFrames * 2;
  if (fftBuffer == null)
  {
    fftBuffer = new float[帧数 * 2]; // 乘以2,因为它是复杂的输入
  }

  for (int n = 0; n < 帧; n++)
  {
     if (n < 帧内数)
     {
       fftBuffer[n * 2] = prevBuffer[n] * 窗口(n,帧);
       fftBuffer[n * 2 + 1] = 0; // 当fft修改缓冲区时需要清除
     }
     别的
     {
       fftBuffer[n * 2] = 缓冲区[n - inFrames] * 窗口(n, 帧);
       fftBuffer[n * 2 + 1] = 0; // 当fft修改缓冲区时需要清除
     }
   }
   SmbPitchShift.smbFft(fftBuffer, 帧, -1);
  }
并且为了解释结果:
float binSize = 采样率 / 帧数;
int minBin = (int)(82.407 / binSize); //吉他上最低的E弦
int maxBin = (int)(1244.508 / binSize); //吉他上最高的E弦

浮动最大强度 = 0f;
int maxBinIndex = 0;

for (int bin = minBin; bin <= maxBin; bin++)
{浮点实数 = fftBuffer[bin * 2];
    浮点虚数 = fftBuffer[bin * 2 + 1];
    浮点强度 = 实数 * 实数 + 虚数 * 虚数;
    如果(强度 > 最大强度)
    {
        最大强度=强度;
        maxBinIndex = bin;
    }
}

返回 binSize * maxBinIndex;
更新(如果有人仍然感兴趣): 因此,下面的答案之一指出 FFT 的频率峰值并不总是等于音调。我明白那个。但是,如果是这种情况,我想自己尝试一些东西(假设有时频率峰值是最终音调)。基本上,我有 2 个软件(DewResearch 的 SpectraPLUS 和 FFTProperties;相信它们)能够显示音频信号的频域。 以下是时域中频率峰值的结果: 光谱PLUS 和 FFT 属性: 这是使用 A2 的测试记录(大约 110Hz)完成的。查看图像时,SpectraPLUS 的频率峰值约为 102-112 Hz,FFT 属性的频率峰值约为 108 Hz。在我的代码中,我得到 104Hz(我使用 8192 个块,采样率为 44.1khz...8192 然后加倍以使其复杂输入,所以最终,我得到大约 5Hz binsize,与 SpectraPLUS 的 10Hz binsize 相比)。 所以现在我有点困惑,因为在软件上它们似乎返回了正确的结果,但在我的代码上我总是得到 104Hz(注意我已经将我使用的 FFT 函数与 www.sychzs.cn 等其他函数进行了比较,似乎是正确的)。 您认为问题可能与我对数据的解释有关吗?或者软件在显示光谱之前是否做了其他事情?谢谢! ​​

相关文章

最新资讯