识别录制声音中的音符 - 第2部分 - Python

时间:2010-09-15 10:21:18

标签: python numpy audio fft computer-science

这是此问题的延续here

这是我用来获取样本的代码:

spf = wave.open(speech,'r')
sound_info = spf.readframes(-1)
sound_info = fromstring(sound_info, 'Int16')

sound_info的长度为194560 ,<44>采样率44100 的4.4倍。声音文件的长度是 2.2秒,所以sound_info的长度不是它应该的两倍吗?

此外,我似乎只能找到为什么使用FFT来产生频谱的足够信息。

我想将声音分开并分析多个分数的频谱,而不是整个声音文件。


非常感谢帮助。 :)


这是基本的sound_info图

plot(sound_info)

这是FFT图

freq = [abs(x.real) for x in fft(sound_info)]
plot(freq)

2 个答案:

答案 0 :(得分:1)

如果你的wav文件有两个通道,那么sound_info的长度将是2 *采样率*持续时间(秒)。通道数据交替出现,因此如果您将所有值都投入到一维数组中data,则与一个通道关联的值为data[::2],另一个为data[1::2] }。


粗略地说,平滑函数可以表示为正弦和余弦波的总和(具有不同的幅度和频率)。

FFT(快速傅里叶变换)将函数与那些正弦和余弦波的系数(幅度)联系起来。也就是说,一方面功能与另一方面系数序列之间存在一对一的映射。

如果声音样本主要由一个音符组成,则其FFT将具有一个非常大的系数(绝对值),而其他系数将非常小。该系数对应于具有特定频率的特定正弦波。那就是音符的频率。

答案 1 :(得分:0)

不要重新发明轮子:)

查看http://librosa.github.io,特别是关于短时傅里叶变换(STFT)的部分,或者在你的情况下,更像是恒定Q变换(CQT)。

但首先要做的事情是: 假设我们有一个来自音频文件的立体声信号(2个声道)。现在,我们通过创建平均通道(将两个通道相加并除以2)丢弃在音频文件的两个通道中编码的空间信息。我们现在有一个单声道(1声道)信号。由于我们有数字信号,因此每个时间点都称为样本。

现在开始有趣的部分,我们通过连续采样(512或2的倍数是标准值)将信号切割成小块(称为帧)。 通过对这些帧中的每一帧进行离散傅里叶变换(DFT),我们得到称为谱图的时频表示。 任何进一步的概念(重叠等)都可以在每本DSP书中或在本实验课程的资源中阅读: https://www.audiolabs-erlangen.de/content/05-fau/professor/00-mueller/02-teaching/2016s_apl/LabCourse_STFT.pdf

请注意,DFT的频率轴是线性间隔的。在西方音乐系统中,八度音程被分成12个半音,其中心频率以对数方式间隔开。查看上面关于如何从线性STFT接收对数间隔频率轴的分箱策略的脚本。 然而,这种方法非常基础,还有很多其他可能更好的方法。

现在回到你的笔记识别问题。 第一:这是一个非常艰难的。 :) 如上所述,乐器演奏的真实声音包含泛音。 此外,如果你有兴趣抄录完整乐队演奏的音符,你会受到其他音乐家的干扰等。

谈论你可以尝试的方法: 现在很多人使用非负矩阵特征化(NMF或类似的LDPCA)或神经网络来完成这项任务。 例如,NMF包含在scikit-learn中。 要开始,我会推荐NMF。仅使用单声道声音,即一次播放一个乐器。使用简单的衰减泛音结构初始化模板,看看会发生什么。