Ios 为什么我的iPhone FFT频率值不正确?

Ios 为什么我的iPhone FFT频率值不正确?,ios,objective-c,signal-processing,fft,accelerate-framework,Ios,Objective C,Signal Processing,Fft,Accelerate Framework,我一直在尝试在苹果的加速框架中使用FFT获得精确的频率,但我很难找出为什么我的值偏离了真实频率 我一直在使用这篇文章作为我实现的基础,在真正努力达到我现在的目的之后,我完全被难住了 到目前为止,我已经在->汉宁窗口->FFT->相位计算->怪异的最终输出音频。我原以为我的数学在什么地方会有问题,但我现在真的没有主意了 输出比它们应该的低很多,例如,我输入440Hz,它输出190Hz,或者我输入880Hz,它输出400Hz。在大多数情况下,这些结果是一致的,但并不总是一致的,而且似乎任何事物之间也

我一直在尝试在苹果的加速框架中使用FFT获得精确的频率,但我很难找出为什么我的值偏离了真实频率

我一直在使用这篇文章作为我实现的基础,在真正努力达到我现在的目的之后,我完全被难住了

到目前为止,我已经在->汉宁窗口->FFT->相位计算->怪异的最终输出音频。我原以为我的数学在什么地方会有问题,但我现在真的没有主意了

输出比它们应该的低很多,例如,我输入440Hz,它输出190Hz,或者我输入880Hz,它输出400Hz。在大多数情况下,这些结果是一致的,但并不总是一致的,而且似乎任何事物之间也没有任何共同的因素

这是我的密码:

enum
{
    sampleRate  = 44100,
    osamp       = 4,
    samples     = 4096,
    range       = samples * 7 / 16,
    step        = samples / osamp
};

NSMutableArray *fftResults;

static COMPLEX_SPLIT    A;
static FFTSetup         setupReal;
static uint32_t         log2n, n, nOver2;
static int32_t          stride;

static float            expct = 2*M_PI*((double)step/(double)samples);
static float            phase1[range];
static float            phase2[range];
static float            dPhase[range];

- (void)fftSetup
{
    // Declaring integers
    log2n = 12;
    n = 1 << log2n;
    stride = 1;
    nOver2 = n / 2;

    // Allocating memory for complex vectors
    A.realp = (float *) malloc(nOver2 * sizeof(float));
    A.imagp = (float *) malloc(nOver2 * sizeof(float));

    // Allocating memory for FFT
    setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2);

    // Setting phase
    memset(phase2, 0, range * sizeof(float));

}
        // For each sample in buffer...
        for (int bufferCount = 0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++)
        {
            // Declaring samples from audio buffer list
            SInt16 *samples = (SInt16*)audioBufferList.mBuffers[bufferCount].mData;


            // Creating Hann window function
            for (int i = 0; i < nOver2; i++)
            {
                double hannMultiplier = 0.5 * (1 - cos((2 * M_PI * i) / (nOver2 -  1)));

                // Applying window to each sample
                A.realp[i] = hannMultiplier * samples[i];
                A.imagp[i] = 0;
            }

            // Applying FFT
            vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);

            // Detecting phase
            vDSP_zvphas(&A, stride, phase1, stride, range);

            // Calculating phase difference
            vDSP_vsub(phase2, stride, phase1, stride, dPhase, stride, range);

            // Saving phase
            memcpy(phase2, phase1, range * sizeof(float));

            // Extracting DSP outputs
            for (size_t j = 0; j < nOver2; j++)
            {
                NSNumber *realNumbers = [NSNumber numberWithFloat:A.realp[j]];
                NSNumber *imagNumbers = [NSNumber numberWithFloat:A.imagp[j]];

                [real addObject:realNumbers];
                [imag addObject:imagNumbers];

            }

            // Combining real and imaginary parts
            [resultsCombined addObject:real];
            [resultsCombined addObject:imag];

            // Filling FFT output array
            [fftResults addObject:resultsCombined];
        }

    }


    int fftCount = [fftResults count];
    NSLog(@"FFT Count: %d",fftCount);

    // For each FFT...
    for (int i = 0; i < fftCount; i++)
    {
        // Declaring integers for peak detection
        float peak = 0;
        float binNumber = 0;

        // Declaring integers for phase detection
        float deltaPhase;

        static float trueFrequency[range];


        for (size_t j = 1; j < range; j++)
        {
            // Calculating bin magnitiude
            float realVal   = [[[[fftResults objectAtIndex:i] objectAtIndex:0] objectAtIndex:j] floatValue];
            float imagVal   = [[[[fftResults objectAtIndex:i] objectAtIndex:1] objectAtIndex:j] floatValue];
            float magnitude = sqrtf(realVal*realVal + imagVal*imagVal);

            // Peak detection
            if (magnitude > peak)
            {
                peak = magnitude;
                binNumber = (float)j;
            }

            // Getting phase difference
            deltaPhase = dPhase[j];

            // Subtract expected difference
            deltaPhase -= (float)j*expct;

            // Map phase difference into +/- pi interval
            int qpd = deltaPhase / M_PI;

            if (qpd >= 0)
                qpd += qpd&1;
            else
                qpd -= qpd&1;

            deltaPhase -= M_PI * (float)qpd;

            // Getting bin deviation from +/i interval
            float deltaFrequency = osamp * deltaPhase / (2 * M_PI);

            // Calculating true frequency at the j-th partial
            trueFrequency[j] = (j * (sampleRate/samples)) + (deltaFrequency * (sampleRate/samples));

        }

        UInt32 mag;
        mag = binNumber;

        // Extracting frequency at bin peak
        float f = trueFrequency[mag];

        NSLog(@"True frequency = %fHz", f);

        float b = roundf(binNumber*(sampleRate/nOver2));

        NSLog(@" Bin frequency = %fHz", b);

    }
enum
{
采样率=44100,
osamp=4,
样本数=4096,
范围=样品*7/16,
步骤=样本/osamp
};
NSMutableArray*fftResults;
静态复合_分裂A;
静态FFTSetup setupReal;
静态uint32_t log2n,n,nOver2;
静态跨步;
静态浮点表达式=2*M_PI*((双)步进/(双)样本);
静态浮动相位1[范围];
静态浮动相位2[范围];
静态浮点dPhase[范围];
-(无效)FFT安装
{
//声明整数
log2n=12;
n=1峰值)
{
峰值=震级;
binNumber=(float)j;
}
//获取相位差
deltaPhase=dPhase[j];
//减去期望差
deltaPhase-=(浮点)j*expct;
//将相位差映射到+/-pi间隔
int qpd=延迟相位/M_PI;
如果(qpd>=0)
qpd+=qpd&1;
其他的
qpd-=qpd&1;
deltaPhase-=M_PI*(浮点)qpd;
//从+/i间隔获取仓位偏差
浮动增量频率=osamp*增量相位/(2*M_PI);
//计算第j部分的真频率
trueFrequency[j]=(j*(采样器/样本))+(deltaFrequency*(采样器/样本));
}
UInt32-mag;
mag=二进制数;
//在bin峰值提取频率
浮动f=真实频率[mag];
NSLog(@“真实频率=%fHz”,f);
浮点数b=roundf(二进制数*(采样器/nOver2));
NSLog(@“Bin frequency=%fHz”,b);
}

请注意,预期相位差(即使对于以仓为中心的频率)取决于FFT对的窗口偏移或重叠,以及FFT结果的仓数或频率。e、 g.如果窗口偏移很小(1个样本),则2个FFT之间的未包裹相位差将小于偏移较大的情况。在相同的偏移量下,如果频率更高,两个FFT的同一个bin之间的预期相位差将更大(或者它将包裹更多)。

看看这里,我不认为您实际上正在将FFT输出索引转换为实际频率!!!我已经看过了,我已经得到了bin输出(最后2行代码),这里正在讨论,这就是你所指的吗?我追求的是精确的频率,我认为我的问题在于我的相位计算,那一页似乎没有涉及到这一点。。。除非我误解了你的意思!你能解释一下为什么相位会影响准确的频率吗?它不应该不仅影响功率吗?我的理解是,如果频率等于bin频率,那么它将没有相位差,但是如果频率不同于bin频率,那么它的相位可以用来计算它离bin频率有多远:即精确频率=delta频率+bin频率,其中,通过该相位计算增量频率。我想至少是这样,因为我的程序不起作用!fft仅具有有限的频率分辨率,等于面元宽度。这个阶段没有达到你的预期。如果您遵循trumpetlicks发布的链接,您应该会没事的。