首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >核心-音频,Goertzel算法不工作

核心-音频,Goertzel算法不工作
EN

Stack Overflow用户
提问于 2011-03-13 02:08:33
回答 2查看 2.3K关注 0票数 5

我目前正在创建一个应用程序,它可以从iPhone的麦克风中实时计算出预定义频率(16780‘s)的大小。

我在缓冲区中有声音数据,并尝试使用Goertzel处理它,Goertzel是为此任务设计的算法。Goertzel info。这就是问题开始的地方。

当记录的声音的频率(5000 of )比定义的频率(16780 Of)低得多时,该算法会得到非常积极的结果。事实上,这种结果比记录正确频率的声音时产生的结果要积极得多。

下面是我对goertzel的实现:

代码语言:javascript
复制
double goertzel(unsigned short *sample, int sampleRate, double Freq, int len )
{

double realW = 2.0 * cos(2.0 * M_PI * Freq / sampleRate);
double imagW = 2.0 * sin(2.0 * M_PI * Freq / sampleRate);
double d1 = 0;
double d2 = 0;
int z;
double y;
for (int i = 0; i < len; i++) {
    y=(double)(signed short)sample[i] +realW * d1 - d2;
    d2 = d1;
    d1 = y;
}
double rR = 0.5 * realW *d1-d2;
double rI = 0.5 * imagW *d1-d2;

return (sqrt(pow(rR, 2)+pow(rI,2)))/len;
} /* end function goertzel */

下面是我如何检索音频(如果它是相关的

代码语言:javascript
复制
-(void)startListeningWithFrequency:(float)frequency;
{
OSStatus status;
//AudioComponentInstance audioUnit;
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;

AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
status = AudioComponentInstanceNew( inputComponent, &audioUnit);
checkStatus(status);

UInt32 flag = 1;
status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,kInputBus, &flag, sizeof(flag));
checkStatus(status);

AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate         = 44100.00;//44100.00;
audioFormat.mFormatID           = kAudioFormatLinearPCM;
audioFormat.mFormatFlags        = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
audioFormat.mFramesPerPacket    = 1;
audioFormat.mChannelsPerFrame   = 1;
audioFormat.mBitsPerChannel     = 16;
//  float
audioFormat.mBytesPerPacket     = 2;
audioFormat.mBytesPerFrame      = 2;

status = AudioUnitSetProperty(audioUnit,
                              kAudioUnitProperty_StreamFormat,
                              kAudioUnitScope_Output,
                              kInputBus,
                              &audioFormat, 
                              sizeof(audioFormat));
checkStatus(status);
//status = AudioUnitSetProperty(audioUnit, 
//                            kAudioUnitProperty_StreamFormat, 
//                            kAudioUnitScope_Input, 
//                            kOutputBus, 
//                            &audioFormat, 
//                            sizeof(audioFormat));
checkStatus(status);
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit, 
                              kAudioOutputUnitProperty_SetInputCallback,
                              kAudioUnitScope_Global,
                              kInputBus, &callbackStruct, sizeof(callbackStruct));
checkStatus(status);
/*  UInt32 shouldAllocateBuffer = 1;
AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ShouldAllocateBuffer, kAudioUnitScope_Global, 1, &shouldAllocateBuffer, sizeof(shouldAllocateBuffer));
*/
status = AudioOutputUnitStart(audioUnit);

}
static OSStatus recordingCallback(void *inRefCon, 
                              AudioUnitRenderActionFlags *ioActionFlags, 
                              const AudioTimeStamp *inTimeStamp, 
                              UInt32 inBusNumber, 
                              UInt32 inNumberFrames, 
                              AudioBufferList *ioData) {
AudioBuffer buffer;

buffer.mNumberChannels = 1;
buffer.mDataByteSize = inNumberFrames * 2;
//NSLog(@"%d",inNumberFrames);
buffer.mData = malloc( inNumberFrames * 2 );

// Put buffer in a AudioBufferList
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0] = buffer;



OSStatus status;
status = AudioUnitRender(audioUnit, 
                         ioActionFlags, 
                         inTimeStamp, 
                         inBusNumber, 
                         inNumberFrames, 
                         &bufferList);  
checkStatus(status);
//double g = calculateGoertzel((const char *)(&bufferList)->mBuffers[0].mData,16789.0,96000.0);
UInt16 *q = (UInt16 *)(&bufferList)->mBuffers[0].mData;
int N = sizeof(q)/sizeof(UInt16);
double Qr,Qi;
double theta = 2.0*M_PI*16780/44100;
double g = goertzel(q,44100,16780,N);

NSLog(@"goertzel:%f", g);
}

对于远低于16780 of的频率,这将返回数百个数字,而对于16780 of的频率,将返回更小的数字。

我非常沮丧,如果能帮上忙,我将非常感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-13 02:23:22

我猜一下:

根据Nyquist-Shannon采样定理,采样率应该至少是您试图测量的频率的两倍。你的也是,但只是勉强而已。44.1 the的采样率是测量22 the信号的外沿。16 the的信号足够接近混叠可能会导致波形分析问题的极限。这里有一张图片来说明我的观点:

所以,我猜你需要更高的采样率。为什么你不试着在算法中运行一个纯16 the的正弦波,看看它是否做得更好?如果测试数据中只有一个频率,那么混叠就不是什么问题了。如果你从正弦波得到更高的响应,那么你可能只需要更高的采样率。

票数 3
EN

Stack Overflow用户

发布于 2011-03-13 03:50:34

看起来Goertzel滤波器中使用的谐振器是单极谐振器的一级近似。这将大大降低每步高相角时的精度和稳定性。使用对trig函数的更好近似的1-bin DFT在如此高的频率下可能工作得更好。

而iPhone麦克风的频率响应可能会以如此高的频率滚动。

添加:

对于1-bin DFT,在你的内部循环中尝试这样做:

代码语言:javascript
复制
d1 += (double)sample[i] * cos(2.0*M_PI*i*Freq/sampleRate);
d2 += (double)sample[i] * sin(2.0*M_PI*i*Freq/sampleRate);

然后返回:

代码语言:javascript
复制
dR = d1;
dI = d2;
magnitude = sqrt(dR*dR + dI*dI) / (double)len;

注意,对于固定的频率和采样率,可以在音频回调之外预先计算触发函数,并将其保存在数组或查找表中。如果你不做一些这样的优化,在你的音频回调中调用多个双精度超越函数可能会太慢和/或浪费大量的电池电量,但在典型的快速PC上可能会模拟正常。

DFT被定义为作为bin频率Freq的精确整数周期数的长度,但是其它长度将用于包含不同量的所谓的谱“泄漏”和/或扫频误差的近似。滤波器频率响应的宽度将与DFT长度大致成反比。此外,频率越接近Fs/2,DFT需要越长以避免复杂的图像混叠,也许长度为N*Fs/(Fs/2 - Freq)的多个周期将是更好的长度。您可能需要保存或排队采样以获得适当的长度(而不仅仅是使用音频回调给出的缓冲区长度)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5284412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档