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

如何获取1Hz至32kHz对数频率间隔的频谱图数值数组?

获取对数频率缩放的STFT幅度数组解决方案

核心思路

scipy.signal.stft生成的是线性间隔的频率轴,要得到1Hz~32kHz的对数间隔幅度数组,需先计算线性STFT的幅度谱,再通过插值将线性频率上的幅度值映射到自定义的对数频率轴上。

实现步骤与代码示例

1. 基础STFT计算(保留原有代码)

import librosa
import scipy
import numpy as np
from scipy.interpolate import interp1d

# 加载音频
sample, samplerate = librosa.load('sound.wav', sr=64000)
# 计算线性频率的STFT
f, t, Zxx = scipy.signal.stft(
    sample, 
    fs=samplerate, 
    window='hamming', 
    nperseg=512, 
    noverlap=256
)
# 提取幅度谱
mag = np.abs(Zxx)

2. 生成对数频率轴

用np.logspace生成1Hz到32kHz的对数间隔频率点,可指定点数(建议和原线性频率点数一致,方便后续对比):

# 生成对数频率轴:1Hz到32kHz,点数与原线性频率轴相同
log_f = np.logspace(
    np.log10(1),       # 起始频率的对数(1Hz)
    np.log10(32000),   # 结束频率的对数(奈奎斯特频率)
    num=len(f)         # 对数频率点的数量
)

3. 插值映射幅度到对数频率轴

有两种常用插值方式,按需选择:

方式一:线性插值(快速高效)

用np.interp对每个时间帧的幅度做线性插值:

log_mag = np.zeros((len(log_f), len(t)))
for idx in range(len(t)):
    # 将当前时间帧的线性幅度插值到对数频率轴上
    log_mag[:, idx] = np.interp(log_f, f, mag[:, idx])
方式二:高阶插值(结果更平滑)

用scipy.interpolate.interp1d实现三次插值,无需循环,效率更高:

# 创建插值函数,指定对频率轴(axis=0)做三次插值
interp_func = interp1d(f, mag, axis=0, kind='cubic', fill_value="extrapolate")
# 得到对数频率对应的幅度数组
log_mag = interp_func(log_f)

4. 可选优化:过滤无效频率范围

原STFT的频率轴包含0Hz,而我们的目标是1Hz起,可先过滤掉1Hz以下的频率点,避免外推误差:

# 过滤出1Hz及以上的频率点
valid_mask = f >= 1
f_valid = f[valid_mask]
mag_valid = mag[valid_mask, :]

# 重新生成对应点数的对数频率轴
log_f = np.logspace(np.log10(1), np.log10(32000), num=len(f_valid))

# 插值得到优化后的对数幅度数组
interp_func = interp1d(f_valid, mag_valid, axis=0, kind='cubic')
log_mag = interp_func(log_f)

最终结果说明

  • log_f:1Hz到32kHz的对数间隔频率数组
  • log_mag:对应对数频率轴的二维幅度数组,维度为(对数频率点数, 时间帧数量),可直接用于后续分析或可视化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 21:30:54