VF_filter | VD_filter | VE_filter |
VCF_filter | VCD_filter | VCE_filter |
VFb_filter | VDb_filter | VEb_filter |
VCFb_filter | VCDb_filter | VCEb_filter |
|
Function | Frequency 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/Delphi | uses 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/Delphi | uses 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 );
|
|
Description | A 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;
begin
...
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 *)
end;
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 handling | If 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. |
|
|
|