FunctionFrequency filtering
Syntax C/C++#include <VFstd.h>
void VF_filter(fVector Y, fVector X, fVector Flt, ui size );
void VFb_filter(fVector Y, fVector X, fVector Flt, ui size, fVector Buf );
C++ VecObj#include <OptiVec.h>
void vector<T>::filter( const vector<T>& X, const vector<T>& Flt );
void vector<T>::b_filter( const vector<T>& X, const vector<T>& Flt, vector<T>& Buf );
Pascal/Delphiuses VFstd;
procedure VF_filter( Y, X, Flt:fVector; size:UIntSize );
procedure VFb_filter( Y, X, Flt:fVector; size:UIntSize; Buf:fVector );
CUDA function C/C++#include <cudaVFstd.h>
int cudaVF_filter(fVector d_Y, fVector d_X, fVector d_Flt, ui size );
void VFcu_filter(fVector h_Y, fVector h_X, fVector h_Flt, ui size );
CUDA function Pascal/Delphiuses VFstd;
function cudaVF_filter( d_Y, d_X, d_Flt:fVector; size:UIntSize ): IntBool;
procedure VFcu_filter( h_Y, h_X, h_Flt:fVector; size:UIntSize );
DescriptionA frequency filter Flt is applied to the vector X. Internally, this is done by performing a Fourier transform on X, multiplying the transform with Flt and transforming the product back into the time domain.

Complex versions: X, Y and the filter Flt are complex vectors.
Real versions: X and Y are real. Flt has to be in the packed complex format that is obtained by Fourier transforming a real vector with VF_FFT (see that function for the description of the packed complex format) or by using VF_convolve.

Internally, VF_filter allocates and frees additional workspace memory. For repeated calls, this would be inefficient. In such a case, it is recommended to use VFb_filter instead. The size of Buf must be ≥ size. Additionally, Buf must be 128-bit (P8) or 256-bit (P9) aligned. This usually means you can only take a vector allocated by the VF_vector family as Buf.

For purely real filter functions known analytically, construct your filter by first evaluating it for a real vector of size/2+1 elements, and subsequently copy this real vector into Flt, as in the following example (fNyquist = 0.5 / sampling_interval; the desired cutoff frequency is fCutOff):

Example C/C++:float Coeffs[3] = {1.0, 1.4142135, 1.0};
fVector Flt = VF_vector0( size );
fVector RealFlt = VF_vector( size/2+1 );
fVector Freq = VF_vector( size/2+1 );
VF_ramp( Freq, size/2+1, 0, (fNyquist / fCutOff) / (size/2) );
    /* reduced frequencies from 0 to fNyquist / fCutOff */
VF_poly( RealFlt, Freq, size/2+1, Coeffs, 2 );
VF_inv( RealFlt, RealFlt, size/2+1 );
    /*  calc. response from coeffs of this 2nd order filter */
VF_RetoC( (cfVector)Flt, RealFlt, size/2 );
    /* the imaginary elements remain 0 */
Flt[1] = RealFlt[ size/2 ]; /* response at Nyquist frequency */
VF_filter( Y, X, Flt, size ); /* apply the just constructed filter */

The same example for Pascal/Delphi:const Coeffs: array[0..2] of Single = (1.0, 1.4142135, 1.0);
var Flt, RealFlt, Freq: fVector;
    size_2: UIntSize;
  size_2 := size div 2;
  Flt := VF_vector0( size );
  RealFlt := VF_vector( size_2+1 );
  Freq := VF_vector( size_2+1 );
  VF_ramp( Freq, size_2+1, 0, (fNyquist / fCutOff) / (size_2) );
      (* reduced frequencies from 0 to fNyquist / fCutOff *)
  VF_poly( RealFlt, Freq, size_2+1, @Coeffs, 2 );
  VF_inv( RealFlt, RealFlt, size_2+1 );
      (*  calc. response from coeffs of this 2nd order filter *)
  VF_RetoC( cfVector(Flt), RealFlt, size_2 );
      (* the imaginary elements remain 0 *)
  VF_Pelement( Flt, 1 )^ := VF_element( RealFlt, size_2 );
      (* response at Nyquist frequency *)
  VF_filter( Y, X, Flt, size ); (* apply the just constructed filter *)

If X is non-periodic, both ends of the filtered function may be spoiled by wrap-around. See VF_convolve about how to avoid end-effects by embedding X in a larger vector or by removing a possible linear trend.

Error handlingIf size is not a power of 2, VF_FFT (on which VF_filter is based) complains "Size must be an integer power of 2" and the program is aborted.
Return valuenone
See alsoVF_FFT,   VF_convolve,   VF_autocorr,   VF_xcorr,   VF_spectrum,   VF_smooth,   VF_biquad

VectorLib Table of Contents  OptiVec home