【发布时间】:2019-11-02 21:21:16
【问题描述】:
aubio 是否有办法检测一段音频中缺少音调元素的部分——仅节奏?我测试了一首开始时有 16 秒节奏的音乐,但所有的 aubiopitch 和 abionotes 算法似乎都在节奏部分检测到了音调。是否可以通过某种方式对其进行调整以区分音调和非音调开始?或者有没有相关的库可以做到这一点?
【问题讨论】:
标签: python signal-processing pitch-tracking aubio
aubio 是否有办法检测一段音频中缺少音调元素的部分——仅节奏?我测试了一首开始时有 16 秒节奏的音乐,但所有的 aubiopitch 和 abionotes 算法似乎都在节奏部分检测到了音调。是否可以通过某种方式对其进行调整以区分音调和非音调开始?或者有没有相关的库可以做到这一点?
【问题讨论】:
标签: python signal-processing pitch-tracking aubio
过去几天一直很忙 - 但今天开始研究这个......
我想这需要一段时间才能完善,但我想我会给你一些想法和一些我已经开始编写的代码来解决这个问题!
首先,伪代码是设计初始方法的好方法。
1/使用import matplotlib.pyplot as plt对音频进行频谱分析,绘制各种fft和音频信号。
2/ import numpy as np 用于基本的类数组结构处理。
(我知道这不仅仅是伪代码,但是嘿 :-)
3/ plt.specgram 为您的音频创建频谱图。除了它创建的图像(可用于开始手动解构您的音频文件)之外,它还返回 4 个结构。
例如
ffts,freqs,times,img = plt.specgram(signal,Fs=44100)
ffts 是一个二维数组,其中列是时间段(行)的ffts(快速傅立叶变换)。
plain vanilla specgram 分析 256 个样本长的时间段,每次向前步进 128 个样本。
这会以相当快的速度提供分辨率非常低的频率阵列。
由于音符在以或多或少 10 赫兹播放时合并为一个声音,我决定使用specgram 选项将音频分成 4096 个样本长度(大约 10 赫兹),每 2048 个样本(即 20秒)。
这提供了不错的频率分辨率,相隔 20 秒的时间部分比人们感知单个音符的速度要快。
这意味着调用specgram如下:
plt.specgram(signal,Fs=44100,NFFT=4096,noverlap=2048,mode='magnitude')
(注意模式 - 这似乎给了我 0 - 0.1 之间的幅度:我有一个问题,fft 没有给我与音频信号相同比例的幅度(你可能已经看到我发布的问题) . 但是我们在这里...
4/ 接下来我决定去除返回的ffts 中的噪音。这意味着我们可以专注于幅度合适的freqs,并将ffts 中始终存在的噪声归零(根据我的经验)。
这是我的功能:
def gate(signal,minAmplitude):
return np.array([int((((a-minAmplitude)+abs(a-minAmplitude))/2) > 0) * a for a in signal])
看起来有点疯狂——我敢肯定一个合适的数学家可以想出更有效的东西——但这是我能发明的最好的东西。它将幅度小于minAmplitude 的任何频率归零。
这是从plt.specgram 返回的ffts 调用它的相关代码,如下所示,我的函数涉及更多,因为它是类的一部分,并且具有它引用的其他函数 - 但这应该足够了:
def fft_noise_gate(minAmplitude=0.001,check=True):
'''
zero the amplitudes of frequencies
with amplitudes below minAmplitude
across self.ffts
check - plot middle fft just because!
'''
nffts = ffts.shape[1]
gated_ffts = []
for f in range(nffts):
fft = ffts[...,f]
# Anyone got a more efficient noise gate formula? Best I could think up!
fft_gated = gate(fft,minAmplitude)
gated_ffts.append(fft_gated)
ffts = np.array(gated_ffts)
if check:
# plot middle fft just to see!
plt.plot(ffts[int(nffts/2)])
plt.show(block=False)
return ffts
这应该给你一个开始
我的策略是:
1/ 找到峰值(即任何声音的开始)然后 2/ 寻找同时上升和下降的频率范围(即组成一个声音)。
和
3/ 将它们区分为单独的乐器(更具体地说是声源),并绘制它们的时间和幅度以创建您的分析(乐谱)。
希望你玩得开心 - 我知道我是。
正如我所说的任何想法......
问候
托尼
【讨论】:
使用频谱分析仪检测振幅较大的部分。如果您进行编程 - 您可以获取每个部分并对存在的频率(和幅度)进行平均,以让您了解创建该幅度峰值所涉及的仪器。
希望对您有所帮助 - 如果您使用的是 python,我可以为您提供一些如何编程的指导!?
问候
托尼
【讨论】: