我尝试在安卓平台上开发吉他游戏。
而且我需要进行实时音高检测以获取吉他和弦/弦的频率。
我会从麦克风获取输入,然后分析输入(输入演奏哪种吉他弦/和弦)
我找到了两种我可以使用的方法,一种是 YIN,另一种是 FFT。
哪种方法可以获得更好的性能和准确的结果?
我尝试在安卓平台上开发吉他游戏。
而且我需要进行实时音高检测以获取吉他和弦/弦的频率。
我会从麦克风获取输入,然后分析输入(输入演奏哪种吉他弦/和弦)
我找到了两种我可以使用的方法,一种是 YIN,另一种是 FFT。
哪种方法可以获得更好的性能和准确的结果?
你需要先了解什么是' pitch' 真的是(阅读下面的维基百科链接)。当在吉他或钢琴上发出一个音符时,我们听到的不仅仅是一个声音振动频率,而是在不同数学相关频率上发生的多个声音振动的复合。这种不同频率的振动复合的元素被称为谐波或分音。例如,如果我们按下钢琴上的中间 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)。
下面,在 GitHub.com,是我设计的一种不寻常的两阶段算法的 C++ 源代码,它可以在 Windows 上播放时对复音 MP3 文件进行实时音高检测。这个免费的应用程序(PitchScope Player,可在网络上获得)经常用于检测 MP3 录音中吉他或萨克斯管独奏的音符。您可以下载适用于 Windows 的可执行文件,以查看我的算法在您选择的 mp3 文件上的运行情况。该算法旨在检测 MP3 或 WAV 音乐文件中任何给定时刻的最主要音高(音符)。在 MP3 录制期间的任何给定时刻,最主要的音高(一个音符)的变化可以准确地推断出音符的开始。
我使用修改后的 DFT 对数变换(类似于 FFT)首先通过寻找具有峰值电平的频率来检测这些可能的谐波(见下图)。由于我为修改后的 Log DFT 收集数据的方式,我不必对信号应用窗口函数,也不必添加和重叠。我创建了 DFT,因此它的频率通道以对数方式定位,以便直接与吉他、萨克斯管等音符产生的谐波频率对齐。
我的音高检测算法实际上是一个两阶段的过程:a)首先检测到 ScalePitch('ScalePitch' 有 12 个可能的音高值:{E、F、F#、G、G#、A、A#、B、C、C#、D , D#} ) b) 并且在确定 ScalePitch 之后,通过检查 4 个可能的 Octave-Candidate 音符的所有谐波来计算 Octave。该算法旨在检测和弦 MP3 文件中任何给定时刻的最主要音高(音符)。这通常对应于器乐独奏的音符。那些对我的两阶段音高检测算法的 C++ 源代码感兴趣的人可能希望从 GitHub.com 上的 SPitchCalc.cpp 文件中的 Estimate_ScalePitch() 函数开始。
https://github.com/CreativeDetectors/PitchScope_Player
https://en.wikipedia.org/wiki/Transcription_(music)#Pitch_detection
下面是对数 DFT(由我的 C++ 软件创建)在复调 mp3 录音中吉他独奏 3 秒的图像。它显示了演奏独奏时吉他上各个音符的谐波如何出现。对于这个对数 DFT 上的每个音符,我们可以看到它的多个谐波垂直延伸,因为每个谐波将具有相同的时间宽度。确定音符的八度后,我们就知道了基本音的频率。
下图演示了八度检测算法,一旦确定了该音符的 ScalePitch,我开发该算法以选择正确的八度候选音符(即正确的基本音)。那些希望在 C++ 中看到该方法的人应该转到名为 FundCandidCalcer.cpp 的文件中的 Calc_Best_Octave_Candidate() 函数,该文件包含在我在 GitHub 的源代码中。