从iPhone上的audiostream获取Hz频率

从iOS上的audiostream(音乐)获取Hz频率值的最佳方法是什么? 苹果公司提供的最好和最简单的框架是做什么的。 提前致谢。

像这样的问题在这里被问到很多。 (我在这里已经回答了类似的问题 ),所以我写了一个包含代码的小教程,甚至可以在商业和封闭源代码应用程序中使用。 这不一定是最好的方式,但这是很多人理解的一种方式。 您将不得不根据“每个短音乐段的Hz平均值”的含义对其进行修改。 例如,您是指基本音高还是频率中心。

您可能想要在加速框架中使用Apple的FFT,正如另一个答案所build议的那样。

希望能帮助到你。

http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html

这里是我使用加速框架在iOS中执行FFT的一些代码,这使得它非常快速。

//keep all internal stuff inside this struct typedef struct FFTHelperRef { FFTSetup fftSetup; // Accelerate opaque type that contains setup information for a given FFT transform. COMPLEX_SPLIT complexA; // Accelerate type for complex number Float32 *outFFTData; // Your fft output data Float32 *invertedCheckData; // This thing is to verify correctness of output. Compare it with input. } FFTHelperRef; 

//首先 – 用这个函数初始化你的FFTHelperRef。

 FFTHelperRef * FFTHelperCreate(long numberOfSamples) { FFTHelperRef *helperRef = (FFTHelperRef*) malloc(sizeof(FFTHelperRef)); vDSP_Length log2n = log2f(numberOfSamples); helperRef->fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2); int nOver2 = numberOfSamples/2; helperRef->complexA.realp = (Float32*) malloc(nOver2*sizeof(Float32) ); helperRef->complexA.imagp = (Float32*) malloc(nOver2*sizeof(Float32) ); helperRef->outFFTData = (Float32 *) malloc(nOver2*sizeof(Float32) ); memset(helperRef->outFFTData, 0, nOver2*sizeof(Float32) ); helperRef->invertedCheckData = (Float32*) malloc(numberOfSamples*sizeof(Float32) ); return helperRef; } 

//在这里传递初始化的FFTHelperRef,数据和数据大小。 用numSamples / 2大小返回FFT数据。

 Float32 * computeFFT(FFTHelperRef *fftHelperRef, Float32 *timeDomainData, long numSamples) { vDSP_Length log2n = log2f(numSamples); Float32 mFFTNormFactor = 1.0/(2*numSamples); //Convert float array of reals samples to COMPLEX_SPLIT array A vDSP_ctoz((COMPLEX*)timeDomainData, 2, &(fftHelperRef->complexA), 1, numSamples/2); //Perform FFT using fftSetup and A //Results are returned in A vDSP_fft_zrip(fftHelperRef->fftSetup, &(fftHelperRef->complexA), 1, log2n, FFT_FORWARD); //scale fft vDSP_vsmul(fftHelperRef->complexA.realp, 1, &mFFTNormFactor, fftHelperRef->complexA.realp, 1, numSamples/2); vDSP_vsmul(fftHelperRef->complexA.imagp, 1, &mFFTNormFactor, fftHelperRef->complexA.imagp, 1, numSamples/2); vDSP_zvmags(&(fftHelperRef->complexA), 1, fftHelperRef->outFFTData, 1, numSamples/2); //to check everything ============================= vDSP_fft_zrip(fftHelperRef->fftSetup, &(fftHelperRef->complexA), 1, log2n, FFT_INVERSE); vDSP_ztoc( &(fftHelperRef->complexA), 1, (COMPLEX *) fftHelperRef->invertedCheckData , 2, numSamples/2); //================================================= return fftHelperRef->outFFTData; } 

像这样使用它:

  1. 初始化它: FFTHelperCreate(TimeDomainDataLenght);

  2. 通过Float32时域数据,返回频域数据: Float32 * fftData = computeFFT(fftHelper,buffer,frameSize);

现在你有一个数组索引=频率,数值=数量(平方数?)。 根据奈奎斯特定理,您arrays中的最大可能频率是采样率的一半。 那就是如果你的采样率= 44100,你可以编码的最大频率是22050Hz。

所以去找你的采样率奈奎斯特最高频率: const Float32 NyquistMaxFreq = SAMPLE_RATE / 2.0;

查找Hz很容易: Float32 hz =((Float32)someIndex /(Float32)fftDataSize)* NyquistMaxFreq; (fftDataSize = frameSize / 2.0)

这对我有用。 如果我在Audacity中生成特定的频率并播放它 – 这个代码检测到正确的(最强的,你也需要在fftData中findmax来做这个)。

(大概有1-2%的不匹配,不知道为什么会发生这种情况,如果有人能解释我为什么 – 那将会非常感激。)

编辑:

发生这种不匹配是因为我用于FFT的部分太小。 使用更大的时域数据块(16384帧)解决了这个问题。 这个问题解释它: 无法得到正确的频率值在iphone上

编辑:这是示例项目: https : //github.com/krafter/DetectingAudioFrequency

苹果公司不提供频率或音调估计的框架。 但是,iOS Accelerate框架确实包含了用于FFT和自相关的例程,可以将其用作更复杂的频率和音高识别或估算algorithm的组件。

除了可能对于几乎为零的噪声中的单个长连续恒定频率纯正弦波音调(其中长窗FFT的内插幅度峰值可能是合适的),没有办法既简单又最好。 对于语音和音乐而言,这种简单的方法往往不能工作。 但是对基音检测或估计方法的search将会产生许多关于更合适的algorithm的研究论文。