声音样本的数学分析(数字数组)
我需要找到一个以字节数组存储(以vb格式)的样本频率。样本是一个正弦波,已知频率,因此我可以检查),但是数字有点奇怪,我的maths-foo很弱。
值的完整范围(0-255)。 99%的数字在235至245范围内,但有些离群值低至0和1,其余1%则高达255.
如何将其标准化以消除异常值(计算235-245间隔,因为间隔可能随不同样本而变化),然后如何计算零交叉以获取频率?
抱歉,此描述是垃圾!
解决方案
回答
使用傅立叶变换,与对零交叉计数相比,它对噪声更不敏感
编辑:@WaveyDavey
我找到了一个进行FFT的库:从这里
As it turns out, the best free implementation that I've found for F# users so far is still the fantastic FFTW library. Their site has a precompiled Windows DLL. I've written minimal bindings that allow thread-safe access to FFTW from F#, with both guru and simple interfaces. Performance is excellent, 32-bit Windows XP Pro is only up to 35% slower than 64-bit Linux.
现在,我确定我们可以从VB.net,Cetc调用Flib,这应该在他们的文档中
回答
解决此问题的标准方法是考虑一个数据块,希望至少是实际频率的两倍(获取更多数据也不错,所以最好高估一点),然后进行FFT并猜测该频率对应到最终FFT频谱中的最大数目。
顺便说一句,在我们也可以搜索这些答案之前,已经在这里提出了非常类似的问题。
回答
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范围之外的结果。
现在我们可以算出零交叉了。为了确保我们不会被噪音所迷惑,我们可能希望跟踪最后几个点的坡度,并且仅在平均坡度正确时才计算交叉点。
回答
我用谷歌搜索了"基本英尺"。 Visual Basic FFT问题会激怒FFT,但要小心,在不了解DSP的情况下使用FFT可能会导致结果,我们可能不了解或者不知道它们来自何处。
回答
如果我从描述中很好地理解,我们所拥有的就是一个信号,它是一个正弦波,一个常数以及一些随机毛刺的组合。说,像
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都不是答案,则可以尝试使用以下方法拟合正弦曲线:拟合程序并读取拟合的频率。
使用Fityk,我们可以加载数据,并拟合到" a * sin(b * x-c)",其中" 2 * pi / b"将为我们拟合后的频率。
Fityk可以在gui中使用,也可以从命令行中使用以进行脚本编写,并且具有C ++ API,因此可以直接包含在程序中。
回答
在http://www.relisoft.com/Freeware/index.htm上获取"频率分析器",然后运行它并查看代码。