如何使用librosa peak picking得到的onset结果提取60ms打击类音频片段
操作步骤
1. 调整librosa.util.peak_pick参数适配60ms打击信号
首先明确librosa.util.peak_pick的参数定义及转换逻辑:
函数语法为librosa.util.peak_pick(x, pre_max, post_max, pre_avg, post_avg, delta, wait),其中所有帧长相关参数的单位都是「onset强度包络的帧」,默认配置下onset强度每帧时长约为23.2ms(sr=22050,hop_length=512)。
你当前使用的参数(10,10,10,10,2,60)中核心问题是wait=60,对应强制间隔约1.4s,会导致大量相邻的打击信号被漏检,调整方向如下:
pre_max=2、post_max=2:打击信号 onset 陡度高,仅需前后2帧范围内找峰值即可,避免误判pre_avg=3、post_avg=3:前后3帧计算平均强度,适配短打击信号的特征delta=0.5:峰值阈值,比前后平均高0.5即可判定为有效峰值,漏检多就调小,误检多就调大wait=4:两个峰值最小间隔约90ms,略长于你的60ms信号时长,避免同一个信号被多次拾取
调整后peak_pick代码改为:
onset_frames = librosa.util.peak_pick(o_env, pre_max=2, post_max=2, pre_avg=3, post_avg=3, delta=0.5, wait=4)
运行后看可视化结果里的红色虚线标记数量,如果不足28就继续降低delta、减小wait,如果超过28就升高delta、增大wait,直到数量匹配。
2. 基于校正后的onset提取60ms音频片段
不要重复加载音频文件,直接用已经读入内存的x切片提取,精度更高速度更快,完整代码如下:
import librosa import numpy as np import soundfile as sf # 加载音频、计算onset强度、拾取峰值(参数已经按上述调整) x, sr = librosa.load("C:/data/test.wav", sr=None) # 加sr=None保留原采样率 o_env = librosa.onset.onset_strength(y=x, sr=sr) onset_frames = librosa.util.peak_pick(o_env, pre_max=2, post_max=2, pre_avg=3, post_avg=3, delta=0.5, wait=4) # 把onset帧转成采样点索引 onset_samples = librosa.frames_to_samples(onset_frames, hop_length=512) # 计算60ms对应的采样点数量 extract_len = int(sr * 0.06) # 遍历提取片段 for i, onset_samp in enumerate(onset_samples, start=1): # 避免超出音频长度 end_samp = min(onset_samp + extract_len, len(x)) current_clip = x[onset_samp:end_samp] sf.write(f'./clicks/clicks{i}.wav', current_clip, sr) print(f"共提取{len(onset_samples)}个片段")
内容的提问来源于stack exchange,提问作者VGF
相关产品推荐
相关产品推荐

