11

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

4

7 回答 7

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

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

于 2008-09-17T20:59:32.153 回答
5

解决这个问题的标准方法是考虑一个数据块,希望至少是实际频率的两倍(获取更多数据还不错,所以高估一点是好的),然后进行FFT并猜测频率对应到得到的 FFT 频谱中的最大数。

顺便说一句,以前在这里问过非常相似的问题——你也可以搜索这些答案。

于 2008-09-17T20:31:10.460 回答
3

使用傅里叶变换,它比计算零交叉对噪声不敏感

编辑:@WaveyDavey

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

事实证明,到目前为止,我为 F# 用户找到的最好的免费实现仍然是出色的 FFTW 库。他们的网站有一个预编译的 Windows DLL。我编写了最小的绑定,允许从 F# 对 FFTW 进行线程安全访问,具有 guru 和简单接口。性能极佳,32 位 Windows XP Pro 仅比 64 位 Linux 慢 35%。

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

于 2008-09-17T20:30:04.330 回答
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 的样本数量高于 0。周期是缓冲区的样本总数除以这个,频率是周期的相反 (1/x)。

于 2008-09-17T21:24:57.130 回答
1

虽然我会和大多数人一起说你想要的是一个 fft 解决方案(fft 算法非常快),但如果 fft 不是答案,无论出于何种原因,你可能想尝试使用正弦曲线拟合数据拟合程序并读取拟合频率。

使用Fityk,您可以加载数据,并拟合到a*sin(b*x-c)哪里2*pi/b会给您拟合后的频率。

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

于 2008-09-17T23:37:14.660 回答
0

我用谷歌搜索“基本 fft”。Visual Basic FFT您的问题尖叫 FFT,但要小心,在不了解 DSP 的情况下使用 FFT 可能会导致您不了解或不知道它们来自何处的结果。

于 2008-09-17T21:04:48.863 回答
0

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

于 2008-09-18T01:12:55.757 回答