因此,无论是C4还是C5都不重要:它们都必须被检测为C。
想象一下12个半音在时钟表面上排列,指针指向音级。这就是我想要的!理想情况下,我希望能够判断唱出的音符是否完美或略有偏差。
这不是以前提出的问题的重复,因为它引入了以下限制:
1.声源是一个单独的人声,希望背景干扰可以忽略(尽管我可能需要处理); 2.八度并不重要,只有音级。
编辑--链接: 实时音高检测 使用苹果FFT和加速框架
查看我的答案,以获取平滑的频率检测:https://dev59.com/e3A75IYBdhLWcg3wP2gg#11042551
至于将此频率捕捉到最近的音符,这是我为我的调音器应用程序创建的一种方法:
- (int) snapFreqToMIDI: (float) frequencyy {
int midiNote = (12*(log10(frequencyy/referenceA)/log10(2)) + 57) + 0.5;
return midiNote;
}
这将返回MIDI音符值(http://www.phys.unsw.edu.au/jw/notes.html)
为了从这个MIDI音符值得到一个字符串:
- (NSString*) midiToString: (int) midiNote {
NSArray *noteStrings = [[NSArray alloc] initWithObjects:@"C", @"C#", @"D", @"D#", @"E", @"F", @"F#", @"G", @"G#", @"A", @"A#", @"B", nil];
return [noteStrings objectAtIndex:midiNote%12];
}
如果你需要一个关于音高检测的实现例子以及输出平滑处理,可以查看musicianskit.com/developer.php
我怀疑你正在尝试构建一个类似于Autotune的音高检测和/或校正器,因此你可能想使用M. Morise出色的WORLD实现,它可以快速而高质量地检测和修改语音流中的f0。
最后,请注意,只有少数几个声音音高检测器在声带颤音区间内能够很好地工作。其中几乎所有的音高检测器,包括WORLD,在声带颤音以及非常低的声音上都会失败。许多论文将声带颤音称为"creaky voice"并开发了特定算法,以帮助处理这种类型的声音输入。
我会尽力帮助您翻译以下内容,涉及IT技术方面:
随着我发现信息,我会把它放在这里...
维基百科上的音高检测算法是一个很好的起点。它列出了一些方法,用于确定八度,这对我的目的来说是可以的。
有关自相关的良好解释可以在这里找到(为什么维基百科不能像这样简单明了呢?)。
如其他人提到的,你应该使用音高检测算法。由于这个领域已经被广泛覆盖,我会介绍你问题的一些细节。你说你正在寻找这个音符的音高类别。然而,找到这个方法是计算音符的频率,然后使用一个表格将其转换为音高类别、八度和cents。我不知道有任何方法可以获得音高类别而不找到基频。
你将需要一个实时音高检测算法。在评估算法时,要注意每个算法所暗示的延迟时间,与你所希望的精度相比较。虽然有些算法比其他算法更好,但基本上你必须在一个和另一个之间进行权衡,并且不能确定两者都正确 - 就像海森堡测不准原理一样。(当只听到了一个周期的一小部分时,怎么能知道音符是C4呢?)
你的“平滑”方法相当于数字滤波器,它会改变声音的频率特性。简而言之,它可能会干扰你估计音高的尝试。如果你对数字音频有兴趣,数字滤波器是该领域基本且有用的工具,也是一个迷人的主题。理解它们需要强大的数学背景,但你不一定需要这个来获得基本的想法。
此外,你的零交叉方法是一种估计波形周期和音高的基本技术。可以用这种方式完成,但需要很多启发式和微调。(基本上,开发许多“候选”音高并尝试推断出主导音高。将出现许多特殊情况,这将使其混淆。一个快速的例子是较少的's'。)你会发现使用频率域音高检测算法更容易入手。