gpt4 book ai didi

iphone - 从 iPhone 上的音频流中获取 Hz 频率

转载 作者:技术小花猫 更新时间:2023-10-29 10:13:40 27 4
gpt4 key购买 nike

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

最佳答案

这是我使用 Accelerate Framework 在 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);

现在你有一个数组,其中索引=频率,值=幅度(平方幅度?)。根据Nyquist theorem该阵列中的最大可能频率是采样率的一半。也就是说,如果您的采样率 = 44100,则您可以编码的最大频率为 22050 Hz。

因此,请为您的采样率找到奈奎斯特最大频率:const Float32 NyquistMaxFreq = SAMPLE_RATE/2.0;

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

这对我有用。如果我在 Audacity 中生成特定频率并播放它 - 此代码会检测到正确的频率(最强的频率,您还需要在 fftData 中找到最大值才能执行此操作)。

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

编辑:

这种不匹配的发生是因为我用于 FFT 的部分太小了。使用更大的时域数据 block (16384 帧)解决了这个问题。这个问题解释了它: Unable to get correct frequency value on iphone

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

关于iphone - 从 iPhone 上的音频流中获取 Hz 频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11686625/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com