1

当我实现使用 FIR 数字滤波器设计器创建的系数时,我得到了失真/奇怪的噪音。我将每个系数相乘,然后将下一个系数添加到每个样本中。我究竟做错了什么?

这是我的回调代码。

    #define FILTER_LEN 80
double coeffs[FILTER_LEN] = {
    0.4125 ,
    0.30599221057325454 ,
    0.08276044954686006 ,
    -0.0712490359027435 ,
    -0.06955311277904458 ,
    0.012051224652113425 ,
    0.05063742923584152 ,
    0.014831744868668527 ,
    -0.029779626539569115 ,
    -0.025159694030674883 ,
    0.010775174598886429 ,
    0.024755079985752222 ,
    0.0034713457185069014 ,
    -0.01801104775186626 ,
    -0.011545826635692912 ,
    0.008870916828741674 ,
    0.013655646830993191 ,
    -5.071102664251368E-4 ,
    -0.011300641103149761 ,
    -0.00510565075476355 ,
    0.006635644627205735 ,
    0.007342041186401136 ,
    -0.0017580021987183615 ,
    -0.006718478769227455 ,
    -0.001849971567154631 ,
    0.004418212284366871 ,
    0.003574469697178196 ,
    -0.0017346630584036216 ,
    -0.0035938670191588205 ,
    -3.7421959758368194E-4 ,
    0.0025646904655304632 ,
    0.0014944285606302294 ,
    -0.0012317293951690197 ,
    -0.0017072619265551775 ,
    1.2436035789109519E-4 ,
    0.0013643560681614716 ,
    5.61402657685598E-4 ,
    -8.232131487266428E-4 ,
    -8.902383271571432E-4 ,
    2.7287466296042835E-4
};


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


MusicPlaybackState *musicPlaybackState = (MusicPlaybackState*) inRefCon;


double sampleinp;

double acc = 0;



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


        AudioBuffer buffer = ioData->mBuffers[i];
        SInt16 *outSampleBuffer = buffer.mData;

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

            //Left Channel
            sampleinp = musicPlaybackState->samplePtr[packetIndex++];


            //For each sample add filter
            for (int k=0; k < FILTER_LEN ; k++) {
                acc += coeffs[k] * sampleinp;

            }

            outSampleBuffer[j]  = MAX(MIN(acc,32767.0),-32768.0);


            j++;

            //Right Channel
            sampleinp = musicPlaybackState->samplePtr[packetIndex++];

            //For each sample add filter
            for (int k=0; k < FILTER_LEN ; k++) {
                acc += coeffs[k] * sampleinp;

            }

             outSampleBuffer[j]=MAX(MIN(acc,32767.0),-32768.0);


        }} 
}
4

1 回答 1

1

我可能误读了您的代码,因此我将对其进行简化。如我错了请纠正我:

//  incorrect
double out = 0;
double in = ....
for( int i=0; i<FILTER_LEN; ++i ) {
   out += in * coeff[i];
}
//bound out

这根本不对——如果你做一点因式分解,你会发现这相当于乘以一个常数(你的系数的总和)。FIR 滤波器实际上是卷积运算。要执行此操作,您需要存储旧输入。

//  correct (or close to it)
double out = 0;
double in = ....
//shift stored inputs
for( int i=FILTER_LEN-2; i>=0; --i ) {
   inarr[i+1] = inarr[i];
}
// add new input to the mix
inarr[0] = in;
// perform convolution
for( int i=0; i<FILTER_LEN; ++i ) {
   out += inarr[i] * coeff[i];
}
//bound out

该代码未经测试,我可能在这里或那里颠倒了一些索引,但你明白了。

于 2013-03-12T03:53:32.373 回答