Librosa 音调跟踪 - STFT
Librosa pitch tracking - STFT
我正在使用 this 算法来检测
this 音频文件。正如您所听到的,这是在吉他上弹奏的 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 函数来做到这一点,它只是 returns 一个二维矩阵(用于绘制频谱图)。
但是,piptrack
做了一些额外的事情,这可能很有用,但我不太明白是什么。 pitches[f, t] contains instantaneous frequency at bin f, time t
。这是否意味着,如果我想在时间帧 t 找到最大频率,我必须:
- 转到
magnitudes[][t]
数组,找到最大的bin
震级。
- 将 bin 分配给变量
f
。
- 查找
pitches[b][t]
以查找属于该 bin 的频率?
音高检测是一个棘手的话题,而且通常是违反直觉的。我对这个特定功能的源代码记录方式并不感兴趣——开发人员似乎混淆了 'harmonic' 和 'pitch'。
当在吉他或钢琴上发出单音符('pitch')时,我们听到的不仅仅是一种声音振动频率,而是一种复合以不同的数学相关频率发生的多种声音振动的集合,称为谐波。典型的音调跟踪技术包括在 FFT 结果中搜索与预期的谐波频率相对应的特定区间中的幅度。例如,如果我们按下钢琴上的中央 C 键,复合谐波的各个频率将从 261.6 Hz 开始作为基频,523 Hz 将是二次谐波,785 Hz 将是三次谐波,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,这样我就可以专注于音乐感兴趣的精确频率(见附件来自 3 秒吉他独奏的自定义 DFT 图)。如果你认真地追求音高检测,你应该考虑多读读这个主题,看看其他示例代码(我的链接在下面),并考虑编写你自己的函数来测量频率。
https://en.wikipedia.org/wiki/Transcription_(music)#Pitch_detection
https://github.com/CreativeDetectors/PitchScope_Player
原来在某一帧t
选择音高的方法很简单:
def detect_pitch(y, sr, t):
index = magnitudes[:, t].argmax()
pitch = pitches[index, t]
return pitch
首先通过查看magnitudes
数组得到最强频率的bin,然后找到pitches[index, t]
处的音高。
我正在使用 this 算法来检测 this 音频文件。正如您所听到的,这是在吉他上弹奏的 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 函数来做到这一点,它只是 returns 一个二维矩阵(用于绘制频谱图)。
但是,piptrack
做了一些额外的事情,这可能很有用,但我不太明白是什么。 pitches[f, t] contains instantaneous frequency at bin f, time t
。这是否意味着,如果我想在时间帧 t 找到最大频率,我必须:
- 转到
magnitudes[][t]
数组,找到最大的bin 震级。 - 将 bin 分配给变量
f
。 - 查找
pitches[b][t]
以查找属于该 bin 的频率?
音高检测是一个棘手的话题,而且通常是违反直觉的。我对这个特定功能的源代码记录方式并不感兴趣——开发人员似乎混淆了 'harmonic' 和 'pitch'。
当在吉他或钢琴上发出单音符('pitch')时,我们听到的不仅仅是一种声音振动频率,而是一种复合以不同的数学相关频率发生的多种声音振动的集合,称为谐波。典型的音调跟踪技术包括在 FFT 结果中搜索与预期的谐波频率相对应的特定区间中的幅度。例如,如果我们按下钢琴上的中央 C 键,复合谐波的各个频率将从 261.6 Hz 开始作为基频,523 Hz 将是二次谐波,785 Hz 将是三次谐波,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,这样我就可以专注于音乐感兴趣的精确频率(见附件来自 3 秒吉他独奏的自定义 DFT 图)。如果你认真地追求音高检测,你应该考虑多读读这个主题,看看其他示例代码(我的链接在下面),并考虑编写你自己的函数来测量频率。
https://en.wikipedia.org/wiki/Transcription_(music)#Pitch_detection
https://github.com/CreativeDetectors/PitchScope_Player
原来在某一帧t
选择音高的方法很简单:
def detect_pitch(y, sr, t):
index = magnitudes[:, t].argmax()
pitch = pitches[index, t]
return pitch
首先通过查看magnitudes
数组得到最强频率的bin,然后找到pitches[index, t]
处的音高。