使用 JavaScript 进行 FFT 分析:如何找到特定频率?

Posted

技术标签:

【中文标题】使用 JavaScript 进行 FFT 分析:如何找到特定频率?【英文标题】:FFT analysis with JavaScript: How to find a specific frequency? 【发布时间】:2015-09-25 12:43:00 【问题描述】:

我有以下问题: 我使用 javascript 和 FFT 分析音频数据。我已经可以将 FFT 数据写入数组了:

audioCtx = new AudioContext();
analyser = audioCtx.createAnalyser();
source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
analyser.fftSize = 64;

var frequencyData = new Uint8Array(analyser.frequencyBinCount);

每次我想获得新数据时,我都会调用:

analyser.getByteFrequencyData(frequencyData);

变量“audio”是一个用 html 定义的 mp3 文件:

<audio id="audio" src="test.mp3"></audio>

到目前为止一切顺利。

我现在的问题是我想检查当前数组“frequencyData”是否包含特定频率。例如:我在 mp3 文件中的某处放置了一个 1000 Hz 的信号,并希望在 mp3 文件的这部分当前位于数组“frequencyData”中时得到通知。

第一步,当 mp3 文件的重要部分仅包含 1000 Hz 信号时,它将帮助我解决问题。在第二步中,如果有音乐覆盖,我还想找到该部分。

【问题讨论】:

【参考方案1】:

frequencyData 是一个振幅数组,数组的每个元素基本上代表一个频率范围。每个范围的大小由采样率除以 FFT 点数定义,在您的情况下为 64。因此,如果您的采样率为 48000 并且您的 FFT 大小为 64,那么每个元素的范围为 48000/64 = 750 Hz。这意味着frequencyData[0] 是频率 0Hz-750Hz,frequencyData[1] 是 750Hz-1500Hz,依此类推。在此示例中,1kHz 音调的存在将被视为第一个 bin 中的峰值。此外,对于如此小的 FFT,您可能会注意到分辨率非常粗糙。如果您想提高频率分辨率,则需要进行更大的 FFT。

【讨论】:

我认为这只是部分正确!我发现如果 FFT 大小是 64,你会得到 32 个 bin。所以数组是大小的一半。从这个半尺寸来看,只有前半部分是相关的,因为我们听不到超过 20000 Hz 的频率。我唯一仍然想念的是数组包含什么样的数据。我知道它包含从 0 到 255 的数字。但是这些数字是否指定响度? 响度与数组中的另一个数字相比,当然不是绝对响度! 如果您的库返回的频率数据仅为您指定的 FFT 大小的一半,那么您的 FFT 库返回的频率数据是 0Hz 和 Fs/2 之间的频率数据,其中 Fs 是采样如果 FFT 函数的输入是真实的(例如音频的情况),则可以从 0Hz 到 Fs/2 区域中的频率数据重建完整的频谱,因此不需要额外的样本。注意正如 jaket 所说,频率区间之间的间距仍然是 Fs/(FFT Size)。 从 FFT 方法得到的数字代表音频中特定频率的幅度,而不是真正的响度。严格来说,响度是一个感知量,不同的频率对耳朵的感知不同,因此在正确分析组件的响度之前,您已经从标准频率标度转移到诸如 MEL 标度之类的感知标度。不过,实际上,您可以假设幅度来表示不同频率的响度,并将其用于许多应用例如音频可视化。

以上是关于使用 JavaScript 进行 FFT 分析:如何找到特定频率?的主要内容,如果未能解决你的问题,请参考以下文章

如何在matlab的powergui里面进行fft分析

关于用FFT分析信号频谱的问题

matlab中powergui中的fft分析怎么用

使用 FFT 进行频谱分析,基频推导

使用 FFT 进行频谱分析

如何用一个n点fft求2n点实数