从iPhone上的音频流获取赫兹的频率(Get Hz frequency from audio st

2019-06-17 13:31发布

什么是在iOS得到的音频流(音乐)Hz的频率值的最佳方法? 什么是苹果提供这样做的最好,最简单的框架。 提前致谢。

Answer 1:

这样的问题在这里问了很多关于SO。 (我已经回答了类似的一个位置 ),所以我写了代码一点教程,你甚至可以在商业和封闭源代码的应用程序使用。 这并不一定是最好的方式,但它是一种方式,很多人都明白。 你将不得不根据你所说的“每个短音乐片段的赫兹平均值”如何修改它。 你的意思是基音或频率重心,例如。

您可能需要使用苹果的FFT在加速框架,另一个答案的建议。

希望能帮助到你。

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



Answer 2:

下面是一些代码,我用它来使用加速框架,这使得它相当快的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,数据和数据的大小。 返回FFT数据与NUMSAMPLES / 2的大小。

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. 通过浮点32时域数据,得到回报的频域数据: 浮点32 * fftData = computeFFT(fftHelper,缓冲液,框架尺寸);

现在你有一个数组,其中指数=频率值=幅度(平方值?)。 根据奈奎斯特定理数组中的最大可能的频率是你的采样率的一半。 也就是说,如果你的采样率= 44100,你可以编码,最高频率为22050赫兹。

所以,去发现你的采样速率奈奎斯特频率最高:const的浮点32 NyquistMaxFreq = SAMPLE_RATE / 2.0;

查找赫兹很容易: 浮点32赫兹=((浮点32)someIndex /(浮点32)fftDataSize)* NyquistMaxFreq; (fftDataSize =框架尺寸/ 2.0)

这对我的作品。 如果我生成Audacity的特定频率和发挥它 - 这个代码检测右一个(最强的一个,您还需要找到在fftData最大做到这一点)。

(仍有约1-2%有点不匹配不知道为什么会这样,如果有人能解释我为什么 - 。这将不胜感激)

编辑:

这不匹配的情况,因为我用它来FFT块太小。 使用较大的时域数据(16384帧)的块解决该问题。 这个问题解释它: 无法取得iphone正确的频率值

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



Answer 3:

苹果不提供频率或音高估计的框架。 然而,iOS的加速框架并包括用于FFT和自相关,其可以被用作更复杂的频率和音调识别或估计算法组件例程。

没有办法既容易,最好,除了可能用于单个长的连续的恒定频率的纯正弦在几乎为零噪声音调,其中长FFT窗的内插幅度峰可能是适宜的。 对于语音和音乐,简单方法往往无法工作。 但对于基音检测或估算方法搜索将大量的研究论文更合适的算法。



文章来源: Get Hz frequency from audio stream on iPhone