把写歌用的鼓组采样按音色归堆,我用一个笨脚本干完了
我的动机库里有 1200 多个鼓组采样,来自几个不同时期下载的免费包和几套买的。文件名基本没有规律,有的写 kick_01.wav,有的写 001.wav,还有一堆带空格和中文的。想找“一个偏闷的底鼓”时只能一个个点开听,这件事拖了快两年。
上个月我写了个脚本,不再试图理解文件名,改成按声音本身归堆。环境是 macOS,Python 3.11,依赖 librosa 和 soundfile,跑 1200 个文件大概六七分钟。核心就三步:读音频、算特征、聚类。
import librosa, numpy as np, soundfile as sf
from sklearn.cluster import KMeans
def feat(p):
y, sr = librosa.load(p, sr=22050, mono=True)
y = y[:sr] # 只取前 1 秒
cent = librosa.feature.spectral_centroid(y=y, sr=sr).mean()
roll = librosa.feature.spectral_rolloff(y=y, sr=sr, roll_percent=0.85).mean()
zcr = librosa.feature.zero_crossing_rate(y).mean()
dur = librosa.get_duration(y=y, sr=sr)
return [cent, roll, zcr, dur]
X = np.array([feat(p) for p in paths])
X = (X - X.mean(0)) / X.std(0)
label = KMeans(n_clusters=12, n_init=10).fit_predict(X)
然后按 label 建子文件夹,把文件复制进去。我发现的第一个问题是 dur 这一维把底鼓和军鼓分开了,但把镲片和长音效混在一起,因为 1 秒截断让长音效的时长全一样。砍掉 dur 之后,聚类结果贴合“音色”本身,代价是军鼓和短音效会串。
为什么用谱质心加滚降:这两个数字大致就是“亮度”,底鼓偏暗、镲片偏亮,比 MFCC 直观,出了问题我能看懂。代价是它分不出“同一个鼓不同力度”和“两个不同的鼓”,因为力度主要影响能量,不影响亮度。我接受这个代价,因为我要的是找东西快,不是做分类器。
哪里会失效:静音几乎的空文件会算出离谱的质心,得先过滤掉 RMS 低于阈值的;48kHz 和 44.1kHz 混着放没问题,但别把立体声和单声道混在一起算 zcr,我第一版就栽在这,同一组底鼓被劈成两堆。还有一点点:KMeans 的簇数是我手调的,12 这个数字只是对我这批文件合适,换一批包就得重新试。
现在我的流程是:要底鼓就去标着“暗”的那几个文件夹里翻,翻不到再全库搜。它没让我变得更有创造力,只是把找声音的时间从二十分钟压到两分钟。
你们归堆采样时是按文件名、按来源包,还是也按声音特征?有没有人试过用手动打标签配合这个,我觉得纯自动的簇名还是太抽象。


0 条评论
还没有评论,写下第一条。