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

如何获取音频音量波形图中音符的起止索引?

音频音符按下时机(起止索引)识别方案优化

问题背景

我正在开发一个程序,用于识别音符的按下时机。现有一段包含4遍不同节奏、力度和八度C大调音阶的.wav音频文件,已通过以下代码获取音频的音量数据:

from scipy.io import wavfile

def get_volume(file):
    sr, data = wavfile.read(file)

    if data.ndim > 1:
        data = data[:, 0]

    return data

volumes = get_volume("FILE")

该输出的相关信息如下:

Max: 27851
Min: -25664
Mean: -0.7569383391943734
A Sample from the array: [ -7987  -8615  -8983  -9107  -9019  -8750  -8324  -7752  -7033  -6156
  -5115  -3920  -2610  -1245    106   1377   2520   3515   4364   5077
   5659   6113   6441   6639   6708   6662   6518   6288   5962   5525
   4963   4265   3420   2418   1264    -27  -1429  -2901  -4388  -5814
  -7101  -8186  -9028  -9614  -9955 -10077 -10012  -9785  -9401  -8846]

绘制音量数组的波形图后,需要获取图中每个音符的起止索引,但现有方法存在缺陷。

现有尝试及问题

  • 批量计算平均梯度:将音量数组分批次计算平均梯度判断音符起止,但批量大小难以平衡——过小会识别无效小峰值,过大则错过准确起止点。
  • 静音检测:用pydub的silence模块检测非静音区域,效果尚可,但无法准确识别音符未完全静音就切换的情况(如第二、第四遍音阶)。
  • FFT尝试:尝试通过FFT获取频率数据,但未理解其应用逻辑,无法有效利用。

优化方案建议

1. 音量+频率双维度检测

单靠音量无法处理连音切换,结合频率特征是核心解决思路:

  • 分帧预处理:对原始音频分帧(每帧20-50ms,比如44100采样率下每帧882-2205个样本),添加50%重叠帧,避免边界信息丢失。
  • 提取帧特征:
    • 用**均方根(RMS)**代替原始样本值计算每帧音量,更贴合实际响度感知;
    • 对每帧做FFT后提取主频率(能量最高的频率成分),或用梅尔频率倒谱系数(MFCC)简化特征;也可以直接提取基频(F0),对应音符的实际音高。
  • 起止判断逻辑:
    • 新音符起始:当帧RMS超过静音阈值,且当前帧主频率与前一帧主频率差异超过设定阈值(比如半音对应的频率差),标记为起始点;
    • 音符结束:当帧RMS持续下降到自适应阈值以下,或主频率即将切换时,标记为结束点。

2. 自适应阈值改进静音检测

针对pydub无法处理连音的问题,修改阈值逻辑:

  • 放弃全局静音阈值,采用自适应阈值:计算前N帧的平均音量,将当前帧音量与该平均值的比值作为判断依据(比如比值低于0.2视为音符结束过渡阶段);
  • 结合能量变化率:当连续几帧能量下降速率超过设定值,即使未到全局静音阈值,也判定当前音符结束,同时监测下一帧的能量上升和频率变化识别新音符。

3. 用 librosa 简化特征提取

librosa是专业音频分析库,能快速处理分帧、RMS、基频提取:

import librosa

# 加载音频,保留原始采样率
y, sr = librosa.load("your_file.wav", sr=None)

# 计算每帧RMS音量(frame_length和hop_length可根据需求调整)
rms = librosa.feature.rms(y=y, frame_length=2048, hop_length=512)
# 提取基频F0,限定C大调音阶的频率范围
f0, voiced_flag, voiced_probs = librosa.pyin(y, fmin=librosa.note_to_hz('C2'), fmax=librosa.note_to_hz('C7'))

# 基于rms和f0的变化判断音符起止:
# 遍历帧数据,当f0从无到有/切换到新频率,且rms超过阈值时标记起始;
# 当f0消失或rms持续下降到阈值以下时标记结束

通过f0(基频)的变化可精准区分不同音符,即使音量未完全降到静音水平,只要基频切换,就能识别新音符开始。

4. 后处理修正结果

识别出初步起止点后,做以下优化:

  • 过滤过短片段(比如持续时间低于50ms的,视为噪声);
  • 合并连续同频率片段(中间短暂频率波动但整体属于同一音符的情况);
  • 结合C大调音阶的音高范围,过滤无效频率识别结果,减少误判。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:05:22