【问题标题】:Peak Filter has clicks and pops峰值过滤器有咔嗒声和弹出声
【发布时间】:2011-06-17 22:48:37
【问题描述】:
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; 

【问题讨论】:

  • 我无法想象为什么有人投票结束这个。
  • @Slomojo:我认为这个问题不应该结束,但就目前而言,它的提出并不是很好,我可以理解为什么它可能会获得接近的选票。 @Cocell:您可能希望改进问题以避免进一步接近投票 - 尝试提供有关问题的更多详细信息以及您尝试过的内容,并将其作为单个特定问题而不是一般的“呼救”。
  • @Paul R - 我同意这个问题应该更有效地提出,但完全无声的投票结束是不合适的。很明显,Cocell 是 SO 的新用户,只是想解决一个棘手的问题。低于 2k 代表的人不可能投票结束,所以当这种情况发生时非常令人失望。这是武断的、无益的而且坦率地说是粗鲁的,如果需要,需要更多信息的评论就是这里所需要的,而不是“走开,你的问题是不想要的”,这正是近距离投票所传达的内容。
  • @Slomojo:你是对的,当然,近距离投票应该总是有评论解释原因,但不幸的是,我们似乎确实得到了很多“路过”的近距离投票,没有厘米。
  • @eryksun 数据类型是 SInt16,希望这就是您所需要的。我还没有通过 SineWave 进行测试。我正在测试不同的立体声歌曲,认为过滤器会起作用。这真让我抓狂。我一直在使用 MATLab 创建过滤器,然后尝试在我的应用程序中实现它们,但即使有静态系数也没有运气。

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


【解决方案1】:

看起来您正在使用 RBJ 的 biquad 食谱食谱。

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

如果没有 AGC,这是一个问题,因为一些客户希望峰值或低音增强滤波器可以使声音更大,而您必须将平均电平衰减到实际上更低,以完全防止峰值频率处的削波。

【讨论】:

  • 好的,我将尝试添加 AGC。所以你基本上说它发出声音的原因是因为不同频率的增益在幅度上超过 1.0 而不是 eryksun 提到的 dB?
【解决方案2】:

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

否则,您的过滤器会在每次调用回调时重新构建和初始化,这意味着状态将无法正确保存,并且您将在除第一个回调之外的每个回调的边界处出现故障。

【讨论】:

    【解决方案3】:

    根据 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()
    

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

    编辑 2: 如果这是用于可调节 EQ,则由用户设置避免失真的增益。另外,我怀疑您描述的极端问题是由典型音轨的窄带上 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; 
        }
    }
    

    【讨论】:

    • 请注意,即使您保证增益在所有频率下
    • 那么,如果您说它必须小于 1dB,我将如何提高 10000kHz 的频率,例如在 12dB 处达到峰值而没有咔嗒声和爆裂声?
    • @eryksun 不只是以它为例。只是想知道如果我想在某个频率下提高 12dB 怎么办,这会导致同样的问题吗?感谢您的帮助。
    • 哇,解决了所有问题。我不敢相信这是一件如此简单却如此艰难的事情。只需在循环中添加第二个通道并保持在 -1.0-1.0 之间。谢谢大家,非常感谢 eryksun,这真的要了我的命。伙计,我很高兴。
    • 如果有人能回答这个问题,这不是一个大问题,当尝试提高或降低增益时,dB 是 20*log10(A),问题是我怎样才能在没有削波的情况下得到 -12dB/12dB如果我必须保持在 -1.0-1.0 之间?如何确定它的平坦位置?
    【解决方案4】:

    除了已经给出的出色答案之外,我将只添加一个一般性的建议 - 您应该将过滤器例程与回调分离并分离(即,使其成为一个单独的函数,不依赖于您的iOS 代码)。这样,您就可以将其放入测试工具中并更轻松地对其进行调试(在非实时环境中),与任何可能使问题复杂化的 iOS 特定问题分开。

    【讨论】:

    • 谢谢,我的第二个版本确实有这样的问题,但仍然是同样的问题。我只是把它们放在一起,以便更容易提供帮助。
    • @Cocell: 好的 - 当您单独实现例程时,编写一个可以生成输入信号的测试工具,例如给定幅度和频率的正弦波,然后以可以绘制的格式转储输出 - 使调试等更容易。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    相关资源
    最近更新 更多