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