【发布时间】:2020-01-30 20:40:49
【问题描述】:
我正在用 C# 在 Visual Studio 2010 中开发一个小应用程序来绘制频谱图(频率“热图”)。
我已经完成了基本的事情:
- 从输入信号数组中切出一个矩形窗口数组
- 将该数组输入 FFT,返回复数值
- 将幅度值存储在数组中(该窗口的频谱)
- 步进窗口,并将新值存储在其他数组中,从而生成一个锯齿状数组,其中包含窗口的每一步及其光谱
- 将它们绘制到图形对象中,颜色使用热图的全局最小值/最大值作为相对冷和热
屏幕截图的左侧显示了我的应用程序,在右侧有一个频谱图,用于相同的输入(512 个样本长)和来自名为“过去 - 时间序列分析”的程序的大小为 32 的相同矩形窗口(@ 987654321@)。我的 512 长样本数组仅包含 100 到 1400 之间的整数元素。 (注意:PAST 谱图最右侧的浅蓝色条只是因为我不小心在那个输入数组的末尾留下了一个不必要的 '0' 元素。否则它们是相同的。)
截图链接:https://drive.google.com/open?id=1UbJ4GyqmS6zaHoYZCLN9c0JhWONlrbe3
但是我在这里遇到了一些问题:
- 频谱图看起来很不详细,和我在“过去时间序列分析”中做的另一张有关系,供参考,那张看起来非常详细。这是为什么? 我知道,例如32 个长时间窗口,FFT 返回 32 个元素,这里不需要 0. elem,接下来的 32/2 个元素具有我需要的幅度值。但这意味着 32 长窗口的输出频率“分辨率”为 16。这正是我的程序使用的。但是“PAST”程序显示了更多细节。如果您查看蓝色背景中的细线,您会看到它们在频率轴上显示出很好的图案,但在我的频谱图中,这些信息仍然看不到。为什么?
- 在开始 (windowSize/2) 宽窗口步进带和结束 (windowSize/2) 步进带中,FFT 输入的值较少,因此输出较少,或者精度较低。但在“PAST”程序中,这些部分似乎也比较详细,而不是像我的那样只是拉伸条。我该如何改进?
- FFT 返回数组的 0. 元素(所谓的“DC”元素)是一个巨大的数字,比样本平均值甚至它的总和要大得多。这是为什么呢?
- 为什么我的值(例如,您在彩条附近看到的最大值)如此之大?这只是 FFT 输出的幅度值。为什么 PAST 程序中有不同的值?我应该在 FFT 输出上使用什么校正来获得这些值?
如果您对此主题有更多了解,请分享您的想法。我对此很陌生。一个多星期前,我才第一次读到傅里叶变换。
提前致谢!
【问题讨论】:
-
如果您想在 STFT(短时傅立叶变换)中获得更高的频率分辨率,则需要更多的时间步长,这意味着这会降低您的时间分辨率。但是,您可以重叠您的时间间隔(实际上是插值)。您可以通过从数据中减去所有数据的平均值来移除 DC。是否要保留它是编程之外的问题,这是您需要考虑的数据的物理含义。同上关于颜色条,也许你还没有删除 DC。
-
注意:我会首先在更高级别的环境(如 Matlab、Python Numpy、Mathematica)中开发类似的东西来计算参数。这也将使您更容易获得对您的问题的支持(可以发布短代码,图像代码可以制作,因此您不会陷入 C# 实现问题)。
-
感谢您的所有回答! :) 我最大的问题是(因为我的 Y 值都很大)我应该在任何处理之前从整个信号数组中减去平均值。现在我已经做到了。我现在还使用了最大重叠量,并添加了零填充,这对强调细节很有帮助。对数着色也非常有效,并且显示接近最大幅度的信息更易于识别。如果我使用 32、64(或任何偶数)长窗口,窗口函数必须像“matlab 对称”:en.wikipedia.org/wiki/Window_function#Symmetry
标签: c# fft dft spectrogram spectrum