Iphone 使用Apple FFT和Accelerate框架
有没有人在iPhone应用程序中使用了Iphone 使用Apple FFT和Accelerate框架,iphone,audio,signal-processing,fft,accelerate-framework,Iphone,Audio,Signal Processing,Fft,Accelerate Framework,有没有人在iPhone应用程序中使用了Apple FFT,或者知道在哪里可以找到示例应用程序来使用它?我知道苹果有一些发布的代码,但是我不太确定如何将它实现到一个实际的项目。 < P>这里是一个真实的例子:一个C++的片段,使用加速的VDSP FFT例程对远程IO音频单元的输入进行自相关。使用这个框架相当复杂,但文档也不太糟糕 OSStatus DSPCore::初始化(双采样器,uint16\u t\u缓冲大小){ 采样器=_采样器; bufferSize=\u bufferSize; pea
Apple FFT
,或者知道在哪里可以找到示例应用程序来使用它?我知道苹果有一些发布的代码,但是我不太确定如何将它实现到一个实际的项目。 < P>这里是一个真实的例子:一个C++的片段,使用加速的VDSP FFT例程对远程IO音频单元的输入进行自相关。使用这个框架相当复杂,但文档也不太糟糕
OSStatus DSPCore::初始化(双采样器,uint16\u t\u缓冲大小){
采样器=_采样器;
bufferSize=\u bufferSize;
peakIndex=0;
频率=0.f;
uint32_t maxFrames=getMaxFramesPerSlice();
displayData=(float*)malloc(maxFrames*sizeof(float));
bzero(显示数据,最大帧*sizeof(浮点));
log2n=log2f(最大帧);
n=1 mBuffers[0].mData,2,&A,1,numFrames/2);
memset(ioData->mBuffers[0].mData,0,ioData->mBuffers[0].mDataByteSize);
//快速傅里叶变换
vDSP_fft_zrip(fft设置和A,1,ln,fft_前向);
//绝对平方(等于mag^2)
vDSP_zvmag(&A,1,A.realp,1,numFrames/2);
bzero(A.imagp,(numFrames/2)*sizeof(float));
//逆FFT
vDSP_fft_zrip(fft设置,&A,1,ln,fft_逆);
//将复杂拆分转换为实拆分
vDSP_ztoc(&A,1,(复杂*)显示数据,2,numFrames/2);
//正常化
浮动比例=1.f/显示数据[0];
vDSP_vsmul(显示数据,1和比例,显示数据,1,numFrames);
//朴素峰值拾取:找到第一个局部最大值
peakIndex=0;
对于(尺寸ii=1;iidisplayData[ii-1])&(displayData[ii]>displayData[ii+1])){
peakIndex=ii;
打破
}
}
//计算频率
频率=采样器/peakIndex+四次插值(&displayData[peakIndex-1]);
bufferSize=numFrames;
对于(int ii=0;iimNumberBuffers;++ii){
bzero(ioData->mBuffers[ii].mData,ioData->mBuffers[ii].mDataByteSize);
}
}
我刚得到一个iPhone项目的FFT代码:
- 创建新项目
- 删除除main.m和xxx_info.plist之外的所有文件
- 转到“项目设置”并搜索pch,阻止它尝试加载.pch(因为我们刚刚删除了它)
- 将代码示例复制粘贴到main.m中的任何内容上
- 拆下包含碳的管路。碳用于OSX
- 删除所有框架,并添加加速框架
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_INVERSE);
对n个实浮点进行FFT,然后反向返回到我们开始的位置。
ip代表就地,这意味着&A被覆盖
这就是所有这些特殊打包错误的原因——这样我们就可以将返回值压缩到与发送值相同的空间中
为了给出一些观点(比如:为什么我们首先要使用这个函数?),让我们假设我们想要对麦克风输入执行基音检测,并且我们已经设置了它,以便每次麦克风进入1024个浮点时都会触发一些回调。假设麦克风的采样率为44.1kHz,即约44帧/秒
因此,我们的时间窗口是1024个样本的持续时间,即1/44秒
因此,我们将使用麦克风的1024个浮点数打包,设置log2n=10(2^10=1024),预先计算一些线轴(setupReal),并:
现在A将包含n/2个复数。这些代表n/2个频率箱:
- bin[1]。idealFreq=44Hz——即我们能够可靠检测到的最低频率是该窗口内的一个完整波,即44Hz波
- bin[2]。idealFreq=2*44Hz
- 等等
- bin[512]。idealFreq=512*44Hz——我们可以检测到的最高频率(称为奈奎斯特频率)是每对点代表一个波的位置,即窗口内的512个完整波,即512*44Hz,或:n/2*bin[1]。idealFreq
- 实际上还有一个额外的Bin,Bin[0],它通常被称为“DC偏移”。恰好Bin[0]和Bin[n/2]始终具有复杂组件0,因此[0].realp用于存储Bin[0]和[0]。imagp用于存储Bin[n/2]
for (i = 0; i < n; i++)
originalReal[i] = (float) (i + 1);
你真的需要看看A是如何分配的,也许可以查一下复杂的
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);
for (i = 0; i < n; i++)
originalReal[i] = (float) (i + 1);
// 1. masquerades n real #s as n/2 complex #s = {1+2i, 3+4i, ...}
// 2. splits to
// A.realP = {1,3,...} (n/2 elts)
// A.compP = {2,4,...} (n/2 elts)
//
vDSP_ctoz(
(COMPLEX *) originalReal,
2, // stride 2, as each complex # is 2 floats
&A,
1, // stride 1 in A.realP & .compP
nOver2); // n/2 elts
A.realp = (float *) malloc(nOver2 * sizeof(float));
A.imagp = (float *) malloc(nOver2 * sizeof(float));
z = exp(i.theta) = cos(theta) + i.sin(theta)
// let's say log2n = 8, so n=2^8=256 samples, or 'harmonics' or 'terms'
// if we pre-calculate the 256th roots of unity (of which there are 256)
// that will save us time later.
//
// Note that this call creates an array which will need to be released
// later to avoid leaking
setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2);
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_INVERSE);
// Need to see the documentation for this one...
// in order to optimise, different routines return values
// that need to be scaled by different amounts in order to
// be correct as per the math
// In this case...
scale = (float) 1.0 / (2 * n);
vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2);
vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2);