峰值过滤器具有点击和弹出功能

时间:2011-01-30 00:59:01

标签: iphone c++ ios signal-processing core-audio

OSStatus MusicPlayerCallback ( 
                       void *                     inRefCon, 
                       AudioUnitRenderActionFlags *   ioActionFlags, 
                       const AudioTimeStamp *         inTimeStamp, 
                       UInt32                     inBusNumber, 
                       UInt32                     inNumberFrames, 
                       AudioBufferList *            ioData) { 


MusicPlaybackState *musicPlaybackState = (MusicPlaybackState*) inRefCon; 

double sampleinp; 

double A,omega,sn,cs,alpha,Bandwidth; 

double dbGain; 

double   a0,a1,a2,b0,b1,b2; 

dbGain = 1.0; 

A=pow(10.0,dbGain/40.0); 

Bandwidth = 2.0; 

omega=2 * M_PI * 800.0/44100.0; 

sn=sin(omega); 

cs=cos(omega); 

alpha=sn*sinh(((M_LN2/2)*Bandwidth*omega)/sn); 


//Peak Filter Biquad 

b0 =1.0 + alpha * A; 

b1 = (-2.0 * cs); 

b2 = 1.0 - alpha * A; 

a0 = 1.0 + (alpha /A); 

a1 = -2.0 * cs; 

a2 = 1.0 - (alpha /A); 



double b0a0, b1a0, b2a0, a1a0, a2a0; 

double static x1; 

double static x2; 

double static y1; 

double static y2; 


b0a0=b0/a0;   

b1a0=b1/a0; 

b2a0=b2/a0; 

a1a0=a1/a0; 

a2a0=a2/a0; 


for (int i = 0 ; i < ioData->mNumberBuffers; i++){ 


  AudioBuffer buffer = ioData->mBuffers[i]; 
  AudioSampleType *outSample = buffer.mData; 

  for (int j = 0; j < inNumberFrames*2; j++){ 

     sampleinp = *musicPlaybackState->samplePtr++; 

     outSample[j] =  b0a0 * sampleinp + 
     b1a0 * x1 + 
     b2a0 * x2 - 
     a1a0 * y1 - 
     a2a0 * y2; 


     x2=x1; 
     x1=sampleinp; 

     y2=y1; 
     y1=outSample[j]; 

  }} 





return noErr; 
} 

有点击/弹出问题。有人请帮助......我不知道我做错了什么。这是在Xcode中使用Objective-C中的C.我尝试制作Coeff Global和Static,但没有运气。使用的音频文件是.caf我试过.wav但仍然没有好....

谢谢,抱歉一般的呼救声。我是这个网站的新手..我正在尝试在我的应用程序中添加峰值过滤器,但每次我使用滑块或只是将增益保持为1我会得到弹出和点击。对于保持前面的样本等,似乎存在并且正常工作。在改变频率或带宽时,我也得到某种类型的相位。我很困惑,现在研究dsp几个月了,我认为这是Objective-C和lil用户错误。将样本更改为SInt32似乎会消失,但更改频率时左声道会消失。

Dsp.h

typedef struct { 

  void* audioData; 

   UInt32 audioDataByteCount; 

   SInt16 *samplePtr; 

} MusicPlaybackState; 

4 个答案:

答案 0 :(得分:4)

根据hotpaw2的回答,这是过滤器响应的图表:

from pylab import *
import scipy.signal as signal

def biquad_peak(omega, gain_db, bandwidth):
    sn = sin(omega)
    cs = cos(omega)
    alpha = sn * sinh(log(2) / 2 * bandwidth * omega / sn)
    gain_sqrt = 10.0 ** (gain_db / 40.0)

    # feed-forward coefficients
    b0 = 1.0 + alpha * gain_sqrt
    b1 = -2.0 * cs
    b2 = 1.0 - alpha * gain_sqrt
    # feedback coefficients
    a0 = 1.0 + (alpha / gain_sqrt)
    a1 = -2.0 * cs
    a2 = 1.0 - (alpha / gain_sqrt)
    # normalize by a0
    B = array([b0, b1, b2]) / a0
    A = array([a0, a1, a2]) / a0
    return B, A

omega = 2 * pi * 800.0 / 44100.0
gain_db = 1.0
bandwidth = 2.0

B, A = biquad_peak(omega, gain_db, bandwidth)
w, H = signal.freqz(B, A)
f = w / pi * 22050.0
plot(f, abs(H), 'r')
gain = 10.0 ** (gain_db / 20.0)
print  "Gain:", gain
plot(f, gain*ones(len(f)), 'b--'); grid()

biquad peak filter response

峰值增益设置为1.1220184543(即1 dB)。您可以看到滤波器如何使大部分可听范围的增益大于1.

编辑2: 如果这是一个可调整的均衡器,则由用户设置避免失真的增益。另外,我怀疑你所描述的极端问题是由典型音轨的窄带上1 dB的温和增益引起的。我认为这是因为你的音频有交错的立体声数据。这些通道中的每一个都需要单独过滤。我修改了你的嵌套循环以实现这个目的:

a0 = 1.0 + alpha / A; 
a1 = -2.0 * cs / a0;     
a2 = (1.0 - alpha / A) / a0; 
b0 = (1.0 + alpha * A) / a0; 
b1 = -2.0 * cs / a0; 
b2 = (1.0 - alpha * A) / a0;

double static x11, x12, x21, x22;
double static y11, y12, y21, y22;
double x0, y0;

for (int i = 0; i < ioData->mNumberBuffers; i++) {  

    AudioBuffer buffer = ioData->mBuffers[i]; 
    AudioSampleType *outSample = buffer.mData; 

    for (int j = 0; j < inNumberFrames*2; j++) { 

        /* x0 is in the range of SInt16: -32768 to 32767 */

        x0 = *musicPlaybackState->samplePtr++;

        y0 = b0 * x0 + 
             b1 * x11 + 
             b2 * x12 - 
             a1 * y11 - 
             a2 * y12; 

        outSample[j] = fmax(fmin(y0, 32767.0), -32768.0); 

        x12 = x11; 
        x11 = x0;
        y12 = y11;
        y11 = y0
        j++;          

        x0 = *musicPlaybackState->samplePtr++;

        y0 =  b0 * x0 + 
              b1 * x21 + 
              b2 * x22 - 
              a1 * y21 - 
              a2 * y22; 

        outSample[j] = fmax(fmin(y0, 32767.0), -32768.0); 

        x22 = x21; 
        x21 = x0;          
        y22 = y21; 
        y21 = y0; 
    }
}

答案 1 :(得分:2)

一个重要问题是您的过滤器状态必须存储在refcon状态内(至少在典型情况下这是最明显的最佳位置)。

没有它,你的过滤器会在每次调用回调时重建并初始化,这意味着状态将无法正确保存,并且除了第一个回调之外,你将在每个回调的边界上出现故障。

答案 2 :(得分:1)

看起来你正在使用RBJ的biquad食谱配方。

平均增益为1.0的双二阶峰值滤波器在某些频率下的增益大于1.0。如果您不想要削波,则必须使用小于1.0的增益,或者在输入上使用衰减器或AGC,以便峰值频率提升永远不会达到削波的水平。

这是一个没有AGC的问题,因为有些客户希望使用峰值或低音增强滤波器来使声音更大,并且你必须将平均电平衰减到实际降低以完全防止在峰值频率下削波。

答案 3 :(得分:1)

除了已经给出的优秀答案之外,我还会添加一个通用的建议 - 你应该将你的过滤器例程与回调分解并解耦(即将它作为一个单独的函数,不依赖于你的iOS代码)。通过这种方式,您可以将其置于测试工具中并更轻松地对其进行调试(在非实时环境中),与任何可能使问题复杂化的特定于iOS的问题分开。