You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用fft.js提取折线图频率:振幅异常与负值疑问

FFT频率提取问题

我正在使用fft.js库从每秒获取新数据点的折线图数据中提取频率,以下是我的代码:

function getFrequencis(frequencySpectrum, sampleRate, dataLength) {
    const binSize = sampleRate / dataLength;
    var frequenciesDict = {}

    for (let j = 1; j < frequencySpectrum.length; j++) {
      frequenciesDict[j*binSize] = frequencySpectrum[j]
    }

    return frequenciesDict
}


const f = new FFT(32);

const out = f.createComplexArray();


    f.realTransform(out, [1,2,3,4,5,5,4,3,2,1,1,2,3,4,5,5,4,3,2,1,1,2,3,4,5,5,4,3,2,1,2,3]);

getFrequencis(out, 1, 32)

我预期0.09375频率的振幅最强,但得到如下返回结果:

{
    "1": -1,
    "0.03125": 0,
    "0.0625": -1.330508935085469,
    "0.09375": -0.5060331130932036,
    "0.125": -2.7653668647301792,
    "0.15625": -2.082392200292394,
    "0.1875": -17.666465995914333,
    "0.21875": -21.984229521692033,
    "0.25": 3.82842712474619,
    "0.28125": 8.242640687119286,
    "0.3125": 0.947624077129027,
    "0.34375": 4.812059092662567,
    "0.375": -0.15224093497742652,
    "0.40625": 3.613125929752753,
    "0.4375": -0.7634026789260374,
    "0.46875": 2.773999558787147,
    "0.5": -1,
    "0.53125": 2,
    "0.5625": -0.3599059628302478,
    "0.59375": 1.0688810757972436,
    "0.625": -3.8477590650225735,
    "0.65625": 1.6131259297527532,
    "0.6875": -2.2684947746976585,
    "0.71875": 0.6627612703477461,
    "0.75": -1.82842712474619,
    "0.78125": 0.24264068711928477,
    "0.8125": -1.4979446807556052,
    "0.84375": 0.008608279724096946,
    "0.875": -1.2346331352698205,
    "0.90625": -0.0823922002923938,
    "0.9375": -1.0609010489196744,
    "0.96875": -0.06901597235215756,
    "1.03125": 0,
    "1.0625": -0.41421356237309515,
    "1.09375": 0.1715728752538097,
    "1.125": 0,
    "1.15625": 0,
    "1.1875": 2.414213562373096,
    "1.21875": -5.82842712474619,
    "1.25": -4,
    "1.28125": 0,
    "1.3125": -3,
    "1.34375": 0,
    "1.375": 7,
    "1.40625": 0,
    "1.4375": 3,
    "1.46875": 0,
    "1.5": 25,
    "1.53125": 0,
    "1.5625": 0.8786796564403576,
    "1.59375": 0.2928932188134523,
    "1.625": 0,
    "1.65625": 1,
    "1.6875": 5.121320343559643,
    "1.71875": -1.7071067811865475,
    "1.75": -5,
    "1.78125": 0,
    "1.8125": -1,
    "1.84375": 0,
    "1.875": 8,
    "1.90625": 0,
    "1.9375": 2,
    "1.96875": 0
}

我有两个问题:

  1. 为什么0.09375频率的振幅不是最大的?
  2. 为什么仅含正值的折线图会返回负振幅?

问题解答

1. 0.09375频率振幅不是最大的原因

你的代码存在两个核心错误:

  • 错误解析FFT输出:fft.js的realTransform返回的是复数数组,格式为[实部0, 虚部0, 实部1, 虚部1, ...],你直接将数组元素当作振幅是完全错误的。正确的振幅计算应该是对每个频率分量的实部和虚部取模,即Math.sqrt(实部² + 虚部²)。
  • 数据实际频率与预期不符:你输入的序列是[1,2,3,4,5,5,4,3,2,1]重复三次后追加2,3,这个序列的主要周期是10个采样点(对应0.1Hz),而且末尾的额外数据破坏了完美周期性,实际FFT结果中更强的频率是和数据真实重复模式匹配的分量,并非你预期的0.09375Hz。

2. 仅含正值的折线图出现负振幅的原因

你看到的"负振幅"其实是复数结果的实部或虚部值,并非真正的振幅。FFT将信号分解为正弦/余弦分量,这些分量的系数可以是正或负,代表相位偏移,而振幅是分量的模值,永远是非负的。你代码中取的frequencySpectrum[j]只是某个分量的实部或虚部,自然可能为负,但真正的振幅需要通过实部和虚部的平方和开根号计算,结果一定是正数。

另外,对于实输入信号,FFT结果存在共轭对称性,高于采样率/2的频率其实是低于该值的频率的镜像,实际分析时只需关注0到采样率/2范围内的分量即可。


内容的提问来源于stack exchange,提问作者gal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 12:37:03