二阶IIR滤波器,butterworth带通(EQ)的系数?

ost*_*oon 4 audio signal-processing objective-c core-audio accelerate-framework

重要更新:我已经找到答案并将它们放在这个简单的开源库中:http://bartolsthoorn.github.com/NVDSP/检查一下,如果遇到问题,它可能会节省很多时间在IOS中使用音频过滤器!

^

我创建了一个(实时)音频缓冲区(float *data),它可以容纳几个sin(theta)不同频率的波.

下面的代码显示了我是如何创建缓冲区的,我试图做一个带通滤波器,但它只是将信号转换为噪声/闪烁:

    // Multiple signal generator
__block float *phases = nil;
[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
{
    float samplingRate = audioManager.samplingRate;
    NSUInteger activeSignalCount = [tones count];

    // Initialize phases
    if (phases == nil) {
        phases = new float[10];
        for(int z = 0; z <= 10; z++) {
            phases[z] = 0.0;
        }
    }

    // Multiple signals
    NSEnumerator * enumerator = [tones objectEnumerator];
    id frequency;
    UInt32 c = 0;
    while(frequency = [enumerator nextObject])
    {
        for (int i=0; i < numFrames; ++i)
        {
            for (int iChannel = 0; iChannel < numChannels; ++iChannel) 
            {
                float theta = phases[c] * M_PI * 2;
                if (c == 0) {
                    data[i*numChannels + iChannel] = sin(theta);
                } else {
                    data[i*numChannels + iChannel] = data[i*numChannels + iChannel] + sin(theta);
                }
            }
            phases[c] += 1.0 / (samplingRate / [frequency floatValue]);
            if (phases[c] > 1.0) phases[c] = -1;
        }
        c++;
    }

    // Normalize data with active signal count
    float signalMulti = 1.0 / (float(activeSignalCount) * (sqrt(2.0)));
    vDSP_vsmul(data, 1, &signalMulti, data, 1, numFrames*numChannels);


    // Apply master volume
    float volume = masterVolumeSlider.value;
    vDSP_vsmul(data, 1, &volume, data, 1, numFrames*numChannels);


    if (fxSwitch.isOn) {
        // H(s) = (s/Q) / (s^2 + s/Q + 1)
        // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
        // BW 2.0  Q 0.667
        // http://www.rane.com/note170.html
        //The order of the coefficients are, B1, B2, A1, A2, B0.
        float Fs = samplingRate;

        float omega = 2*M_PI*Fs; // w0 = 2*pi*f0/Fs

        float Q = 0.50f;
        float alpha = sin(omega)/(2*Q); // sin(w0)/(2*Q)

        // Through H
        for (int i=0; i < numFrames; ++i)
        {
            for (int iChannel = 0; iChannel < numChannels; ++iChannel) 
            {
                data[i*numChannels + iChannel] = (data[i*numChannels + iChannel]/Q) / (pow(data[i*numChannels + iChannel],2) + data[i*numChannels + iChannel]/Q + 1);
            }
        }

        float b0 = alpha;
        float b1 = 0;
        float b2 = -alpha;
        float a0 = 1 + alpha;
        float a1 = -2*cos(omega);
        float a2 = 1 - alpha;

        float *coefficients = (float *) calloc(5, sizeof(float));


        coefficients[0] = b1;
        coefficients[1] = b2;
        coefficients[2] = a1;
        coefficients[3] = a2;
        coefficients[3] = b0;

        vDSP_deq22(data, 2, coefficients, data, 2, numFrames);

        free(coefficients);
    }

    // Measure dB
    [self measureDB:data:numFrames:numChannels];
 }];
Run Code Online (Sandbox Code Playgroud)

我的目标是为这个缓冲区制作一个10波段均衡器,使用vDSP_deq22方法的语法是: vDSP_deq22(<float *vDSP_A>, <vDSP_Stride vDSP_I>, <float *vDSP_B>, <float *vDSP_C>, <vDSP_Stride vDSP_K>, <vDSP_Length __vDSP_N>) 参见:http://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/ #的reference.html // apple_ref/DOC/c_ref/vDSP_deq22

参数:

float *vDSP_A is the input data
float *vDSP_B are 5 filter coefficients
float *vDSP_C is the output data
Run Code Online (Sandbox Code Playgroud)

我必须制作10个过滤器(10次vDSP_deq22).然后我为每个乐队设置增益并将它们组合在一起.但是,我为每个过滤器提供什么系数?我知道vDSP_deq22是2阶(butterworth)IIR滤波器,但我该如何将其变成带通?

现在我有三个问题:

a)我是否必须对音频缓冲区进行解交织和交错?我知道设置步幅为2只是通道上的过滤器,但我如何过滤另一个,步幅1将两个通道处理为一个.

b)在进入vDSP_deq22方法之前,我是否必须转换/处理缓冲区?如果是这样,我是否还必须将其转换回正常状态?

c)我应该将系数的哪些值设置为10 vDSP_deq22s?

我已经尝试了好几天了但是我还没有想到这个,请帮帮我!

Pau*_*l R 7

你的omega价值需要标准化,即表示为Fs的一小部分 - 看起来你f0在计算时遗漏了omega,这也会造成alpha错误:

    float omega = 2*M_PI*Fs; // w0 = 2*pi*f0/Fs
Run Code Online (Sandbox Code Playgroud)

应该是:

    float omega = 2*M_PI*f0/Fs; // w0 = 2*pi*f0/Fs
Run Code Online (Sandbox Code Playgroud)

其中f0是以Hz为单位的中心频率.

对于10频段均衡器,您需要选择10个f0值,间隔对数,例如25 Hz,50 Hz,100 Hz,200 Hz,400 Hz,800 Hz,1.6 kHz,3.2 kHz,6.4 kHz,12.8 kHz.