# fili

• fili

## Stats

StarsIssuesVersionUpdatedCreatedSize
fili
2.0.34 years ago8 years ago

fili

A digital filter library for JavaScript.

## Installation

``\$ npm install fili``

## Usage

##### Node
``````var Fili = require('fili');

##### Browser
1. Copy `./dist/fili.min.js` into your working directory

```html ```
1. Use `Fili` in your application

```js var iirCalculator = new Fili.CalcCascades(); // ... ```

## API

### Generate IIR Filters with bilinear transform

IIR filters are composed of n Biquad filters. The Biquad filters need a and b coefficients to work. So, they have a backward and a forward path. Possible filters are:
• lowpass

• highpass

• bandpass

• bandstop

• peak

• lowshelf

• highshelf

• aweighting

Possible characteristics are:
• bessel

• butterworth

Note: for peak, lowshelf and highshelf a gain attribute must be defined when generating the coefficients. Gain can be positive or negative and represents the dB value for the peak or dip.
``````//  Instance of a filter coefficient calculator

// get available filters
var availableFilters = iirCalculator.available();

// calculate filter coefficients
var iirFilterCoeffs = iirCalculator.lowpass({
characteristic: 'butterworth',
Fs: 1000, // sampling frequency
Fc: 100, // cutoff frequency / center frequency for bandpass, bandstop, peak
BW: 1, // bandwidth only for bandstop and bandpass filters - optional
gain: 0, // gain for peak, lowshelf and highshelf
preGain: false // adds one constant multiplication for highpass and lowpass
// k = (1 + cos(omega)) * 0.5 / k = 1 with preGain == false
});

// create a filter instance from the calculated coeffs
var iirFilter = new Fili.IirFilter(filterCoeffs);``````

### Generate IIR Filters with matched-z transform

IIR filters are composed of n Biquad filters. The Biquad filters need only a coefficients to work. So, they have a backward but no forward path. Possible filters are:
• lowpass

Possible characteristics are:
• bessel

• butterworth

• allpass

• tschebyscheff05

• tschebyscheff1

• tschebyscheff2

• tschebyscheff3

Note: The number behind tschebyscheff defines the passband ripple.
``````// calculate filter coefficients
var iirFilterCoeffs = iirCalculator.lowpass({
characteristic: 'tschebyscheff3',
transform: 'matchedZ',
Fs: 1000, // sampling frequency
Fc: 100, // cutoff frequency / center frequency for bandpass, bandstop, peak
preGain: false // uses k when true for gain correction b[0] otherwise
});``````

### Generate FIR Filters

FIR filter calculation is done with a windowed sinc function Possible filters are:
• lowpass
• highpass
• bandpass
• bandstop

``````//  Instance of a filter coefficient calculator
var firCalculator = new Fili.firCoeffs();

// calculate filter coefficients
var firFilterCoeffs = firCalculator.lowpass({
order: 100, // filter order
Fs: 1000, // sampling frequency
Fc: 100 // cutoff frequency
// forbandpass and bandstop F1 and F2 must be provided instead of Fc
});

// filter coefficients by Kaiser-Bessel window
var firFilterCoeffsK = firCalculator.kbFilter({
order: 101, // filter order (must be odd)
Fs: 1000, // sampling frequency
Fa: 50, // rise, 0 for lowpass
Fb: 100, // fall, Fs/2 for highpass
Att: 100 // attenuation in dB
});

// create a filter instance from the calculated coeffs
var firFilter = new Fili.FirFilter(filterCoeffs);``````

### Run Filter

``````// run the filter with 10 samples from a ramp
// returns single value
for (var cnt = 0; cnt < 10; cnt++) {
console.log(filter.singleStep(cnt));
}

// run the filter from input array
// returns array
console.log(filter.multiStep([1,10,-5,3,1.112,17]));

// simulate the filter
// does not change the internal state
// returns array
console.log(filter.simulate([-3,-2,-1,5,6,33]));``````

### Evaluate Filter

``````// get the filter impact on magnitude, phase, unwrapped phase, phase delay and group delay
// returns array of n objects
// Fs = 1000 n = 100, so the array represents 0Hz, 10Hz, 20Hz....
// returns array of objects
// {dBmagnitude: -4, groupDelay: 2, magnitude: 0, phase: -7, phaseDelay: 12, unwrappedPhase: 7}
var response = filter.response(100);

// get the filter impact on magnitude, phase, unwrapped phase, phase delay and group delay
// for a defined frequency
// returns one object
var responsePoint = filter.responsePoint({
Fs: 1000,  // sampling frequency
Fr: 123 // frequency of interest
});``````

### Evaluate stability

``````// initialize filter for testing
// note: changes internal state of filter -> create a new filter from
// the calculated coefficients for evaluation
var filterTester = new Fili.FilterTester(testFilter);

// check if filter is stable for the specified input range
// returns true for stable filter
var stable = filterTester.directedRandomStability({
steps: 10000, // filter steps per test
tests: 100, // numbers of tests (random, ramp, impulses, steps)
offset: 5, // offset of input
pp: 10, // peak to peak of input
maxStable: 20, // values over this border will be considered as unstable
minStable: -10, // values under this border will be considered as unstable
setup: 1000 // steps until initial setup of filter is complete
});``````

### Calculate FFT

An FFT is always useful to evaluate filter responses. The algorithm uses precalculated twiddle factors and a lookup table for sine and cosine values. It also reuses all calculation buffers and precalculated window functions. This minimizes garbage collection and improves calculation speed.
Generate a new FFT calculator:
``````// Fft radix must be 2^n
var fft = new Fili.Fft(8192);``````

Frequency<--->Time Domain:
``````var buffer = [];
for (var cnt = 0; cnt < 8192; cnt++) {
buffer.push(cnt);
}

// Supported window functions are
// none, hanning, hamming, rectangular
// tukery, cosine, lanczos,
// triangular, bartlett, gaussian,
// bartlettHanning, blackman, blackmanHarris,
// nuttall3, nuttall3a, nuttall3b,
// nuttall4, nuttall4a, nuttall4b, nuttall4c
// sft3f, sft4f, sft5f, sft3m, sft4m, sft5m
// nift, hpft, srft, hft70, hft95, hft90d
// hft116d, hft144d, hft196d, hft223d, hft248d

// get available window functions
var availableWindows = fft.windows();

// buffer.length must be greater or equal fft radix
var fftResult = fft.forward(buffer, 'hanning');

// fftResult = {re: [], im: []}. The array length equals the FFT radix

var magnitude = fft.magnitude(fftResult); // magnitude
var dB = fft.magToDb(magnitude); // magnitude in dB
var phase = fft.phase(fftResult); // phase

// Note: magnitude, dB and phase are arrays.
// The length equals the FFT radix.
// For exact phase evaluation, the phase must be unwrapped.

var originalBuffer = fft.inverse(fftResult.re, fftResult.im);``````

## Test

``\$ make test``