我使用Librosa转录单声道吉他音频信号。切片音频信号检测音调
我认为,根据发病时间对信号进行“切片”是一个很好的开始,以便在正确的时间检测音符变化。
Librosa提供了一个function,检测发病时间之前的局部极小值。我检查了这些时机,他们是正确的。
这里是原始信号的波形和最小值的时间。
[ 266240 552960 840704 1161728 1427968 1735680 1994752]
演奏的旋律是E4,F4,F#4 ...,B4。
因此,理想的结果应该是:330Hz,350Hz,...,493Hz(大约)。
如您所见,minima
阵列中的时间表示音符播放前的时间。
然而,在一个切片信号(10-12秒,每片只有一个音符),我的频率检测方法有非常差的结果。我很困惑,因为我看不到任何错误在我的代码:
y, sr = librosa.load(filename, sr=40000)
onset_frames = librosa.onset.onset_detect(y=y, sr=sr)
oenv = librosa.onset.onset_strength(y=y, sr=sr)
onset_bt = librosa.onset.onset_backtrack(onset_frames, oenv)
# Converting those times from frames to samples.
new_onset_bt = librosa.frames_to_samples(onset_bt)
slices = np.split(y, new_onset_bt[1:])
for i in range(0, len(slices)):
print freq_from_hps(slices[i], 40000)
print freq_from_autocorr(slices[i], 40000)
print freq_from_fft(slices[i], 40000)
凡freq_from
功能直接取自here。
我会认为这只是从方法的精度差,但我得到了一些疯狂的结果。具体而言,freq_from_hps
返回:
1.33818658287
1.2078047577
0.802142642257
0.531096911977
0.987532329094
0.559638134414
0.953497587952
0.628980979055
这些值应该是8个对应切片的8个间距(以Hz!)。
freq_from_fft
收益相似的价值观,而freq_from_autocorr
返回一些更 “正常” 值,但也有一些随机值10000Hz附近:
242.748000585
10650.0394232
275.25299319
145.552578747
154.725859019
7828.70876515
174.180627765
183.731497068
这是从整个信号频谱图:
正如您所见,切片已正确完成。但是有几个问题。首先,谱图中存在一个八度音阶问题。我期待着一些问题。然而,我从上面提到的3种方法得到的结果只是非常奇怪。
这是我的信号处理理解或我的代码问题?