我需要找到一个样本的频率,存储(在vb中)作为一个字节数组。样本是一个正弦波,已知频率,所以我可以检查),但数字有点奇怪,我的数学foo很弱。 全系列值0-255。 99%的数字在235到245的范围内,但有一些异常值降至0和1,其余1%则高达255。 如何对此进行归一化以去除异常值(计算235-245间隔,因为它可能随着不同的样本而变化),以及如何计算过零点以获得频率? 如果这个描述是垃圾,请道歉!
答案 0 :(得分:7)
FFT可能是最好的答案,但是如果你真的想通过你的方法来做,那试试这个:
要进行标准化,首先要制作一个直方图,以计算从0到255的每个值的出现次数。然后从每一端丢弃X%的值,例如:
for (i=lower=0;i< N*(X/100); lower++)
i+=count[lower];
//repeat in other direction for upper
现在使用
进行标准化A[i] = 255*(A[i]-lower)/(upper-lower)-128
将结果丢弃在-128..127范围之外。
现在你可以计算过零点。为了确保您不会受到噪音的愚弄,您可能希望跟踪最后几个点的斜率,并且仅在平均斜率正确的情况下计算交叉点。
答案 1 :(得分:5)
攻击这个问题的标准方法是考虑一个数据块,希望至少是实际频率的两倍(获取更多数据也不错,所以高估一点是好的),然后采用{{3}并猜测频率对应于得到的FFT频谱中的最大数字。
顺便说一下,之前已经问过非常类似的问题 - 你也可以搜索这些答案。
答案 2 :(得分:3)
使用傅立叶变换,它比计算零交叉更加噪声不敏感
编辑:@WaveyDavey
我发现了一个用于进行FFT的F#库:From here
事实证明,最好的免费 我为F#找到的实现 到目前为止用户仍然很棒 FFTW库。他们的网站有一个 预编译的Windows DLL。我写过 最小的绑定允许 从F#线程安全访问FFTW, 同时拥有大师和简单的界面。 性能非常出色,32位 Windows XP Pro仅高达35% 比64位Linux慢。
现在我确定你可以从VB.net,C#等调用F#lib,这应该在他们的文档中
答案 3 :(得分:2)
如果我从你的描述中理解得很清楚,你所拥有的是一个信号,它是一个正弦加一个常数加上一些随机故障的组合。说,像
x[n] = A*sin(f*n + phi) + B + N[n]
其中N [n]是你要摆脱的“小故障”噪音。
如果毛刺是单样本长的,您可以使用中值滤波器去除它们,中值滤波器必须大于毛刺长度。在故障的两边。长度为1的毛刺意味着你将有足够的中位数为3个样本的长度。
y[n] = median3(x[n])
计算中位数:取你想要过滤的x的样本(x [n-1],x [n],x [n + 1]),对它们进行排序,输出是中间的。
现在噪声信号消失,摆脱恒定信号。我知道缓冲区的长度有限且已知,因此您只需计算整个缓冲区的平均值即可。摘要它。
现在你有了单个窦信号。您现在可以通过计算过零点来计算基频。计算前一个样本低于0的样本数量。该时间段是缓冲区样本的总量除以此值,频率是该时间段的对数(1 / x)。
答案 4 :(得分:1)
虽然我会与大多数人一起说,看起来你想要的是一个fft解决方案(fft算法非常快),如果fft不是任何理由的答案,你可能想尝试拟合正弦曲线使用拟合程序并读取拟合频率的数据。
使用Fityk,您可以加载数据,并适合a*sin(b*x-c)
2*pi/b
,其中{{1}}会在拟合后为您提供频率。
Fityk可以从一个gui,一个脚本命令行使用,并且有一个C ++ API,因此可以直接包含在你的程序中。
答案 5 :(得分:0)
我用Google搜索“基本fft”。 Visual Basic FFT你的问题尖叫FFT,但要小心,使用FFT而不了解一点关于DSP可能导致你不理解或不知道它们来自哪里的结果。
答案 6 :(得分:0)
将频率分析器放在http://www.relisoft.com/Freeware/index.htm并运行它并查看代码。