15

我正在使用这个算法来检测 这个音频文件的音高。正如你所听到的,这是用吉他演奏的 E2 音符,背景中有一点噪音。

我使用 STFT 生成了这个频谱图:频谱图

我正在使用上面链接的算法,如下所示:

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方法的输出有什么关系来发现时间框架的基频?

更新

不过,我仍然不确定那些二维数组代表什么。假设我想知道第 5 帧中 82Hz 的强度有多大。我可以使用 STFT 函数来做到这一点,该函数只返回一个 2D 矩阵(用于绘制频谱图)。

但是,piptrack做了一些其他可能有用的事情,我真的不明白是什么。pitches[f, t] contains instantaneous frequency at bin f, time t. 这是否意味着,如果我想在时间帧 t 找到最大频率,我必须:

  1. 转到magnitudes[][t]数组,找到最大量级的 bin。
  2. 将 bin 分配给一个变量f
  3. Findpitches[b][t]找到属于该 bin 的频率?
4

2 回答 2

11

音高检测是一个棘手的话题,通常是违反直觉的。对于这个特定功能的源代码记录方式,我并不疯狂——开发人员似乎将“谐波”与“音高”混淆了。

当一个音符(“音高”)是在吉他或钢琴上制作的,我们听到的不仅仅是声音振动的一个频率,而是发生在不同数学相关频率上的多个声音振动的组合,称为谐波。典型的音调跟踪技术包括在 FFT 的结果中搜索与预期的谐波频率相对应的某些 bin 中的幅度。例如,如果我们按下钢琴上的中间 C 键,复合谐波的各个频率将从 261.6 Hz 作为基频开始,523 Hz 将是 2 次谐波,785 Hz 将是 3 次谐波,1046 Hz 将是 4 次谐波,等等。后面的谐波是基频 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

https://github.com/CreativeDetectors/PitchScope_Player

在此处输入图像描述

于 2017-05-11T19:55:48.847 回答
7

事实证明,在某个帧选择音高的方法t很简单:

def detect_pitch(y, sr, t):
  index = magnitudes[:, t].argmax()
  pitch = pitches[index, t]

  return pitch

首先通过查看magnitudes阵列获得最强频率的 bin,然后在 处找到音高pitches[index, t]

于 2017-05-16T19:14:45.593 回答