改善音高检测的技巧


21

我正在开发一个简单的Web应用程序,该应用程序允许用户调整他/她的吉他。我是信号处理方面的真正初学者,因此,如果我的问题不合适,请不要过分判断。

因此,我设法使用FFT算法获得了基频,此时,该应用程序可以实现某种功能。但是,还有改进的余地,现在我将原始pcm发送给FFT算法,但是我在想,也许有一些前置/后置算法/过滤器可以改善检测效果。你能建议什么吗?

我的主要问题是,当检测到某个频率时,它将显示该频率1-2秒,然后跳至其他随机频率,然后再次返回,依此类推,即使声音是连续的。

我也对任何其他类型的优化感兴趣,如果有人对此有经验的话。

Answers:


20

我猜它得到的其他频率是基波的谐波?就像您在演奏100 Hz,而是拾取200 Hz或300 Hz一样?首先,您应该将搜索空间限制在吉他可能会出现的频率范围内。找到您可能需要最高基本知识,并限制于此。

如果基频的幅度低于谐波(或完全缺失,但这与吉他无关紧要),则自相关在查找基频方面将比FFT更好。

在此处输入图片说明

您也可以尝试加权较低的频率以强调基波并最大程度地减少谐波,或者使用类似这样峰值拾取算法,然后选择最低频率。

同样,在应用FFT之前,应先对信号加窗。您只需将其乘以窗口函数即可,该函数会逐渐减小波形的开始和结束以使频谱更清晰。然后,您将获得频率分量的高尖峰而不是宽的尖峰。

您还可以使用插值来获得更准确的峰。取光谱的对数,然后将抛物线拟合到峰和两个相邻点,并找到抛物线的真实峰。但是,您可能不需要这么高的准确性。

这是我所有这些的示例Python代码


这是我一直在寻找的,很好的答案,谢谢!
Valentin Radu

2
乘以渐缩的窗函数实际上会抹去信号中的任何频谱线,从而使它们更宽。但是,它可以为您提供的是动态范围,它使您可以在存在高功率干扰音的情况下识别例如低功率频谱线。
詹森·R

@JasonR考虑到此功能旨在在大功率干扰音的可能性确实较低的环境中工作,您是否建议最好不要使用汉明窗?
Valentin Radu

1
我可以确认,使用汉明窗使我更接近保持读数稳定的目标。现在,当我演奏A4时,我大多数时候会获得440 Hz的频率,而很少见的是接近650 Hz的读数。我猜这些是谐波吗?另外,我不禁注意到,对于更高的频率,该应用程序可以正常工作,而对于更低的频率,该应用程序将开始失败。可能是因为我正在使用FTT来检测峰值幅度频率仓,而对于较低的频率,这并不总是基本的吗?
Valentin Radu

1
@mindnoise:660 Hz不是440 Hz的谐波,而是220 Hz的谐波,或者说是高于440的五分之一。可能是另一个弦谐振或失真或其他原因吗?如果您可以绘制FFT并加以查看,那么找出这样的问题要容易得多。是的,低频可能会由于机械效应或模拟电路而被滤波并相对于高频被降低。
endlith 2011年

12

音调与FFT的峰值幅度频率仓不同。音调是一种人类的心理声学现象。基音可能缺少或非常弱的基音(在某些语音,钢琴和吉他声音中很常见)和/或频谱中的许多有力的泛音使基音频率不堪重负(但仍被人听到为该基音) 。因此,任何FFT峰值频率检测器(甚至包括一些开窗和内插)都不是可靠的音高估计方法。

这个stackoverflow问题包括一些估计音高的替代方法的列表,这些方法可能会产生更好的结果。

补充:如果您要对吉他声音进行此操作,请注意,最低的吉他弦实际上可能会产生轻微的不和谐泛音,使音高估算更加困难,因为人耳可能会听到与泛音的倍数更紧密相关的音高频率,而不是弦的实际基本振动频率。

#2:这个问题经常被问到,以至于我写了一篇较长的博客文章,主题是:http : //www.musingpaw.com/2012/04/musical-pitch-is-not-just-fft-frequency.html


刚刚访问(并评论了)您刚刚推荐给我们的博客。
罗伯特·布里斯托

5

我花了很多年研究和弦音乐的音高检测-就像检测mp3录音中吉他独奏的音符一样。我还写了关于Wikipedia的部分,简要介绍了该过程(请看下面链接中的“音高检测”小节)。

当在钢琴上按下单个键时,我们听到的不仅是声音振动的一个频率,而是在不同的数学相关频率下发生的多个声音振动的组合。这种在不同频率下的振动合成的元素称为谐波或部分谐波。例如,如果我们按钢琴上的中音C键,则复合谐波的单个频率将从261.6 Hz开始作为基频,523 Hz为第二谐波,785 Hz为第三谐波,1046 Hz是4次谐波,等等。后面的谐波是基频261.6 Hz的整数倍(例如:2 x 261.6 = 523、3 x 261.6 = 785、4 x 261.6 = 1046)。

我使用修改后的DFT对数变换,首先通过查找峰值电平的频率来检测可能的谐波(请参见下图)。由于我为修改后的Log DFT收集数据的方式,我不必对信号应用开窗功能,也不必添加和重叠。我已经创建了DFT,以便将其频率通道对数定位,以便与吉他,萨克斯风等音符产生谐波的频率直接对齐。

现在已经退休了,我决定在一个名为PitchScope Player的免费演示应用程序中发布我的音高检测引擎的源代码。PitchScope Player可在网上找到,您可以下载Windows的可执行文件,以查看我的算法在所选mp3文件上的作用。以下指向GitHub.com的链接将带您进入完整的源代码,在这里您可以查看如何通过自定义对数DFT变换检测谐波,然后查找频率满足正确整数关系的部分(谐波),从而定义了“沥青'。

我的音高检测算法实际上是一个两阶段过程:a)首先检测到ScalePitch(“ ScalePitch”具有12个可能的音高值:{E,F,F#,G,G#,A,A#,B,C,C#,D ,d#})b)和被确定ScalePitch后,则八度是通过检查所有谐波的4个可能的倍频候选笔记计算。该算法旨在检测和弦MP3文件中任何给定时刻的最主要音高(音符)。这通常与器乐独奏的音符相对应。那些对我的2级音高检测算法的C ++源代码感兴趣的人可能希望从GitHub.com上SPitchCalc.cpp文件中的Estimate_ScalePitch()函数开始。

https://github.com/CreativeDetectors/PitchScope_Player

https://zh.wikipedia.org/wiki/Transcription_(音乐)#Pitch_detection

下图是对数DFT(由我的C ++软件创建)的图像,在多音mp3录音中吉他独奏3秒。它显示了弹奏独奏时吉他上各个音符的谐波如何出现。对于此对数DFT的每个音符,我们可以看到其多个谐波垂直延伸,因为每个谐波将具有相同的时间宽度。确定音符的八度之后,我们便知道基本音的频率。

在此处输入图片说明

下图演示了八度音阶检测算法,一旦确定了该音阶的ScalePitch,我就会开发该算法来选择正确的八度音阶候选音符(即正确的基本音阶)。那些希望在C ++中看到该方法的人应该转到名为FundCandidCalcer.cpp的文件内的Calc_Best_Octave_Candidate()函数,该文件包含在我在GitHub上的源代码中。

在此处输入图片说明


詹姆斯,您的DFT音高检测器是否检测到基音缺失(或较弱)的音符?
罗伯特·布里斯托

是的,即使信号的“基音缺失(或弱)”,我的两级音高检测算法也可以检测到音符,这是此两级处理的重要优势。当在对数DFT图表上看到的注释的时间宽度上执行八度音阶检测时,在第二阶段确定基本面。由于此音高检测功能可在和弦mp3信号混乱的情况下工作,因此它将检测到缺少许多谐波的音符,包括基本音。我刚刚在“答案”中添加了第二张图,该图解释了我的八度检测算法。
詹姆斯·保罗·米勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.