我正在使用Librosa库进行音高和起始检测。具体来说,我正在使用onset_detect
and piptrack
。
这是我的代码:
def detect_pitch(y, sr, onset_offset=5, fmin=75, fmax=1400):
y = highpass_filter(y, sr)
onset_frames = librosa.onset.onset_detect(y=y, sr=sr)
pitches, magnitudes = librosa.piptrack(y=y, sr=sr, fmin=fmin, fmax=fmax)
notes = []
for i in range(0, len(onset_frames)):
onset = onset_frames[i] + onset_offset
index = magnitudes[:, onset].argmax()
pitch = pitches[index, onset]
if (pitch != 0):
notes.append(librosa.hz_to_note(pitch))
return notes
def highpass_filter(y, sr):
filter_stop_freq = 70 # Hz
filter_pass_freq = 100 # Hz
filter_order = 1001
# High-pass filter
nyquist_rate = sr / 2.
desired = (0, 0, 1, 1)
bands = (0, filter_stop_freq, filter_pass_freq, nyquist_rate)
filter_coefs = signal.firls(filter_order, bands, desired, nyq=nyquist_rate)
# Apply high-pass filter
filtered_audio = signal.filtfilt(filter_coefs, [1], y)
return filtered_audio
在录音棚中录制的吉他音频样本上运行此程序时,因此样本没有噪音(像这样),我在这两个功能中都得到了非常好的结果。开始时间是正确的,频率几乎总是正确的(有时会出现一些八度音阶错误)。
然而,当我尝试用我便宜的麦克风录制自己的吉他声音时,出现了一个大问题。我得到带有噪音的音频文件,例如this。该onset_detect
算法感到困惑,并认为噪声包含起始时间。因此,我得到了非常糟糕的结果。即使我的音频文件由一个音符组成,我也会有很多次发作。
这是两个波形。第一个是在录音室录制的 B3 音符的吉他样本,而第二个是我录制的 E2 音符。
第一个的结果是正确的 B3(检测到一个起始时间)。第二个的结果是一个包含7 个元素的数组,这意味着检测到 7 个起始时间,而不是 1 个!其中一个元素是正确的开始时间,其他元素只是噪声部分的随机峰值。
另一个例子是这个包含音符 B3、C4、D4、E4 的音频文件:
如您所见,噪声很清晰,我的高通滤波器没有帮助(这是应用滤波器后的波形)。
我认为这是一个噪音问题,因为这些文件之间的区别就在那里。如果是,我能做些什么来减少它?我尝试过使用高通滤波器,但没有任何变化。