我正在使用this算法来检测音高 this音频文件。正如你所听到的那样,它是在吉他上演奏的E2音符,背景中有一点噪音。
我正在使用上面链接的算法:
y, sr = librosa.load(filename, sr=40000)
pitches, magnitudes = librosa.core.piptrack(y=y, sr=sr, fmin=75, fmax=1600)
np.set_printoptions(threshold=np.nan)
print pitches[np.nonzero(pitches)]
因此,我在fmin
和fmax
之间获得了几乎所有可能的频率。我如何处理piptrack
方法的输出以发现时间范围的基本频率?
更新
我仍然不确定这些2D数组代表什么。让我们说我想知道第5帧中82Hz的强度。我可以使用STFT函数来做到这一点,它只返回一个2D矩阵(用于绘制频谱图)。
然而,piptrack
做了一些额外的事情,这可能是有用的,我真的不明白什么。 pitches[f, t] contains instantaneous frequency at bin f, time t
。这是否意味着,如果我想在时间帧t找到最大频率,我必须:
magnitudes[][t]
数组,找到最大值的bin
大小。 f
。 pitches[b][t]
以查找属于该垃圾箱的频率?答案 0 :(得分:6)
音高检测是一个棘手的话题,通常是违反直觉的。我对于为这个特定功能记录源代码的方式并不狂热 - 这似乎是开发人员混淆了一个'用'音调'
当在吉他或钢琴上制作单音(a'音高')时,我们听到的不仅仅是声音振动的一个频率,而是多个音频的组合在不同的数学相关频率上发生的声音振动,称为谐波。典型的音调跟踪技术包括搜索FFT的结果,以获得对应于谐波的预期频率的某些箱中的幅度。例如,如果我们按下钢琴上的中间C键,复合波的各个频率将以261.6 Hz开始作为基频,523 Hz将是2次谐波,785 Hz将是3次谐波,1046 Hz将是第四谐波等。后面的谐波是基频的整数倍,261.6 Hz(例如:2 x 261.6 = 523,3 x 261.6 = 785,4 x 261.6 = 1046)。然而,谐波所处的频率是对数间隔的,但FFT使用线性间隔。通常,在较低频率下,FFT的垂直间距不够充分。
出于这个原因,当我编写一个音高检测应用程序(PitchScope Player)时,我选择创建一个对数间隔的DFT,而不是FFT,因此我可以专注于对音乐感兴趣的精确频率(参见附图)我的自定义DFT从3秒的吉他独奏)。如果你认真考虑进行音高检测,你应该考虑更多地阅读这个主题,查看其他示例代码(我的链接如下),并考虑编写自己的函数来测量频率。
https://en.wikipedia.org/wiki/Transcription_(music)#Pitch_detection
答案 1 :(得分:4)
在某个帧t
选择音高的方法很简单:
def detect_pitch(y, sr, t):
index = magnitudes[:, t].argmax()
pitch = pitches[index, t]
return pitch
首先通过查看magnitudes
数组获取最强频率的bin,然后在pitches[index, t]
找到音高。