这是此问题的延续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)
答案 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。仅使用单声道声音,即一次播放一个乐器。使用简单的衰减泛音结构初始化模板,看看会发生什么。