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

如何使用numpy.fft.fft从100个样本中提取LFO信号频率?

从100个音频样本中提取7Hz LFO频率的NumPy实现方案

核心前提说明

100个样本对应的时长约为 100/11025 ≈ 0.009秒,而7Hz信号的周期约为 1/7 ≈ 0.14秒,样本量不足以覆盖一个完整的LFO周期。直接使用FFT会因频率分辨率不足(11025/100 = 110.25Hz,远大于7Hz)无法精准检测,因此自相关法是更可靠的选择。


步骤1:样本数据预处理

将原始16位有符号样本转换为NumPy数组,并归一化到[-1, 1]范围,避免数值运算溢出:

import numpy as np

# 假设samples是包含100个16位有符号整数的输入列表
samples = [你的样本数据]
# 转换为16位有符号数组
x = np.array(samples, dtype=np.int16)
# 归一化到[-1, 1]
x_normalized = x / 32768.0

步骤2:计算自相关函数

自相关函数能捕捉信号的重复周期特征,通过计算信号与自身延迟版本的相关性,找到周期对应的延迟样本数:

# 计算完整自相关序列
autocorr = np.correlate(x_normalized, x_normalized, mode='full')
# 截取正延迟部分(自相关的后半段)
autocorr = autocorr[len(autocorr)//2:]

步骤3:定位周期峰值并计算频率

自相关序列中,跳过延迟为0的峰值(自身相关性最强),第一个有效峰值对应的延迟样本数即为LFO的周期长度,进而计算频率:

# 寻找自相关序列的峰值点(二阶导数由正转负的位置)
peak_indices = np.where(np.diff(np.sign(np.diff(autocorr))) == -2)[0] + 1

if len(peak_indices) == 0:
    print("未检测到有效LFO周期,可能样本量不足或信号被干扰")
else:
    # 取第一个有效峰值对应的周期样本数
    period_samples = peak_indices[0]
    # 频率 = 采样率 / 周期样本数
    detected_frequency = 11025 / period_samples
    # 四舍五入到整数,匹配目标7Hz
    detected_frequency_rounded = round(detected_frequency)
    print(f"检测到的LFO频率:{detected_frequency_rounded}Hz")

补充:FFT方法的局限性与尝试

若必须使用FFT,可通过零填充提高频率分辨率,但在样本不足一个周期时误差较大:

# 零填充到1024点,提升频率分辨率
n_fft = 1024
fft_vals = np.fft.fft(x_normalized, n=n_fft)
fft_amps = np.abs(fft_vals)
# 生成频率轴
freq_axis = np.fft.fftfreq(n_fft, 1/11025)
# 筛选正频率部分
positive_mask = freq_axis >= 0
freq_pos = freq_axis[positive_mask]
amps_pos = fft_amps[positive_mask]
# 找到幅度最大的频率点
max_amp_idx = np.argmax(amps_pos)
detected_freq_fft = freq_pos[max_amp_idx]
print(f"FFT检测频率(近似):{round(detected_freq_fft)}Hz")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:50:25