我需要找到一个样本的频率,存储(在VB中)作为一个字节数组。样本是正弦波,频率已知,所以我可以检查),但数字有点奇怪,而且我的 maths-foo 很弱。全范围值 0-255。99% 的数字在 235 到 245 范围内,但也有一些低至 0 和 1 的异常值,而其余 1% 的数字则高达 255。如何对其进行标准化以消除异常值(计算 235-245 间隔,因为它可能会随不同样本而变化),然后如何计算过零以获得频率?如果这个描述是垃圾,我们深表歉意!

有帮助吗?

解决方案

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 范围之外的结果。

现在您可以计算过零的次数。为了确保您不会被噪音所欺骗,您可能需要跟踪最后几个点的坡度,并且仅在平均坡度正确时才计算交叉口。

其他提示

解决这个问题的标准方法是考虑一个数据块,希望至少是实际频率的两倍(获取更多数据也不错,所以高估一点是有好处的),然后取 快速傅里叶变换 并猜测该频率对应于生成的 FFT 频谱中的最大数字。

顺便说一句,以前曾在这里提出过非常类似的问题 - 您也可以搜索这些答案。

使用傅立叶变换,它比计算过零对噪声更不敏感

编辑:@WaveyDavey

我找到了一个 F# 库来进行 FFT: 从这里

事实证明,到目前为止,我为F#用户找到的最佳免费实施仍然是很棒的FFTW库。他们的网站有一个预编译的Windows DLL。我编写了最小的绑定,可以从f#和简单的接口中从f#访问fftw。性能非常出色,32位Windows XP Pro仅比64位Linux慢35%。

现在我确信您可以从 VB.net、C# 等调用 F# lib,这应该在他们的文档中

如果我从你的描述中很好地理解,你所拥有的是一个信号,它是正弦加常数加上一些随机毛刺的组合。说,像

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 且高于 0 的样本数量。周期是缓冲区的样本总数除以该值,频率是周期的倒数 (1/x)。

虽然我会同意大多数人的观点,并说您似乎想要的是一个 fft 解决方案(fft 算法非常快),但如果出于某种原因 fft 不是答案,您可能想尝试使用以下方法将正弦曲线拟合到数据拟合程序并读取拟合频率。

使用 菲提克, ,您可以加载数据,并拟合 a*sin(b*x-c) 在哪里 2*pi/b 会给你安装后的频率。

Fityk 可以从图形用户界面、命令行脚本中使用,并且具有 C++ API,因此可以直接包含在您的程序中。

我用谷歌搜索“基本 fft”。 Visual Basic 快速傅里叶变换 你的问题尖叫着 FFT,但要小心,在不了解 DSP 的情况下使用 FFT 可能会导致你不理解或不知道它们来自哪里的结果。

获取频率分析仪 http://www.relisoft.com/Freeware/index.htm 并运行它并查看代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top