Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/114.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用纯正弦音调的FFT更精确的频率_Ios_Objective C_Audio_Signal Processing_Fft - Fatal编程技术网

Ios 使用纯正弦音调的FFT更精确的频率

Ios 使用纯正弦音调的FFT更精确的频率,ios,objective-c,audio,signal-processing,fft,Ios,Objective C,Audio,Signal Processing,Fft,我目前使用的FFT代码如下: 以下是两种相关方法的代码: -(void)createFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data { // Setup the length _log2n = log2f(bufferSize); // Calculate the weights array. This is a one-off operation. _FFTSetup = vDSP_create

我目前使用的FFT代码如下:

以下是两种相关方法的代码:

-(void)createFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {

  // Setup the length
  _log2n = log2f(bufferSize);

  // Calculate the weights array. This is a one-off operation.
  _FFTSetup = vDSP_create_fftsetup(_log2n, FFT_RADIX2);

  // For an FFT, numSamples must be a power of 2, i.e. is always even
  int nOver2 = bufferSize/2;

  // Populate *window with the values for a hamming window function
  float *window = (float *)malloc(sizeof(float)*bufferSize);
  vDSP_hamm_window(window, bufferSize, 0);
  // Window the samples
  vDSP_vmul(data, 1, window, 1, data, 1, bufferSize);
  free(window);

  // Define complex buffer
 _A.realp = (float *) malloc(nOver2*sizeof(float));
 _A.imagp = (float *) malloc(nOver2*sizeof(float));

}

-(void)updateFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {

  // For an FFT, numSamples must be a power of 2, i.e. is always even
  int nOver2 = bufferSize/2;

  // Pack samples:
  // C(re) -> A[n], C(im) -> A[n+1]
  vDSP_ctoz((COMPLEX*)data, 2, &_A, 1, nOver2);

  // Perform a forward FFT using fftSetup and A
  // Results are returned in A
  vDSP_fft_zrip(_FFTSetup, &_A, 1, _log2n, FFT_FORWARD);

  // Convert COMPLEX_SPLIT A result to magnitudes
  float amp[nOver2];
  float maxMag = 0;

  for(int i=0; i<nOver2; i++) {
    // Calculate the magnitude
    float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
    maxMag = mag > maxMag ? mag : maxMag;
  }
  for(int i=0; i<nOver2; i++) {
    // Calculate the magnitude
    float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
   // Bind the value to be less than 1.0 to fit in the graph
   amp[i] = [EZAudio MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
 }
-(void)createFFTWithBufferSize:(float)bufferSize与audiodata:(float*)数据{
//设置长度
_log2n=log2f(缓冲区大小);
//计算权重数组。这是一次性操作。
_FFT设置=vDSP_创建_FFT设置(_log2n,FFT_RADIX2);
//对于FFT,numsample必须是2的幂,即始终为偶数
int nOver2=缓冲区大小/2;
//用汉明窗口函数的值填充*窗口
float*window=(float*)malloc(sizeof(float)*bufferSize);
vDSP_hamm_窗口(窗口,缓冲区大小,0);
//将样品开窗
vDSP_vmul(数据,1,窗口,1,数据,1,缓冲区大小);
免费(窗口);
//定义复杂缓冲区
_A.realp=(float*)malloc(nOver2*sizeof(float));
_A.imagp=(浮动*)malloc(11月2日*sizeof(浮动));
}
-(void)updateFFTWithBufferSize:(float)带音频数据的bufferSize:(float*)数据{
//对于FFT,numsample必须是2的幂,即始终为偶数
int nOver2=缓冲区大小/2;
//包装样品:
//C(re)->A[n],C(im)->A[n+1]
vDSP_ctoz((复杂*)数据,2号和1号,11月2日);
//使用FFT设置和
//结果以
vDSP_fft_zrip(_fft设置,&u A,1,_log2n,fft前向);
//将结果转换为量级
浮动放大器[nOver2];
float maxMag=0;
对于(int i=0;i maxMag?mag:maxMag;
}

对于(int i=0;i可能您的采样频率不够高?

您可以通过将抛物线曲线拟合到峰值震级仓周围的3个FFT仓震级,然后找到该抛物线的极值来获得粗略的频率估计

通过使用FFT窗口的变换作为插值核,并进行逐次逼近以细化插值点最大值的估计,可以创建更好的估计值。(零填充和使用更长的FFT将提供类似类型的插值估计值。)


平稳信号的简单方法是,如果可能的话,只需使用更长的FFT和更长时间间隔内的更多样本。

这里出现了许多问题:

1) 你的频率轴间距是fmax/N,或者大约80Hz,所以你不会得到比这更好的分辨率

2) 你的信号非常接近(即,20KHz/44.1KHz几乎为0.5),当你接近奈奎斯特极限时,如果你想要得到准确的结果,你需要非常小心。(也就是说,在20KHz时,每个完整振荡周期只记录大约两个数据点。)


3) 由于20KHz处于人类听力的边缘(对大多数人来说更高),许多话筒并不真正担心它。iPhone的一种测量方法。

如果你对输入一无所知,FFT是获得频谱的一种非常好的方法。如果您知道输入是纯正弦波,您可以做得更好。从计算FFT开始,大致了解正弦的位置。获取最小值和最大值以估计振幅[或从FFT中获取值-将所有输入平方,相加,取平方根],在给定估计频率和振幅的情况下,获取开始和结束处的相位

通常,您会发现相位不匹配。这是因为末端的相位差为2*Δf*N。f-Δf是对频率的更好估计。请记住,这种方法对噪声非常敏感。这种方法之所以有效,是因为输入是一个纯正弦波,而噪声是除此之外的一切。使用这种方法迭代地快速爆炸;您甚至会遇到舍入错误(也不是正弦曲线)


另一个类似的技巧是减去估计的波浪。两个正弦之间的差值是两个正弦的乘积,一个加上频率(在您的情况下为±38.5 kHz),另一个减去频率(Δ_f_,小于100 Hz)。另请参见

正弦音调的声音为44.1 kHz,据我所知,这与我产生的频率有关,因为其中一半的频率比我产生的声音高。考虑到无限长的时间,这就足够了。如果您在固定时间段内需要更好的频率分辨率,则确实需要增加采样频率。由于我的声音的采样率为44.1KHz,因此频率分辨率看起来将在20000/256个音箱左右,即78.125。这就是为什么我不能得到一个特定的频率,只有一个在78范围内。还有其他方法可以更具体地描述正弦音吗?如果你能列出相关的数字,比如:缓冲区大小、分辨率等,那会很有帮助。我想目前我的缓冲区大小是512。我将在哪里/如何增加它?您的频率分辨率将受到采样频率和缓冲区大小的限制。您好,Codeman,您能给我发送增加缓冲区大小的修改代码吗(我面临着类似的问题,我已经工作了一个月了)我将如何增加我的缓冲区大小?这是我可以在代码中手动更改的吗?@codeman:是的,FFT对接受多少点没有实际限制。如果你想通过262.144分而不是512分,它仍然有效。不过,频率分辨率*时间分辨率=2,因此填充该缓冲区将花费512倍的时间。
for(int i=0; i<nOver2; i++) {
    // Calculate the magnitude
    float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
    if(maxMag < mag) {
        _i_max = i;
    }
    maxMag = mag > maxMag ? mag : maxMag;
}

float frequency = _i_max / bufferSize * 44100;
NSLog(@"FREQUENCY: %f", frequency);