我刚写了dft的实现。这是我的代码:
int T = 2205;
float[] sign = new float[T];
for (int i = 0, j = 0; i < T; i++, j++)
sign[i] = (float)Math.Sin(2.0f * Math.PI * 120.0f * i/ 44100.0f);
float[] re = new float[T];
float[] im = new float[T];
float[] dft = new float[T];
for (int k = 0; k < T; k++)
{
for (int n = 0; n < T; n++)
{
re[k] += sign[n] * (float)Math.Cos(2.0f* Math.PI * k * n / T);
im[k] += sign[n] * (float)Math.Sin(2.0f* Math.PI * k * n / T);;
}
dft[k] = (float)Math.Sqrt(re[k] * re[k] + im[k] * im[k]);
}
因此采样频率为44100 Hz,我有一个50ms的120Hz正弦波段。根据结果,我在7号和2200号处有一个dft函数的峰值。我做错了什么,如果没有,我应该如何解释结果?
我尝试了AFORGE的FFT方法。 Heres是我的代码。
int T = 2048;
float[] sign = new float[T];
AForge.Math.Complex[] input = new AForge.Math.Complex[T];
for (int i = 0; i < T; i++)
{
sign[i] = (float)Math.Sin(2.0f * Math.PI * 125.0f * i / 44100.0f);
input[i].Re = sign[i];
input[i].Im = 0.0;
}
AForge.Math.FourierTransform.FFT(input, AForge.Math.FourierTransform.Direction.Forward);
AForge.Math.FourierTransform.FFT(input, AForge.Math.FourierTransform.Direction.Backward);
我本来期望获得原始标志,但我得到了一些不同的东西(只有正值的函数)。这是正常的吗? 提前谢谢!
答案 0 :(得分:1)
您的代码看起来正确,但它可能更有效,DFT通常通过FFT算法解决(快速傅里叶变换,它不是新的变换,它只是一种以更有效的方式解决DFT的算法)。
即使您不想实现FFT(这有点难以理解,并且很难使其处理非2^n
形式的数据)或使用某些开源代码,您也可以让你的实现有点快,例如看到2.0f * Math.PI * K / T
是一个在内循环之外的常量,所以你可以为每个k计算一次(将它移到内部循环之外),然后将它乘以{{1在n
函数中。
至于位置和解释,你已经改变了你的域,现在你的X轴,这是表中数据的索引,不是时间而是频率。您有cos/sin
的采样,并且您已捕获44100Hz
个样本,这意味着每1个样本代表输入信号的幅度,其频率等于2205
。你的幅度峰值在第7点(指数6),因为你的信号是120Hz,所以你可以期待44100Hz / 2205 = 20Hz
。
秒数峰似乎代表一些高频率,但它只是一个虚假的信号,因为你的采样率是6 * 20Hz = 120Hz
,你不能测量高于44100Hz
(奈奎斯特定律)的频率,如果你削减在该频率之后,DFT数据无效。这就是为什么你的桌子的后半部分是无效的,它基本上是你的上半部分但镜像了,你可以忽略它。
修改强> // 从您的问题我可以看到您对音频处理感兴趣,您可能想要谷歌NForge.Net库,这是一个伟大的音频和视觉处理开源库,其作者在codeproject.com上有许多关于许多的好文章它的功能。