2016-02-29 67 views
0

我想写一个音乐应用程序,其中检测音高是它的核心。我已经看到了这个问题的解决方案以及AppStore上的应用程序。然而,其中大部分都很过时,我想这样做是Swift。我一直在看AVAudioEngine作为一种方法来做到这一点,但我发现缺乏文档或者我没有足够努力。是否可以使用AVAudioEngine实时检测音高?

我发现的是,我可以点击inputNode总线这样的:

self.audioEngine = AVAudioEngine() 
self.audioInputNode = self.audioEngine.inputNode! 
self.audioInputNode.installTapOnBus(0, bufferSize:256, format: audioInputNode.outputFormatForBus(0), block: {(buffer, time) in 
     self.analyzeBuffer(buffer) 
}) 

总线被窃听2-3次每秒的缓冲区包含超过16000辆花车每个水龙头。这些来自麦克风的幅度样本是?

该文档至少权利要求它是从所述节点输出:“buffer参数是从一个AVAudioNode的输出捕获的音频的缓冲器。”

是否有可能使用AVAudioEngine来检测实际音高时间还是应该以另一种方式去做?

回答

0

我意识到Hellium3真的给我的信息是什么间距,如果这是一个好主意用Swift做这些事情。

我的问题最初是关于如果窃听PCM总线是从麦克风获取输入信号的方式。

由于问了这个问题,我已经完成了。使用通过点击PCM总线获得的数据并分析缓冲窗口。

它工作得很好,这是我对PCM总线,缓冲区和采样频率缺乏了解的原因,这让我首先提出了这个问题。

了解这三者可以更容易地看出这是正确的。

+0

你在Swift中实现了吗?如果可行,您可以共享音高检测或示例项目的Created文件吗?我正在使用AVAudioRecorder录制音频 –

2

这里有几个不同的概念。 AVAudioEngine只是引导您获取原始PCM数据的引擎,您可以直接使用Novocaine,Core-Audio或其他选项。

PCM数据是来自麦克风的浮点采样。

只要音调跟踪去,有各种技术。有一点要注意的是频率检测与音调检测不同。

FFT这是好的,但不能检测到缺少基本面信号的音调。您需要通过低通滤波器来运行信号,以减少可能出现的频率高于Nyquist Frequency,然后是window的频率混叠,然后将其传递到FFT,这是为了减少spectral leakage。 FFT将输出一系列分箱内的频谱内容,具有最高值的分箱被认为是信号中最强的频率。

Autocorrelation这可以给出更好的结果。它基本上是与自身相关的信号。

最后说明您希望检测的内容,需要考虑一些注意事项。诸如男声和某些乐器之类的东西可能会通过运行在未经过预处理的缓冲区上的正常FFT得到不正确的结果。

入住这PITCH DETECTION METHODS REVIEW

至于斯威夫特去,这不是非常适合于实时性,注重性能的系统。您可以检查old benchmarks of Swift vs C++

enter image description here

C++的FFT实现超过24倍快

+2

这些基准测试已超过一年。从那以后,斯威夫特走了很长一段路,所以我会以怀疑的态度对待他们。 – JeremyP

+0

足够公平,我的观点仍然是关于性能,而Swift无法替代C++/C的音频处理代码 – jarryd

+0

谢谢你的这篇翔实的文章。我测试了上面的代码,假设缓冲区包含自上次敲击以来的采样幅度。我使用Accelerate.framework通过FFT传递缓冲区并获取结果的平均值。使用音调发生器创建A4我测试了结果,它确实显示了预期的440赫兹+ - 电子。 这意味着这是可能的。然而,我想知道是否有更好的方法来做到这一点。我还没有检出AudioKit,也没有探究错误的含义。例如。如果我将麦克风靠近扬声器,它只会显示440赫兹。 – MdaG

相关问题