⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 firfilter.cpp.svn-base

📁 ffshow源码
💻 SVN-BASE
字号:
/*=============================================================================//      //  This software has been released under the terms of the GNU Public//  license. See http://www.gnu.org/copyleft/gpl.html for details.////  Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au////=============================================================================*//* Design and implementation of different types of digital filters*/#include "stdafx.h"#include "firfilter.h"#include "TfirSettings.h"#include "simd.h"#if 0/* Add new data to circular queue designed to be used with a FIR   filter. xq is the circular queue, in pointing at the new sample, xi   current index for xq and n the length of the filter. xq must be n*2   long. */#define updateq(n,xi,xq,in)\  xq[xi]=(xq)[(xi)+(n)]=*(in);\  xi=(++(xi))&((n)-1);#endif  /*******************************************************************************  FIR filter implementations******************************************************************************//* C implementation of FIR filter y=w*x   n number of filter taps, where mod(n,4)==0   w filter taps   x input signal must be a circular buffer which is indexed backwards *//*TfirFilter::_ftype_t TfirFilter::fir(register unsigned int n, _ftype_t* w, _ftype_t* x){  register _ftype_t y; // Output  y = 0.0;   do{    n--;    y+=w[n]*x[n];  }while(n != 0);  return y;}*//*// Boxcar//// n window length// w buffer for the window parameters*/void TfirFilter::boxcar(int n, _ftype_t* w){  int i;  // Calculate window coefficients  for (i=0 ; i<n ; i++)    w[i] = 1.0;}/*// Triang a.k.a Bartlett////               |    (N-1)| //           2 * |k - -----|//               |      2  |// w = 1.0 - ---------------//                    N+1// n window length// w buffer for the window parameters*/void TfirFilter::triang(int n, _ftype_t* w){  _ftype_t k1  = (_ftype_t)(n & 1);  _ftype_t k2  = 1/((_ftype_t)n + k1);  int      end = (n + 1) >> 1;  int      i;    // Calculate window coefficients  for (i=0 ; i<end ; i++)    w[i] = w[n-i-1] = _ftype_t((2.0*((_ftype_t)(i+1))-(1.0-k1))*k2);}/*// Hanning//                   2*pi*k// w = 0.5 - 0.5*cos(------), where 0 < k <= N//                    N+1// n window length// w buffer for the window parameters*/void TfirFilter::hanning(int n, _ftype_t* w){  int      i;  _ftype_t k = _ftype_t(2*M_PI/((_ftype_t)(n+1))); // 2*pi/(N+1)    // Calculate window coefficients  for (i=0; i<n; i++)    *w++ = _ftype_t(0.5*(1.0 - cos(k*(_ftype_t)(i+1))));}/*// Hamming//                        2*pi*k// w(k) = 0.54 - 0.46*cos(------), where 0 <= k < N//                         N-1//// n window length// w buffer for the window parameters*/void TfirFilter::hamming(int n,_ftype_t* w){  int      i;  _ftype_t k = _ftype_t(2*M_PI/((_ftype_t)(n-1))); // 2*pi/(N-1)  // Calculate window coefficients  for (i=0; i<n; i++)    *w++ = _ftype_t(0.54 - 0.46*cos(k*(_ftype_t)i));}/*// Blackman//                       2*pi*k             4*pi*k// w(k) = 0.42 - 0.5*cos(------) + 0.08*cos(------), where 0 <= k < N//                        N-1                 N-1//// n window length// w buffer for the window parameters*/void TfirFilter::blackman(int n,_ftype_t* w){  int      i;  _ftype_t k1 = _ftype_t(2*M_PI/((_ftype_t)(n-1))); // 2*pi/(N-1)  _ftype_t k2 = 2*k1; // 4*pi/(N-1)  // Calculate window coefficients  for (i=0; i<n; i++)    *w++ = _ftype_t(0.42 - 0.50*cos(k1*(_ftype_t)i) + 0.08*cos(k2*(_ftype_t)i));}/*// Flattop//                                        2*pi*k                     4*pi*k// w(k) = 0.2810638602 - 0.5208971735*cos(------) + 0.1980389663*cos(------), where 0 <= k < N//                                          N-1                        N-1//// n window length// w buffer for the window parameters*/void TfirFilter::flattop(int n,_ftype_t* w){  int      i;  _ftype_t k1 = _ftype_t(2*M_PI/((_ftype_t)(n-1))); // 2*pi/(N-1)  _ftype_t k2 = 2*k1;                   // 4*pi/(N-1)    // Calculate window coefficients  for (i=0; i<n; i++)    *w++ = _ftype_t(0.2810638602 - 0.5208971735*cos(k1*(_ftype_t)i) + 0.1980389663*cos(k2*(_ftype_t)i));}/* Computes the 0th order modified Bessel function of the first kind.  // (Needed to compute Kaiser window) //   // y = sum( (x/(2*n))^2 )//      n*/TfirFilter::_ftype_t TfirFilter::besselizero(_ftype_t x){   static const _ftype_t BIZ_EPSILON=_ftype_t(1E-21); // Max error acceptable   _ftype_t temp;  _ftype_t sum   = 1.0f;  _ftype_t u     = 1.0f;  _ftype_t halfx = x/2.0f;  int      n     = 1;  do {    temp = halfx/(_ftype_t)n;    u *=temp * temp;    sum += u;    n++;  } while (u >= BIZ_EPSILON * sum);  return(sum);}/*// Kaiser//// n window length// w buffer for the window parameters// b beta parameter of Kaiser window, Beta >= 1//// Beta trades the rejection of the low pass filter against the// transition width from passband to stop band.  Larger Beta means a// slower transition and greater stop band rejection.  See Rabiner and// Gold (Theory and Application of DSP) under Kaiser windows for more// about Beta.  The following table from Rabiner and Gold gives some// feel for the effect of Beta:// // All ripples in dB, width of transition band = D*N where N = window// length// // BETA    D       PB RIP   SB RIP// 2.120   1.50  +-0.27      -30// 3.384   2.23    0.0864    -40// 4.538   2.93    0.0274    -50// 5.658   3.62    0.00868   -60// 6.764   4.32    0.00275   -70// 7.865   5.0     0.000868  -80// 8.960   5.7     0.000275  -90// 10.056  6.4     0.000087  -100*/void TfirFilter::kaiser(int n, _ftype_t* w, _ftype_t b){  _ftype_t tmp;  _ftype_t k1  = 1.0f/besselizero(b);  int      k2  = 1 - (n & 1);  int      end = (n + 1) >> 1;  int      i;     // Calculate window coefficients  for (i=0 ; i<end ; i++){    tmp = (_ftype_t)(2*i + k2) / ((_ftype_t)n - 1.0f);    w[end-(1&(!k2))+i] = w[end-1-i] = k1 * besselizero(_ftype_t(b*sqrt(1.0 - tmp*tmp)));  }}/*******************************************************************************  FIR filter design******************************************************************************//* Design FIR filter using the Window method   n     filter length must be odd for HP and BS filters   w     buffer for the filter taps (must be n long)   fc    cutoff frequencies (1 for LP and HP, 2 for BP and BS)          0 < fc < 1 where 1 <=> Fs/2   flags window and filter type as defined in filter.h         variables are ored together: i.e. LP|HAMMING will give a          low pass filter designed using a hamming window     opt   beta constant used only when designing using kaiser windows      returns 0 if OK, -1 if fail*/TfirFilter::_ftype_t* TfirFilter::design_fir(unsigned int *n, _ftype_t* fc, int type, int window, _ftype_t opt){  unsigned int  o   = *n & 1;            // Indicator for odd filter length  unsigned int  end = ((*n + 1) >> 1) - o;       // Loop end  unsigned int  i;                      // Loop index  _ftype_t k1 = 2 * _ftype_t(M_PI);             // 2*pi*fc1  _ftype_t k2 = 0.5f * (_ftype_t)(1 - o);// Constant used if the filter has even length  _ftype_t k3;                           // 2*pi*fc2 Constant used in BP and BS design  _ftype_t g  = 0.0f;                    // Gain  _ftype_t t1,t2,t3;                     // Temporary variables  _ftype_t fc1,fc2;                      // Cutoff frequencies  // Sanity check  if(*n==0) return NULL;  fc[0]=limit(fc[0],_ftype_t(0.001),_ftype_t(1));    if (!o && (type==TfirSettings::BANDSTOP || type==TfirSettings::HIGHPASS))   (*n)++;  _ftype_t *w=(_ftype_t*)aligned_calloc(sizeof(_ftype_t),*n);   // Get window coefficients  switch(window){  case(TfirSettings::WINDOW_BOX):    boxcar(*n,w); break;  case(TfirSettings::WINDOW_TRIANGLE):    triang(*n,w); break;  case(TfirSettings::WINDOW_HAMMING):    hamming(*n,w); break;  case(TfirSettings::WINDOW_HANNING):    hanning(*n,w); break;  case(TfirSettings::WINDOW_BLACKMAN):    blackman(*n,w); break;  case(TfirSettings::WINDOW_FLATTOP):    flattop(*n,w); break;  case(TfirSettings::WINDOW_KAISER):    kaiser(*n,w,opt); break;  default:   {    delete []w;    return NULL;           }   }  if(type==TfirSettings::LOWPASS || type==TfirSettings::HIGHPASS){     fc1=*fc;    // Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2    fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25f;    k1 *= fc1;    if(type==TfirSettings::LOWPASS){ // Low pass filter      // If the filter length is odd, there is one point which is exactly      // in the middle. The value at this point is 2*fCutoff*sin(x)/x,       // where x is zero. To make sure nothing strange happens, we set this      // value separately.      if (o){        w[end] = fc1 * w[end] * 2.0f;        g=w[end];      }      // Create filter      for (i=0 ; i<end ; i++){        t1 = (_ftype_t)(i+1) - k2;        w[end-i-1] = w[*n-end+i] = _ftype_t(w[end-i-1] * sin(k1 * t1)/(M_PI * t1)); // Sinc        g += 2*w[end-i-1]; // Total gain in filter      }    }    else{ // High pass filter      //if (!o) // High pass filters must have odd length      // return -1;      w[end] = _ftype_t(1.0 - (fc1 * w[end] * 2.0));      g= w[end];      // Create filter      for (i=0 ; i<end ; i++){        t1 = (_ftype_t)(i+1);        w[end-i-1] = w[*n-end+i] = _ftype_t(-1 * w[end-i-1] * sin(k1 * t1)/(M_PI * t1)); // Sinc        g += ((i&1) ? (2*w[end-i-1]) : (-2*w[end-i-1])); // Total gain in filter      }    }  }  if(type==TfirSettings::BANDPASS || type==TfirSettings::BANDSTOP){    fc1=fc[0];    fc2=limit(fc[1],_ftype_t(0.001),_ftype_t(1));    // Cutoff frequencies must be < 1.0 where 1.0 <=> Fs/2    fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25f;    fc2 = ((fc2 <= 1.0) && (fc2 > 0.0)) ? fc2/2 : 0.25f;    k3  = k1 * fc2; // 2*pi*fc2    k1 *= fc1;      // 2*pi*fc1    if(type==TfirSettings::BANDPASS){ // Band pass      // Calculate center tap      if (o){        g=w[end]*(fc1+fc2);        w[end] = (fc2 - fc1) * w[end] * 2.0f;      }      // Create filter      for (i=0 ; i<end ; i++){        t1 = (_ftype_t)(i+1) - k2;        t2 = _ftype_t(sin(k3 * t1)/(M_PI * t1)); // Sinc fc2        t3 = _ftype_t(sin(k1 * t1)/(M_PI * t1)); // Sinc fc1        g += w[end-i-1] * (t3 + t2);   // Total gain in filter        w[end-i-1] = w[*n-end+i] = w[end-i-1] * (t2 - t3);       }    }          else{ // Band stop      //if (!o) // Band stop filters must have odd length      //  return -1;      w[end] = _ftype_t(1.0 - (fc2 - fc1) * w[end] * 2.0);      g= w[end];      // Create filter      for (i=0 ; i<end ; i++){        t1 = (_ftype_t)(i+1);        t2 = _ftype_t(sin(k1 * t1)/(M_PI * t1)); // Sinc fc1        t3 = _ftype_t(sin(k3 * t1)/(M_PI * t1)); // Sinc fc2        w[end-i-1] = w[*n-end+i] = w[end-i-1] * (t2 - t3);         g += 2*w[end-i-1]; // Total gain in filter      }    }  }  // Normalize gain  g=1/g;  for (i=0; i<*n; i++)     w[i] *= g;    return w;}float TfirFilter::vec_inner_prod_sse(const float *eax, const float *edi, int ecx){  __m128 xmm3,xmm4,xmm0,xmm1,xmm5,xmm6;  xorps (xmm3, xmm3);  xorps (xmm4, xmm4);  ecx-=8;// sub $8, %%ecx  if (ecx<0) goto //jb   mul8_skip;mul8_loop:  movups (xmm0,eax);  movups (xmm1,edi);  movups (xmm5,16/sizeof(float)+eax);  movups (xmm6,16/sizeof(float)+edi);  eax+=32/sizeof(float);  edi+=32/sizeof(float);  mulps (xmm1,xmm0);  mulps (xmm6,xmm5);  addps (xmm3,xmm1);  addps (xmm4,xmm6);  ecx-=8;  if (ecx>=0) //jae   goto mul8_loop;mul8_skip:  addps (xmm3,xmm4);  ecx+=4;  if (ecx<0) //jl   goto mul4_skip;  movups (xmm0,eax);  movups (xmm1,edi);  eax+=16/sizeof(float);  edi+=16/sizeof(float);  mulps (xmm1, xmm0);  addps (xmm3, xmm1);  ecx-=4;mul4_skip:  ecx+=4;  goto cond1;mul1_loop:  movss (xmm0,eax);  movss (xmm1,edi);  eax+=4/sizeof(float);  edi+=4/sizeof(float);  mulss (xmm1,xmm0);  addss (xmm3,xmm1);cond1:  ecx-=1;  if (ecx>=0) // jae   goto mul1_loop;  movhlps  (xmm4,xmm3);  addps    (xmm3,xmm4);  movaps   (xmm4,xmm3);  //FIXME: which one?  xmm4=_mm_shuffle_ps(xmm4,xmm4,0x55);// shufps $0x55, xmm4, xmm4                                      // shufps $33, xmm4, xmm4  addss    (xmm3, xmm4);  float sum;  movss    (&sum , xmm3);  return sum;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -